diff --git a/aql/convertQuery.go b/aql/convertQuery.go index 9e17331b05bea5e565b0b63b8c4ea67fd84b55a5..852571cc31f7b0c04f83a5cf8b6a6a9814adab07 100644 --- a/aql/convertQuery.go +++ b/aql/convertQuery.go @@ -7,6 +7,8 @@ import ( "git.science.uu.nl/datastrophe/query-conversion/entity" ) +// Version 1.13 + /* ConvertQuery converts an IncomingQueryJSON object into AQL JSONQuery: *entity.IncomingQueryJSON, the query to be converted to AQL @@ -69,6 +71,33 @@ func createQuery(JSONQuery *entity.IncomingQueryJSON) *string { // Loop over all relations ret := "" + // Add a WITH statement for entityTo + includedTypes := make(map[string]bool) + allTypes := make(map[string]bool) + for _, relation := range JSONQuery.Relations { + if relation.EntityFrom >= 0 { + includedTypes[JSONQuery.Entities[relation.EntityFrom].Type] = true + allTypes[JSONQuery.Entities[relation.EntityFrom].Type] = true + + // If the type is in the entityTo it is a valid type but not yet included + if relation.EntityTo >= 0 { + allTypes[JSONQuery.Entities[relation.EntityTo].Type] = true + } + } + if relation.EntityFrom == -1 && relation.EntityTo >= 0 { + includedTypes[JSONQuery.Entities[relation.EntityTo].Type] = true + allTypes[JSONQuery.Entities[relation.EntityTo].Type] = true + } + } + + // Include all types that are not yet included + for k := range allTypes { + if !includedTypes[k] { + ret += fmt.Sprintf("WITH %v\n", k) + + } + } + for i, relation := range JSONQuery.Relations { relationName := fmt.Sprintf("r%v", i) @@ -250,11 +279,6 @@ func createRelationLetWithFromEntity(relation *entity.QueryRelationStruct, name // If there is a to-node, generate the filter statement toConstraints := (*entities)[relation.EntityTo].Constraints vFilterStmnt += *createConstraintStatements(&toConstraints, "v", false) - - // Add a WITH statement if the collection of entityTo is not yet included - if (*entities)[(*relation).EntityFrom].Type != (*entities)[(*relation).EntityTo].Type { - header = fmt.Sprintf("%v\n\tWITH %v", header, (*entities)[(*relation).EntityTo].Type) - } } relationFilterStmnt := *createConstraintStatements(&relation.Constraints, "p", true) diff --git a/aql/convertQuery_test.go b/aql/convertQuery_test.go index 6d5a72a1d19fcfe87d4c0f614c86e5cfcff7aeeb..35ad9ff4b5a3102500f1ad48dbb4df4eb724045a 100644 --- a/aql/convertQuery_test.go +++ b/aql/convertQuery_test.go @@ -41,6 +41,80 @@ LET edges = first(RETURN UNION_DISTINCT([],[])) RETURN {"vertices":nodes, "edges":edges }` assert.Equal(t, correctConvertedResult, *convertedResult) } +func TestMultipleEntityTypes(t *testing.T) { + // Setup for test + // Create query conversion service + service := NewService() + + query := []byte(`{ + "databaseName": "test", + "return": { + "entities": [ + 0, + 1 + ], + "relations": [ + 0 + ] + }, + "entities": [ + { + "type": "kamerleden", + "constraints": [ + { + "attribute": "partij", + "value": "GL", + "dataType": "text", + "matchType": "exact" + } + ] + }, + { + "type": "partijen", + "constraints": [ + { + "attribute": "zetels", + "value": "6", + "dataType": "number", + "matchType": "GT" + } + ] + } + ], + "relations": [ + { + "type": "lid_van", + "depth": { + "min": 1, + "max": 1 + }, + "entityFrom": 0, + "entityTo": 1, + "constraints": [] + } + ], + "limit": 5000, + "modifiers": [] + }`) + + // Unmarshall the incoming message into an IncomingJSONQuery object + var JSONQuery entity.IncomingQueryJSON + json.Unmarshal(query, &JSONQuery) + + convertedResult, err := service.ConvertQuery(&JSONQuery) + + // Assert that there is no error + assert.NoError(t, err) + + // Assert that the result and the expected result are the same + correctConvertedResult := "WITH partijen\nLET n0 = (\n\tFOR x IN kamerleden \n\tFILTER x.partij == \"GL\" \n\tRETURN x\n)\nLET r0 = (\n\tFOR x IN n0 \n\tFOR v, e, p IN 1..1 OUTBOUND x lid_van \n\tOPTIONS { uniqueEdges: \"path\" }\n\tFILTER v.zetels > 6 \n\tLIMIT 5000 \nRETURN DISTINCT p )\n\nLET nodes = first(RETURN UNION_DISTINCT(flatten(r0[**].vertices), [],[]))\nLET edges = first(RETURN UNION_DISTINCT(flatten(r0[**].edges), [],[]))\nRETURN {\"vertices\":nodes, \"edges\":edges }" + cleanedResult := strings.ReplaceAll(correctConvertedResult, "\n", "") + cleanedResult = strings.ReplaceAll(cleanedResult, "\t", "") + convertedCleanedResult := strings.ReplaceAll(*convertedResult, "\n", "") + convertedCleanedResult = strings.ReplaceAll(convertedCleanedResult, "\t", "") + + assert.Equal(t, convertedCleanedResult, cleanedResult) +} func TestEntityOneAttributeQuery(t *testing.T) { // Setup for test