Skip to content

Commit

Permalink
feat(graphql): can expand into the fields of subclasses
Browse files Browse the repository at this point in the history
  • Loading branch information
mswertz committed Jan 22, 2024
1 parent 7c5ab5a commit 1b106be
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private GraphQLNamedOutputType createTableObjectType(TableMetadata table) {
tableTypes.put(tableObjectType, GraphQLTypeReference.typeRef(tableObjectType));
// build the object
GraphQLObjectType.Builder tableBuilder = GraphQLObjectType.newObject().name(tableObjectType);
for (Column col : table.getColumnsWithoutHeadings()) {
for (Column col : table.getColumnsIncludingSubclassesExcludingHeadings()) {
String id = col.getIdentifier();
switch (col.getColumnType().getBaseType()) {
case HEADING:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.molgenis.emx2.graphql;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.molgenis.emx2.Column.column;
import static org.molgenis.emx2.Row.row;
import static org.molgenis.emx2.TableMetadata.table;
import static org.molgenis.emx2.graphql.GraphqlApiFactory.convertExecutionResultToJson;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import java.io.IOException;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.molgenis.emx2.ColumnType;
import org.molgenis.emx2.Database;
import org.molgenis.emx2.MolgenisException;
import org.molgenis.emx2.Schema;
import org.molgenis.emx2.sql.TestDatabaseFactory;
import org.molgenis.emx2.tasks.TaskService;
import org.molgenis.emx2.tasks.TaskServiceInMemory;

public class TestTableQueriesWithInheritance {
private static final String schemaName = TestTableQueriesWithInheritance.class.getSimpleName();
private static GraphQL grapql;
private static Database database;
private static TaskService taskService;
private static Schema schema;

@BeforeAll
public static void setup() {
database = TestDatabaseFactory.getTestDatabase();
schema = database.dropCreateSchema(schemaName);
schema.create(table("Person", column("name").setPkey()));
schema.create(
table("Employee", column("salary").setType(ColumnType.INT)).setInheritName("Person"));
schema.getTable("Employee").insert(row("name", "pooky", "salary", 1000));
taskService = new TaskServiceInMemory();
grapql = new GraphqlApiFactory().createGraphqlForSchema(schema, taskService);
}

@Test
public void testQueriesIncludingSubclassColumns() throws IOException {
JsonNode result =
execute(
"{Person{name,salary}}"); // note, Person.salary doesn't exist, but Employee.salary does
assertEquals(1000, result.at("/Person/0/salary").asInt());
}

private JsonNode execute(String query) throws IOException {
String result = convertExecutionResultToJson(grapql.execute(query));
JsonNode node = new ObjectMapper().readTree(result);
if (node.get("errors") != null) {
throw new MolgenisException(node.get("errors").get(0).get("message").asText());
}
return new ObjectMapper().readTree(result).get("data");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,6 @@ else if (col.getColumnType().isArray()) {
}

private static Table<org.jooq.Record> tableWithInheritanceJoin(TableMetadata table) {

Table<org.jooq.Record> result = table.getJooqTable();
TableMetadata inheritedTable = table.getInheritedTable();
// root and intermediate levels have mg_tableclass column
Expand All @@ -851,6 +850,12 @@ private static Table<org.jooq.Record> tableWithInheritanceJoin(TableMetadata tab
mg_tableclass = inheritedTable.getLocalColumn(MG_TABLECLASS);
}
}
// join subclass tables also (todo: can we make this less expensive?)
for (TableMetadata subclassTable : table.getSubclassTables()) {
List<Field<?>> using = subclassTable.getPrimaryKeyFields();
result = result.join(subclassTable.getJooqTable()).using(using.toArray(new Field<?>[0]));
}

return result;
}

Expand Down Expand Up @@ -1381,10 +1386,10 @@ private static Column getColumnByName(TableMetadata table, String columnName) {
return new Column(table, searchColumnName(table.getTableName()));
}
// is scalar column
Column column = table.getColumn(columnName);
Column column = table.getColumnIncludingSubclasses(columnName);
if (column == null) {
// is reference?
for (Column c : table.getColumns()) {
for (Column c : table.getColumnsIncludingSubclasses()) {
if (c.isReference()) {
for (Reference ref : c.getReferences()) {
// can also request composite reference columns, can only be used on row level queries
Expand All @@ -1395,7 +1400,7 @@ private static Column getColumnByName(TableMetadata table, String columnName) {
}
}
// is file?
for (Column c : table.getColumns()) {
for (Column c : table.getColumnsIncludingSubclasses()) {
if (c.isFile()
&& columnName.startsWith(c.getName())
&& (columnName.equals(c.getName())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,4 +583,43 @@ public String getDescription() {
return null;
}
}

public List<Column> getColumnsIncludingSubclasses() {
// get all tables in current schema that inherit this
List<Column> result = new ArrayList<>();
result.addAll(this.getColumns());
result.addAll(getColumnsFromSubclasses());
return result;
}

public List<Column> getColumnsIncludingSubclassesExcludingHeadings() {
return getColumnsIncludingSubclasses().stream().filter(c -> !c.isHeading()).toList();
}

private List<Column> getColumnsFromSubclasses() {
List<Column> result = new ArrayList<>();
for (TableMetadata table : getSubclassTables()) {
result.addAll(table.getLocalColumns());
result.addAll(table.getColumnsFromSubclasses());
}
return result;
}

public Column getColumnIncludingSubclasses(String columnName) {
return getColumnsIncludingSubclasses().stream()
.filter(c -> c.getName().equals(columnName))
.findFirst()
.orElseGet(() -> null);
}

public List<TableMetadata> getSubclassTables() {
List<TableMetadata> result = new ArrayList();
for (TableMetadata table : getSchema().getTables()) {
if (this.getTableName().equals(table.getInheritName())) {
result.add(table);
result.addAll(table.getSubclassTables());
}
}
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.molgenis.emx2;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.molgenis.emx2.Column.column;
import static org.molgenis.emx2.TableMetadata.table;

import java.util.List;
import org.junit.jupiter.api.Test;

public class TestTableMetadata {
@Test
void testGetColumnsFromSubclasses() {
SchemaMetadata s =
new SchemaMetadata()
.create(
table("Person", column("name")),
table("Employee", column("details").setType(ColumnType.HEADING), column("salary"))
.setInheritName("Person"));

List<Column> result = s.getTableMetadata("Person").getColumnsIncludingSubclasses();
assertEquals(3, result.size());

Column salary = result.get(2);
assertEquals("salary", salary.getName());
assertEquals("Employee", salary.getTableName());

result = s.getTableMetadata("Person").getColumnsIncludingSubclassesExcludingHeadings();
assertEquals(2, result.size());
}
}

0 comments on commit 1b106be

Please sign in to comment.