Skip to content
Snippets Groups Projects
Commit 700b62c2 authored by Kieran van Gaalen's avatar Kieran van Gaalen
Browse files

Merge branch '676-Query-Nesting-Development' of...

Merge branch '676-Query-Nesting-Development' of https://git.science.uu.nl/GravenvanPolaris/query-conversion into 676-Query-Nesting-Development
parents 038e64a3 20c02ee8
No related branches found
No related tags found
1 merge request!1Big merge
......@@ -48,10 +48,11 @@ func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, er
}
}
// Don't run search if we are getting empty queries from unit tests
var listoflists []entity.PdictList
if len(JSONQuery.Entities) != 0 && len(JSONQuery.Relations) != 0 {
search(JSONQuery, 0)
listoflists = search(JSONQuery, 0)
}
result := createQuery(JSONQuery)
result := createQuery(JSONQuery, listoflists)
return result, nil
}
......@@ -60,7 +61,7 @@ createQuery generates a query based on the json file provided
JSONQuery: *entity.IncomingQueryJSON, this is a parsedJSON struct holding all the data needed to form a query,
Return: *string, a string containing the corresponding AQL query and an error
*/
func createQuery(JSONQuery *entity.IncomingQueryJSON) *string {
func createQuery(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList) *string {
query := ""
for list := range listoflists {
for index := range listoflists[list] {
......
......@@ -7,14 +7,20 @@ import (
"git.science.uu.nl/graphpolaris/query-conversion/entity"
)
var listoflists []entity.PdictList
// We use consts to define string to prevent typos
const ENTITYSTRING = "entity"
const RELATIONSTRING = "relation"
const GROUPBYSTRING = "groupBy"
const FILTERSTRING = "filter"
var reldone map[int]bool
var entdone map[int]bool
var funcdone map[int]bool
var relfuncdone map[int]bool
var filterDone map[int]bool
func search(JSONQuery *entity.IncomingQueryJSON, index int) {
func search(JSONQuery *entity.IncomingQueryJSON, index int) []entity.PdictList {
var listoflists []entity.PdictList
listoflists = []entity.PdictList{}
reldone = make(map[int]bool)
entdone = make(map[int]bool)
......@@ -25,14 +31,11 @@ func search(JSONQuery *entity.IncomingQueryJSON, index int) {
//printSlice(s)
//layercounter = 0
initent := entity.Pdict{
Typename: "entity",
Pointer: index,
}
initent := makePdict(ENTITYSTRING, index)
s = append(s, initent)
listoflists = append(listoflists, s)
entToRel(JSONQuery, initent)
listoflists = entToRel(JSONQuery, listoflists, initent)
for i := range listoflists {
for j := range listoflists[i] {
......@@ -40,9 +43,9 @@ func search(JSONQuery *entity.IncomingQueryJSON, index int) {
}
fmt.Println("")
}
addFilters(JSONQuery)
listoflists = addFilters(JSONQuery, listoflists)
fmt.Println(listoflists)
return listoflists
}
/*
......@@ -51,7 +54,7 @@ Entities always get added IN FRONT OF their respective relation in the hierarchy
JSONQuery: *entity.IncomingQueryJSON, the query in JSON format
rel: pdict, the relation to find all connected entities for
*/
func relToEnt(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
func relToEnt(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList, rel entity.Pdict) []entity.PdictList {
var newlist entity.PdictList
layercounter := findCurrentLayer(listoflists, rel)
// Loop over all entities
......@@ -59,17 +62,11 @@ func relToEnt(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
// If an entity matches either the from or to in a relation we can add it to the newlist
for i := range JSONQuery.Entities {
if _, ok := entdone[i]; !ok {
if JSONQuery.Relations[rel.Pointer].FromID == i && JSONQuery.Relations[rel.Pointer].FromType == "entity" {
fromentity := entity.Pdict{
Typename: "entity",
Pointer: i,
}
if JSONQuery.Relations[rel.Pointer].FromID == i && JSONQuery.Relations[rel.Pointer].FromType == ENTITYSTRING {
fromentity := makePdict(ENTITYSTRING, i)
newlist = append(newlist, fromentity)
} else if JSONQuery.Relations[rel.Pointer].ToID == i && JSONQuery.Relations[rel.Pointer].ToType == "entity" {
toentity := entity.Pdict{
Typename: "entity",
Pointer: i,
}
} else if JSONQuery.Relations[rel.Pointer].ToID == i && JSONQuery.Relations[rel.Pointer].ToType == ENTITYSTRING {
toentity := makePdict(ENTITYSTRING, i)
newlist = append(newlist, toentity)
}
}
......@@ -88,11 +85,13 @@ func relToEnt(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
// So we recurse by calling EntToRel
for i := range newlist {
fmt.Println("EntToRel being called with index?: " + strconv.Itoa(newlist[i].Pointer))
entToRel(JSONQuery, newlist[i])
listoflists = entToRel(JSONQuery, listoflists, newlist[i])
}
}
return listoflists
}
/*
......@@ -101,7 +100,7 @@ Relation always get added BEHIND their respective entity in the hierarchy
JSONQuery: *entity.IncomingQueryJSON, the query in JSON format
ent: pdict, the entity to find all connected relations for
*/
func entToRel(JSONQuery *entity.IncomingQueryJSON, ent entity.Pdict) {
func entToRel(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList, ent entity.Pdict) []entity.PdictList {
var newlist entity.PdictList
layercounter := findCurrentLayer(listoflists, ent)
// Loop over all relations
......@@ -109,17 +108,11 @@ func entToRel(JSONQuery *entity.IncomingQueryJSON, ent entity.Pdict) {
// If a relation matches either the from or to with the entity we can add it to the newlist
for i := range JSONQuery.Relations {
if _, ok := reldone[i]; !ok {
if JSONQuery.Relations[i].FromID == ent.Pointer && JSONQuery.Relations[i].FromType == "entity" {
rel := entity.Pdict{
Typename: "relation",
Pointer: i,
}
if JSONQuery.Relations[i].FromID == ent.Pointer && JSONQuery.Relations[i].FromType == ENTITYSTRING {
rel := makePdict(RELATIONSTRING, i)
newlist = append(newlist, rel)
} else if JSONQuery.Relations[i].ToID == ent.Pointer && JSONQuery.Relations[i].ToType == "entity" {
rel := entity.Pdict{
Typename: "relation",
Pointer: i,
}
} else if JSONQuery.Relations[i].ToID == ent.Pointer && JSONQuery.Relations[i].ToType == ENTITYSTRING {
rel := makePdict(RELATIONSTRING, i)
newlist = append(newlist, rel)
}
}
......@@ -138,12 +131,13 @@ func entToRel(JSONQuery *entity.IncomingQueryJSON, ent entity.Pdict) {
// So we recurse by calling RelToEnt and RelToAllFunc
for i := range newlist {
fmt.Println("RelToEnt being called with index?: " + strconv.Itoa(newlist[i].Pointer))
relToEnt(JSONQuery, newlist[i])
listoflists = relToEnt(JSONQuery, listoflists, newlist[i])
fmt.Println("RelToAllFunc being called with index?: " + strconv.Itoa(newlist[i].Pointer))
relToAllFunc(JSONQuery, newlist[i])
listoflists = relToAllFunc(JSONQuery, listoflists, newlist[i])
}
}
return listoflists
}
/*
......@@ -154,7 +148,7 @@ If a function is connected to a relation (relation uses the results from the fun
JSONQuery: *entity.IncomingQueryJSON, the query in JSON format
rel: pdict, the relation to find all connected functions for
*/
func relToAllFunc(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
func relToAllFunc(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList, rel entity.Pdict) []entity.PdictList {
var funcappliedtosubquery entity.PdictList
var functowhichrelapplies entity.PdictList
layercounter := findCurrentLayer(listoflists, rel)
......@@ -167,27 +161,18 @@ func relToAllFunc(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
if _, ok := relfuncdone[rel.Pointer]; !ok {
if _, ok := funcdone[i]; !ok {
if JSONQuery.GroupBys[i].RelationID == rel.Pointer {
relfunc := entity.Pdict{
Typename: "groupBy",
Pointer: i,
}
relfunc := makePdict(GROUPBYSTRING, i)
funcappliedtosubquery = append(funcappliedtosubquery, relfunc)
fmt.Println("I AM HERE 1")
}
if JSONQuery.Relations[rel.Pointer].FromID == i && JSONQuery.Relations[rel.Pointer].FromType == "groupBy" {
fromfunc := entity.Pdict{
Typename: "groupBy",
Pointer: i,
}
if JSONQuery.Relations[rel.Pointer].FromID == i && JSONQuery.Relations[rel.Pointer].FromType == GROUPBYSTRING {
fromfunc := makePdict(GROUPBYSTRING, i)
functowhichrelapplies = append(functowhichrelapplies, fromfunc)
fmt.Println("I AM HERE 2")
} else if JSONQuery.Relations[rel.Pointer].ToID == i && JSONQuery.Relations[rel.Pointer].ToType == "groupBy" {
tofunc := entity.Pdict{
Typename: "groupBy",
Pointer: i,
}
} else if JSONQuery.Relations[rel.Pointer].ToID == i && JSONQuery.Relations[rel.Pointer].ToType == GROUPBYSTRING {
tofunc := makePdict(GROUPBYSTRING, i)
functowhichrelapplies = append(functowhichrelapplies, tofunc)
fmt.Println("I AM HERE 3")
......@@ -206,7 +191,7 @@ func relToAllFunc(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
for i := range functowhichrelapplies {
fmt.Println("FuncToAllRell being called with index?: " + strconv.Itoa(functowhichrelapplies[i].Pointer))
funcToAllRel(JSONQuery, functowhichrelapplies[i])
listoflists = funcToAllRel(JSONQuery, listoflists, functowhichrelapplies[i])
}
}
......@@ -217,10 +202,10 @@ func relToAllFunc(JSONQuery *entity.IncomingQueryJSON, rel entity.Pdict) {
for i := range funcappliedtosubquery {
fmt.Println("FuncToAllRel being called with index?: " + strconv.Itoa(funcappliedtosubquery[i].Pointer))
funcToAllRel(JSONQuery, funcappliedtosubquery[i])
listoflists = funcToAllRel(JSONQuery, listoflists, funcappliedtosubquery[i])
}
}
return listoflists
}
/*
......@@ -231,7 +216,7 @@ If a relation is connected to a function, we add the relation BEHIND its respect
JSONQuery: *entity.IncomingQueryJSON, the query in JSON format
function: pdict, the function to find all connected relations for
*/
func funcToAllRel(JSONQuery *entity.IncomingQueryJSON, function entity.Pdict) {
func funcToAllRel(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList, function entity.Pdict) []entity.PdictList {
var funcappliedtosubquery entity.PdictList
var relattachedtofunc entity.PdictList
layercounter := findCurrentLayer(listoflists, function)
......@@ -240,26 +225,17 @@ func funcToAllRel(JSONQuery *entity.IncomingQueryJSON, function entity.Pdict) {
if _, ok := relfuncdone[i]; !ok {
// The func is attached to this relation
if JSONQuery.GroupBys[function.Pointer].RelationID == i {
funcrel := entity.Pdict{
Typename: "relation",
Pointer: i,
}
funcrel := makePdict(RELATIONSTRING, i)
funcappliedtosubquery = append(funcappliedtosubquery, funcrel)
}
if JSONQuery.Relations[i].FromID == function.Pointer && JSONQuery.Relations[i].FromType == "groupBy" {
fromrel := entity.Pdict{
Typename: "relation",
Pointer: i,
}
if JSONQuery.Relations[i].FromID == function.Pointer && JSONQuery.Relations[i].FromType == GROUPBYSTRING {
fromrel := makePdict(RELATIONSTRING, i)
relattachedtofunc = append(relattachedtofunc, fromrel)
} else if JSONQuery.Relations[i].ToID == function.Pointer && JSONQuery.Relations[i].ToType == "groupBy" {
torel := entity.Pdict{
Typename: "relation",
Pointer: i,
}
} else if JSONQuery.Relations[i].ToID == function.Pointer && JSONQuery.Relations[i].ToType == GROUPBYSTRING {
torel := makePdict(RELATIONSTRING, i)
relattachedtofunc = append(relattachedtofunc, torel)
}
......@@ -277,9 +253,9 @@ func funcToAllRel(JSONQuery *entity.IncomingQueryJSON, function entity.Pdict) {
for i := range funcappliedtosubquery {
fmt.Println("RelToEnt being called with index?: " + strconv.Itoa(funcappliedtosubquery[i].Pointer))
relToEnt(JSONQuery, funcappliedtosubquery[i])
listoflists = relToEnt(JSONQuery, listoflists, funcappliedtosubquery[i])
fmt.Println("RelToAllFunc being called with index?: " + strconv.Itoa(funcappliedtosubquery[i].Pointer))
relToAllFunc(JSONQuery, funcappliedtosubquery[i])
listoflists = relToAllFunc(JSONQuery, listoflists, funcappliedtosubquery[i])
}
}
......@@ -289,49 +265,42 @@ func funcToAllRel(JSONQuery *entity.IncomingQueryJSON, function entity.Pdict) {
for i := range relattachedtofunc {
fmt.Println("RelToEnt being called with index?: " + strconv.Itoa(relattachedtofunc[i].Pointer))
relToEnt(JSONQuery, relattachedtofunc[i])
listoflists = relToEnt(JSONQuery, listoflists, relattachedtofunc[i])
fmt.Println("RelToAllFunc being called with index?: " + strconv.Itoa(relattachedtofunc[i].Pointer))
relToAllFunc(JSONQuery, relattachedtofunc[i])
listoflists = relToAllFunc(JSONQuery, listoflists, relattachedtofunc[i])
}
}
return listoflists
}
func addFilters(JSONQuery *entity.IncomingQueryJSON) {
func addFilters(JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList) []entity.PdictList {
for i, filter := range JSONQuery.Filters {
if _, ok := filterDone[i]; !ok {
p := entity.Pdict{
Typename: filter.FromType,
Pointer: filter.FromID,
}
f := entity.Pdict{
Typename: "filter",
Pointer: filter.ID,
}
addOneFilter(f, JSONQuery, p, &filterDone)
p := makePdict(filter.FromType, filter.FromID)
f := makePdict(FILTERSTRING, filter.ID)
listoflists = addOneFilter(f, JSONQuery, listoflists, p, &filterDone)
}
}
return listoflists
}
func addOneFilter(filterPDict entity.Pdict, JSONQuery *entity.IncomingQueryJSON, p entity.Pdict, filterDone *map[int]bool) {
if p.Typename == "filter" && (*filterDone)[p.Pointer] {
func addOneFilter(filterPDict entity.Pdict, JSONQuery *entity.IncomingQueryJSON, listoflists []entity.PdictList, p entity.Pdict, filterDone *map[int]bool) []entity.PdictList {
if p.Typename == FILTERSTRING && (*filterDone)[p.Pointer] {
l := findCurrentLayer(listoflists, p)
k := entity.PdictList{filterPDict}
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == "filter" {
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == FILTERSTRING {
listoflists[l+1] = append(listoflists[l+1], filterPDict)
} else {
listoflists = filterAppend(listoflists, l, k)
}
(*filterDone)[filterPDict.Pointer] = true
} else if p.Typename == "filter" {
pnew := entity.Pdict{
Typename: JSONQuery.Filters[p.Pointer].FromType,
Pointer: JSONQuery.Filters[p.Pointer].FromID,
}
addOneFilter(p, JSONQuery, pnew, filterDone)
} else if p.Typename == FILTERSTRING {
pnew := makePdict(JSONQuery.Filters[p.Pointer].FromType, JSONQuery.Filters[p.Pointer].FromID)
addOneFilter(p, JSONQuery, listoflists, pnew, filterDone)
l := findCurrentLayer(listoflists, p)
k := entity.PdictList{filterPDict}
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == "filter" {
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == FILTERSTRING {
listoflists[l+1] = append(listoflists[l+1], filterPDict)
} else {
listoflists = filterAppend(listoflists, l, k)
......@@ -340,55 +309,56 @@ func addOneFilter(filterPDict entity.Pdict, JSONQuery *entity.IncomingQueryJSON,
} else {
l := findCurrentLayer(listoflists, p)
k := entity.PdictList{filterPDict}
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == "filter" {
if len(listoflists) > l+1 && listoflists[l+1][0].Typename == FILTERSTRING {
listoflists[l+1] = append(listoflists[l+1], filterPDict)
} else {
listoflists = filterAppend(listoflists, l, k)
}
(*filterDone)[filterPDict.Pointer] = true
}
return listoflists
}
// A function that appends 1 level above (if index is 0 this won't work)
func aboveAppend(lists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
func aboveAppend(listoflists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
if index == 0 {
return prepend(lists, values)
return prepend(listoflists, values)
} else {
index--
for i := range values {
lists[index] = append(lists[index], values[i])
listoflists[index] = append(listoflists[index], values[i])
}
return lists
return listoflists
}
}
// A function that appends 1 level below
func belowAppend(lists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
func belowAppend(listoflists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
if index == len(listoflists)-1 {
lists = append(listoflists, values)
return lists
listoflists = append(listoflists, values)
return listoflists
} else {
index++
for i := range values {
lists[index] = append(lists[index], values[i])
listoflists[index] = append(listoflists[index], values[i])
}
return lists
return listoflists
}
}
func filterAppend(lists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
if len(lists)-1 == index { // nil or empty slice or after last element
return append(lists, values)
func filterAppend(listoflists []entity.PdictList, index int, values entity.PdictList) []entity.PdictList {
if len(listoflists)-1 == index { // nil or empty slice or after last element
return append(listoflists, values)
}
k := make([]entity.PdictList, len(lists[index+1:]))
copy(k, lists[index+1:])
l := make([]entity.PdictList, len(lists[:index+1]))
copy(l, lists[:index+1])
lists = append(l, values) // index < len(a)
return append(lists, k...)
k := make([]entity.PdictList, len(listoflists[index+1:]))
copy(k, listoflists[index+1:])
l := make([]entity.PdictList, len(listoflists[:index+1]))
copy(l, listoflists[:index+1])
listoflists = append(l, values) // index < len(a)
return append(listoflists, k...)
}
......@@ -413,13 +383,21 @@ func findCurrentLayer(list []entity.PdictList, element entity.Pdict) int {
// See XToY functions for example usage
func prepend(list []entity.PdictList, element entity.PdictList) []entity.PdictList {
var dummylist entity.PdictList
dummy := entity.Pdict{
Typename: "dummy",
Pointer: -1,
}
dummy := makePdict("dummy", -1)
dummylist = append(dummylist, dummy)
list = append(list, dummylist)
copy(list[1:], list)
list[0] = element
return list
}
/*
makePdict makes a pdict based on a typename and pointer
*/
func makePdict(typeName string, pointer int) entity.Pdict {
return entity.Pdict{
Typename: typeName,
Pointer: pointer,
}
}
......@@ -84,7 +84,7 @@ func TestHierarchyBasic(t *testing.T) {
// Unmarshall the incoming message into an IncomingJSONQuery object
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
search(&JSONQuery, 0)
listoflists := search(&JSONQuery, 0)
// Assert that the result and the expected result are the same
correctResult := `[[{entity 0} {entity 1}] [{filter 0}] [{relation 0}] [{filter 1}]]`
......@@ -173,7 +173,7 @@ func TestHierarchyRandomStart(t *testing.T) {
correctResult[3] = entity.PdictList{{Typename: "filter", Pointer: 1}}
for i := range JSONQuery.Entities {
search(&JSONQuery, i)
listoflists := search(&JSONQuery, i)
sortedListOfLists := make([]entity.PdictList, len(listoflists))
for i, list := range listoflists {
k := make(entity.PdictList, list.Len())
......@@ -316,7 +316,7 @@ func TestHierarchyWithGroupby(t *testing.T) {
correctResult[4] = entity.PdictList{{Typename: "relation", Pointer: 1}, {Typename: "relation", Pointer: 2}}
for i := range JSONQuery.Entities {
search(&JSONQuery, i)
listoflists := search(&JSONQuery, i)
fmt.Println(listoflists)
sortedListOfLists := make([]entity.PdictList, len(listoflists))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment