diff --git a/aql/convertQuery.go b/aql/convertQuery.go index 28303d7d6a98ddf1ae0c430cc814d5214de172cb..e518014191f837009c7d0e2dbc4d211464b53b26 100644 --- a/aql/convertQuery.go +++ b/aql/convertQuery.go @@ -79,39 +79,42 @@ createQuery generates a query based on the json file provided Return: *string, a string containing the corresponding AQL query and an error */ func createQuery(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, topNode entity.QueryEntityStruct) *string { - output := createLetFor("result", fmt.Sprintf("e_%v", topNode.ID), topNode.Name) + output := createLetFor("result", fmt.Sprintf("e_%v", topNode.ID), topNode.Name, 0) for constraint := range topNode.Constraints { output += createFilter(topNode.Constraints[constraint], fmt.Sprintf("e_%v", topNode.ID)) } - subQuery, subName := createQueryRecurse(JSONQuery, tree, 0, topNode) + subQuery, subName := createQueryRecurse(JSONQuery, tree, 0, topNode, 1) subNames := []string{subName} output += subQuery output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", topNode.ID))) output += createReturn(fmt.Sprintf("e_%v", topNode.ID), "", subNames) + output += ")\n" output += "let nodes = union_distinct(flatten(result[**].nodes),[])\nlet edges = union_distinct(flatten(result[**].rel),[])\nreturn {\"vertices\":nodes,\"edges\":edges}" return &output } -func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, currentindex int, topNode entity.QueryEntityStruct) (string, string) { +func createQueryRecurse(JSONQuery *entity.IncomingQueryJSON, tree []entity.Tree, currentindex int, topNode entity.QueryEntityStruct, indentindex int) (string, string) { currentTree := tree[currentindex] newNode := getTreeNewNode(currentTree, tree, topNode) - output := createLetFor(fmt.Sprintf("e%v", newNode.ID), fmt.Sprintf("e_%v", newNode.ID), newNode.Name) - output += fmt.Sprintf("FOR r%v IN %v", currentTree.Self.Rel.ID, currentTree.Self.Rel.Name) + output := "" + output += fixIndent(createLetFor(fmt.Sprintf("e%v", newNode.ID), fmt.Sprintf("e_%v", newNode.ID), newNode.Name, indentindex), indentindex) + output += fixIndent(fmt.Sprintf("\tFOR r%v IN %v\n", currentTree.Self.Rel.ID, currentTree.Self.Rel.Name), indentindex) for constraint := range newNode.Constraints { - output += createFilter(newNode.Constraints[constraint], fmt.Sprintf("e_%v", newNode.ID)) + output += fixIndent(createFilter(newNode.Constraints[constraint], fmt.Sprintf("e_%v", newNode.ID)), indentindex) } for constraint := range currentTree.Self.Rel.Constraints { - output += createFilter(currentTree.Self.Rel.Constraints[constraint], fmt.Sprintf("r%v", currentTree.Self.Rel.ID)) + output += fixIndent(createFilter(currentTree.Self.Rel.Constraints[constraint], fmt.Sprintf("r%v", currentTree.Self.Rel.ID)), indentindex) } - output += fmt.Sprintf("FILTER r%v._from == e_%v._id AND r%v._to == e_%v._id", currentTree.Self.Rel.ID, currentTree.Self.FromNode.ID, currentTree.Self.Rel.ID, currentTree.Self.ToNode.ID) + output += fixIndent(fmt.Sprintf("\tFILTER r%v._from == e_%v._id AND r%v._to == e_%v._id\n", currentTree.Self.Rel.ID, currentTree.Self.FromNode.ID, currentTree.Self.Rel.ID, currentTree.Self.ToNode.ID), indentindex) var subNames []string for i := range currentTree.Children { - subQuery, subName := createQueryRecurse(JSONQuery, tree, currentTree.Children[i], topNode) + subQuery, subName := createQueryRecurse(JSONQuery, tree, currentTree.Children[i], topNode, indentindex+1) output += subQuery subNames = append(subNames, subName) } - output += createZeroFilter(append(subNames, fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID))) - output += createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), subNames) + output += fixIndent(createZeroFilter(append(subNames, fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID))), indentindex) + output += fixIndent(createReturn(fmt.Sprintf("e_%v", newNode.ID), fmt.Sprintf("r%v", currentTree.Self.Rel.ID), subNames), indentindex) + output += fixIndent(")\n", indentindex) return output, fmt.Sprintf("e%v", newNode.ID) } @@ -129,27 +132,52 @@ func getTreeNewNode(currentTree entity.Tree, tree []entity.Tree, topNode entity. } } -func createLetFor(variableName string, forName string, enumerableName string) string { - return "LET " + variableName + " = (\n\tFOR " + forName + " IN " + enumerableName + "\n" +func createLetFor(variableName string, forName string, enumerableName string, indentindex int) string { + output := "LET " + variableName + " = (\n" + for i := 0; i < indentindex; i++ { + output += "\t" + } + output += "\tFOR " + forName + " IN " + enumerableName + "\n" + return output } func createFilter(constraint entity.QueryConstraintStruct, filtered string) string { - return "\tFILTER + " + filtered + constraint.Attribute + " " + wordsToLogicalSign(constraint) + " " + constraint.Value + " \n" + output := "\tFILTER " + filtered + "." + constraint.Attribute + " " + wordsToLogicalSign(constraint) + if constraint.DataType == "string" { + output += " \"" + } else { + output += " " + } + if constraint.MatchType == "contains" { + output += "%" + } + output += constraint.Value + if constraint.MatchType == "contains" { + output += "%" + } + if constraint.DataType == "string" { + output += "\" " + } else { + output += " " + } + output += " \n" + return output } func createZeroFilter(subNames []string) string { - output := "FILTER" + output := "\tFILTER" for i := range subNames { output += fmt.Sprintf(" length(%v) != 0", subNames[i]) if i < len(subNames)-1 { output += " AND" } } + output += "\n" return output } func createReturn(nodeName string, relName string, subNames []string) string { - output := "RETURN {\"nodes\":union_distinct(" + output := "\tRETURN {\"nodes\":union_distinct(" for i := range subNames { output += fmt.Sprintf("flatten(%v[**].nodes), ", subNames[i]) } @@ -165,7 +193,7 @@ func createReturn(nodeName string, relName string, subNames []string) string { if len(subNames) == 0 { output += ", []" } - output += ")}\n)\n" + output += ")}\n" return output } @@ -208,3 +236,12 @@ func wordsToLogicalSign(element entity.QueryConstraintStruct) string { } return match } + +func fixIndent(input string, indentCount int) string { + output := "" + for i := 0; i < indentCount; i++ { + output += "\t" + } + output += input + return output +}