Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove jsonb_array and fix jsonb data types such that it can be used in schema design and graphql api #4409

Merged
merged 35 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4cd9812
fix: remove jsonb_array type
mswertz Oct 29, 2024
5ba651b
fix: remove jsonb_array type
mswertz Oct 29, 2024
adfd5d1
fix tests
mswertz Oct 29, 2024
fe90ef7
Merge branch 'master' into fix/remove_json_array
mswertz Nov 4, 2024
3238649
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 6, 2024
69aa6bd
wip
mswertz Nov 6, 2024
917fdb6
undo|
mswertz Nov 6, 2024
8889644
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 6, 2024
02141e3
add jsonb to graphql api
mswertz Nov 6, 2024
41443eb
many fixes for the proper json passing
mswertz Nov 6, 2024
16dcee1
fix test
mswertz Nov 6, 2024
e5bedd1
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 7, 2024
8e20cad
add test
mswertz Nov 7, 2024
ea0c91a
Merge branch 'master' into fix/remove_json_array
mswertz Nov 11, 2024
3c1aa07
merged
mswertz Nov 15, 2024
092c9d2
Merge branch 'master' of github.com:molgenis/molgenis-emx2 into fix/r…
mswertz Nov 18, 2024
d5dd710
expand test coverage
mswertz Nov 18, 2024
59b7b78
Merge branch 'master' into fix/remove_json_array
mswertz Nov 18, 2024
fc50cf2
remove unused code
mswertz Nov 18, 2024
8f34bdb
merge
mswertz Nov 19, 2024
5febc75
Merge branch 'master' into fix/remove_json_array
svandenhoek Nov 25, 2024
da8e178
Updated code from #4323 to be compatible with this branch
svandenhoek Nov 25, 2024
3755cbd
updated docs
svandenhoek Nov 25, 2024
2188e18
generalized GraphqlCustomTypes in switch
svandenhoek Nov 25, 2024
8414b94
serialize should only throw a CoercingSerializeException (https://www…
svandenhoek Nov 25, 2024
c7ddff2
Updated toJsonb to include full validation
svandenhoek Nov 25, 2024
dad3e7f
Improved JSON validation (no trailing data, duplicate check)
svandenhoek Nov 25, 2024
e3d1243
auto-formatting
svandenhoek Nov 25, 2024
996dfe1
WIP: front-end validation
svandenhoek Nov 26, 2024
d0833c6
Added tests
svandenhoek Nov 26, 2024
150161c
fixes null giving wrong front-end error message
svandenhoek Nov 26, 2024
70f505f
fixed comments
svandenhoek Nov 26, 2024
d2e2d76
more comment fixes
svandenhoek Nov 26, 2024
ff6cdbf
processed feedback
svandenhoek Nov 26, 2024
83f7eec
formatting
svandenhoek Nov 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions apps/metadata-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export type CellValueType =
| "DATETIME"
| "DATETIME_ARRAY"
| "PERIOD"
| "JSONB"
| "JSONB_ARRAY"
| "JSON"
| "REF"
| "REF_ARRAY"
| "REFBACK"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const filterTypeMap = {
HYPERLINK_ARRAY: StringFilter,
TEXT: StringFilter,
TEXT_ARRAY: StringFilter,
JSON: StringFilter,
UUID: StringFilter,
UUID_ARRAY: StringFilter,
INT: IntegerFilter,
Expand Down
13 changes: 13 additions & 0 deletions apps/molgenis-components/src/components/forms/FormInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const typeToInputMap = {
HYPERLINK: InputHyperlink,
STRING: InputString,
TEXT: InputText,
JSON: InputText,
INT: InputInt,
LONG: InputLong,
DECIMAL: InputDecimal,
Expand Down Expand Up @@ -364,6 +365,17 @@ export default {
</div>
<div>You typed: {{ JSON.stringify(textValueArray, null, 2) }}</div>
</DemoItem>
<DemoItem>
<div>
<FormInput
id="json-example"
columnType="JSON"
label="Example json input"
v-model="jsonValue"
/>
</div>
<div>You typed: {{ jsonValue }}</div>
</DemoItem>
<DemoItem>
<div>
<FormInput
Expand Down Expand Up @@ -536,6 +548,7 @@ export default {
intValueArray: [5, 37],
textValue: "example text",
textValueArray: ["text", "more text"],
jsonValue: '{"name":"bofke"}',
longValue: "1337",
longValueArray: ["0", "101"],
decimalValue: 3.7,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import HyperlinkDisplay from "./cellTypes/HyperlinkDisplay.vue";
const typeMap: { [key: string]: string } = {
FILE: "FileDisplay",
TEXT: "TextDisplay",
JSON: "TextDisplay",
REFBACK: "ListDisplay",
REF: "ObjectDisplay",
ONTOLOGY: "ObjectDisplay",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,8 @@ function graphqlFilter(
if (conditions.length) {
if (
col.columnType.startsWith("STRING") ||
col.columnType.startsWith("TEXT")
col.columnType.startsWith("TEXT") ||
col.columnType.startsWith("JSON")
) {
filter[col.id] = { like: conditions };
} else if (col.columnType.startsWith("BOOL")) {
Expand Down
1 change: 1 addition & 0 deletions apps/schema/src/columnTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default [
"HYPERLINK_ARRAY",
"INT",
"INT_ARRAY",
"JSON",
"LONG",
"LONG_ARRAY",
"ONTOLOGY",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,58 @@
package org.molgenis.emx2.graphql;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.schema.*;
import jakarta.servlet.http.Part;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import org.molgenis.emx2.BinaryFileWrapper;
import org.molgenis.emx2.MolgenisException;

public class GraphqlCustomTypes {
private static final ObjectMapper objectMapper = new ObjectMapper();

private GraphqlCustomTypes() {
// hide constructor
}

public static final GraphQLScalarType GraphQLJsonAsString =
GraphQLScalarType.newScalar()
.name("JsonString")
.description("A JSON represented as string")
.coercing(
new Coercing<String, String>() {

@Override
public String serialize(Object dataFetcherResult) {
// Convert Java object to JSON string
try {
return objectMapper.writeValueAsString(dataFetcherResult);
} catch (JsonProcessingException e) {
throw new MolgenisException(
"Unable to serialize to JSON string: " + e.getMessage());
}
}

@Override
public String parseValue(Object input) {
// Pass-through parsing (only used for input values)
return input.toString();
}

@Override
public String parseLiteral(Object input) {
// Pass-through literal parsing
if (input instanceof graphql.language.StringValue) {
return ((graphql.language.StringValue) input).getValue();
}
throw new CoercingParseLiteralException("Value is not a valid JSON string");
}
})
.build();

// thanks to https://stackoverflow.com/questions/57372259/how-to-upload-files-with-graphql-java
public static final GraphQLScalarType GraphQLFileUpload =
GraphQLScalarType.newScalar()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import static org.molgenis.emx2.graphql.GraphqlApiMutationResult.Status.SUCCESS;
import static org.molgenis.emx2.graphql.GraphqlApiMutationResult.typeForMutationResult;
import static org.molgenis.emx2.graphql.GraphqlConstants.*;
import static org.molgenis.emx2.graphql.GraphqlCustomTypes.GraphQLJsonAsString;
import static org.molgenis.emx2.sql.SqlQuery.*;

import graphql.Scalars;
Expand Down Expand Up @@ -187,6 +188,10 @@ private void createTableField(Column col, GraphQLObjectType.Builder tableBuilder
tableBuilder.field(
GraphQLFieldDefinition.newFieldDefinition().name(id).type(Scalars.GraphQLString));
break;
case JSON:
tableBuilder.field(
GraphQLFieldDefinition.newFieldDefinition().name(id).type(GraphQLJsonAsString));
break;
case STRING_ARRAY:
case EMAIL_ARRAY:
case HYPERLINK_ARRAY:
Expand All @@ -196,7 +201,6 @@ private void createTableField(Column col, GraphQLObjectType.Builder tableBuilder
case DATETIME_ARRAY:
case PERIOD_ARRAY:
case UUID_ARRAY:
case JSONB_ARRAY:
tableBuilder.field(
GraphQLFieldDefinition.newFieldDefinition()
.name(id)
Expand Down Expand Up @@ -507,6 +511,8 @@ private GraphQLScalarType graphQLTypeOf(Column col) {
return GraphQLLong;
case DECIMAL, DECIMAL_ARRAY:
return Scalars.GraphQLFloat;
case JSON:
return GraphQLJsonAsString;
case DATE,
DATETIME,
PERIOD,
Expand Down Expand Up @@ -908,6 +914,7 @@ private GraphQLInputType getGraphQLInputType(ColumnType columnType) {
case INT_ARRAY -> GraphQLList.list(Scalars.GraphQLInt);
case LONG_ARRAY -> GraphQLList.list(GraphQLLong);
case DECIMAL_ARRAY -> GraphQLList.list(Scalars.GraphQLFloat);
case JSON -> GraphQLJsonAsString;
case STRING_ARRAY,
TEXT_ARRAY,
DATE_ARRAY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,48 @@ public void testTableType() throws IOException {
assertEquals("ONTOLOGIES", result.at("/_schema/tables/3/tableType").asText());
}

@Test
public void testJsonType() throws IOException {
try {
Schema myschema = database.dropCreateSchema("testJsonType");
myschema.create(
table("TestJson", column("name").setPkey(), column("json").setType(ColumnType.JSON)));

grapql = new GraphqlApiFactory().createGraphqlForSchema(myschema, taskService);

Table table = myschema.getTable("TestJson");
String value = "{\"name\":\"bofke\"}";
table.insert(row("name", "test", "json", value));

assertEquals(value, execute("{TestJson{json}}").at("/TestJson/0/json").asText());

String value2 = "{\"name\":\"bofke2\"}";
Map data = new LinkedHashMap();
data.put("name", "test");
data.put("json", value2);
grapql.execute(
new ExecutionInput.Builder()
.query("mutation update($value:[TestJsonInput]){update(TestJson:$value){message}}")
.variables(Map.of("value", data))
.build());

assertEquals(value2, execute("{TestJson{json}}").at("/TestJson/0/json").asText());
assertEquals(
value2,
execute(
"{TestJson(filter:{json:{equals:\"{\\\"name\\\": \\\"bofke2\\\"}\"}}){json}}") // notice the extra space!
.at("/TestJson/0/json")
.asText());
assertEquals(
value2,
execute("{TestJson(filter:{json:{like:\"bofke2\"}}){json}}") // more useful
.at("/TestJson/0/json")
.asText());
} finally {
grapql = new GraphqlApiFactory().createGraphqlForSchema(schema, taskService);
}
}

@Test
public void testFileType() throws IOException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ private static String getEmx1Type(Column c) {
return "file";
case STRING, UUID:
return "varchar";
case TEXT, JSONB:
case TEXT, JSON:
return "text";
case INT:
return "int";
Expand All @@ -280,7 +280,6 @@ private static String getEmx1Type(Column c) {
INT_ARRAY,
DATE_ARRAY,
DATETIME_ARRAY,
JSONB_ARRAY,
DECIMAL_ARRAY:
return "array types unsupported in emx1: " + c.getColumnType();
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,7 @@ private CoreDatatype.XSD columnTypeToXSD(final ColumnType columnType) {
case EMAIL,
EMAIL_ARRAY,
HEADING,
JSONB,
JSONB_ARRAY,
JSON,
STRING,
STRING_ARRAY,
TEXT,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.molgenis.emx2.sql;

import static org.jooq.impl.DSL.*;
import static org.jooq.impl.SQLDataType.VARCHAR;
import static org.molgenis.emx2.Constants.*;
import static org.molgenis.emx2.Operator.*;
import static org.molgenis.emx2.Privileges.*;
Expand Down Expand Up @@ -1139,10 +1140,9 @@ private Condition whereCondition(
Object[] values) {
Name name = name(alias(tableAlias), columnName);
return switch (type) {
case TEXT, STRING, FILE -> whereConditionText(name, operator, toStringArray(values));
case TEXT, STRING, FILE, JSON -> whereConditionText(name, operator, toStringArray(values));
case BOOL -> whereConditionEquals(name, operator, toBoolArray(values));
case UUID -> whereConditionEquals(name, operator, toUuidArray(values));
case JSONB -> whereConditionEquals(name, operator, toJsonbArray(values));
case INT -> whereConditionOrdinal(name, operator, toIntArray(values));
case LONG -> whereConditionOrdinal(name, operator, toLongArray(values));
case DECIMAL -> whereConditionOrdinal(name, operator, toDecimalArray(values));
Expand All @@ -1159,7 +1159,6 @@ private Condition whereCondition(
case DATE_ARRAY -> whereConditionArrayEquals(name, operator, toDateArray(values));
case DATETIME_ARRAY -> whereConditionArrayEquals(name, operator, toDateTimeArray(values));
case PERIOD_ARRAY -> whereConditionArrayEquals(name, operator, toYearToSecondArray(values));
case JSONB_ARRAY -> whereConditionArrayEquals(name, operator, toJsonbArray(values));
case REF -> whereConditionRefEquals(name, operator, values);
default ->
throw new SqlQueryException(
Expand Down Expand Up @@ -1292,7 +1291,7 @@ private static Condition whereConditionText(
for (String value : values) {
switch (operator) {
case EQUALS:
conditions.add(field(columnName).eq(value));
conditions.add(field(columnName).cast(VARCHAR).eq(value)); // cast is for the json
break;
case NOT_EQUALS:
not = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,7 @@ public static Object getTypedValue(Column c, Row row) {
case DATETIME_ARRAY -> row.getDateTimeArray(name);
case PERIOD -> row.getPeriod(name);
case PERIOD_ARRAY -> row.getPeriodArray(name);
case JSONB -> row.getJsonb(name);
case JSONB_ARRAY -> row.getJsonbArray(name);
case JSON -> row.getJsonb(name);
default ->
throw new UnsupportedOperationException(
"Unsupported columnType found:" + c.getColumnType());
Expand Down Expand Up @@ -209,7 +208,7 @@ static String getPsqlType(ColumnType type) {
case DATE_ARRAY -> "date[]";
case DATETIME -> "timestamp without time zone";
case DATETIME_ARRAY -> "timestamp without time zone[]";
case JSONB -> "jsonb";
case JSON -> "jsonb";
default ->
throw new MolgenisException(
"Unknown type: Internal error: data cannot be mapped to psqlType " + type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,6 @@ public void testTextArray() {
});
}

@Test
public void testJSON() {
executeTest(
JSONB_ARRAY,
new String[] {"{\"key\":\"value1\"}", "{\"key\":\"value2\"}", "{\"key\":\"value3\"}"});
}

// @Test
// public void testBool() {
// executeTest(BOOL_ARRAY, new Boolean[] {null, true, false});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ public void testText() {
@Test
public void testJSON() {
executeTest(
JSONB,
new String[] {"{\"key\":\"value1\"}", "{\"key\":\"value2\"}", "{\"key\":\"value3\"}"});
JSON,
new String[] {"{\"key\": \"value1\"}", "{\"key\": \"value2\"}", "{\"key\": \"value3\"}"});
}

private void executeTest(ColumnType columnType, Serializable[] values) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void testUUID() {

@Test
public void testJSON() {
executeTest(JSONB, "{\"key\": \"value1\"}", "{\"key\": \"value2\"}");
executeTest(JSON, "{\"key\": \"value1\"}", "{\"key\": \"value2\"}");
}

private void executeTest(ColumnType columnType, Object insertValue, Object updateValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,6 @@ public void testTextRef() {
});
}

@Test
public void testJSONRef() {
executeTest(
ColumnType.JSONB,
new String[] {"{\"key\": \"value1\"}", "{\"key\": \"value2\"}", "{\"key\": \"value3\"}"});
}

private void executeTest(ColumnType columnType, Object[] testValues) {

Schema schema = db.dropCreateSchema("TestRefArray" + columnType.toString().toUpperCase());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public enum ColumnType {
STRING_ARRAY(String[].class, STRING_OPERATORS),
TEXT(String.class, STRING_OPERATORS),
TEXT_ARRAY(String[].class, STRING_OPERATORS),
JSON(org.jooq.JSONB.class, STRING_OPERATORS),

// NUMERIC
INT(Integer.class, ORDINAL_OPERATORS),
Expand All @@ -35,10 +36,6 @@ public enum ColumnType {
PERIOD(Period.class, ORDINAL_OPERATORS),
PERIOD_ARRAY(Period[].class, ORDINAL_OPERATORS),

// COMPOSITE
JSONB(org.jooq.JSONB.class),
JSONB_ARRAY(org.jooq.JSONB[].class),

// RELATIONSHIP
REF(Object.class),
REF_ARRAY(Object[].class),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,6 @@ public JSONB getJsonb(String name) {
return TypeUtils.toJsonb(values.get(name));
}

public JSONB[] getJsonbArray(String name) {
return TypeUtils.toJsonbArray(values.get(name));
}

public Row setString(String name, String value) {
this.values.put(name, value);
return this;
Expand Down Expand Up @@ -344,8 +340,6 @@ public <T> T get(String name, Class<T> type) {
return (T) getStringArray(name);
case "JSONB":
return (T) getJsonb(name);
case "JSONB[]":
return (T) getJsonbArray(name);
case "Integer":
return (T) getInteger(name);
case "Integer[]":
Expand Down
Loading