Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
package cypher
import (
"errors"
"fmt"
"git.science.uu.nl/graphpolaris/query-conversion/entity"
)
func performBasicHealthCheck(JSONQuery *entity.IncomingQueryJSON) (bool, error) {
// Check to make sure all indexes exist
// How many entities are there
numEntities := len(JSONQuery.Entities) - 1
// How many relations there are
numRelations := len(JSONQuery.Relations) - 1
// Make sure no entity should be returned that is outside the range of that list
for _, e := range JSONQuery.Return.Entities {
// If this entity references an entity that is outside the range
if e > numEntities || e < 0 {
return false, errors.New("non-existing entity referenced in return")
}
}
// Make sure that no relation mentions a non-existing entity
for _, r := range JSONQuery.Relations {
if r.FromID > numEntities || r.ToID > numEntities {
return false, errors.New("non-exisiting entity referenced in relation")
}
}
// Make sure no non-existing relation is tried to be returned
for _, r := range JSONQuery.Return.Relations {
if r > numRelations || r < 0 {
return false, errors.New("non-existing relation referenced in return")
}
}
return true, nil
}
// checkForQueryCluster will detect (and separate?) if there are multiple queries in the query panel and will try to sepate the queries.
// Maybe also delete floating pills that have no connection (but that is a different function)
func checkForQueryCluster(JSONQuery *entity.IncomingQueryJSON) (*entity.IncomingQueryJSON, *entity.IncomingQueryJSON, bool) {
// Notes naar moizelf: alle pills die dingen aan elkaar verbinden zijn relations en group bys, filter lijken 'op' een lijntje te leven, maar niet als schakel te dienen
// Dit zou recursief kunnen: vind een cluster in de json, haal alles uit de json dat verbonden zit aan die cluster, voer de functie opnieuw uit op het restand
cluster := make(map[string]bool) // aka een set (entities e0 e1 e2, relations r0 .., groub by g0 ..)
// Dit is het startpunt van de cluster, vrij veel if elses ivm half afgemaakte queries
// Lots of existance checks
if len(JSONQuery.Relations) > 0 {
rel := fmt.Sprintf("r%v", JSONQuery.Relations[0].ID)
cluster[rel] = true
if JSONQuery.Relations[0].ToID != -1 {
// Take the first letter: entities with ID 0 -> e0
to := fmt.Sprintf("%v%v", JSONQuery.Relations[0].ToType[0], JSONQuery.Relations[0].ToID)
cluster[to] = true
}
if JSONQuery.Relations[0].FromID != -1 {
from := fmt.Sprintf("%v%v", JSONQuery.Relations[0].FromType[0], JSONQuery.Relations[0].FromID)
cluster[from] = true
}
} else if len(JSONQuery.GroupBys) > 0 {
gb := fmt.Sprintf("g%v", JSONQuery.GroupBys[0].ID)
cluster[gb] = true
// TODO: Wat te doen als de groupby niet goed is aangesloten, want dat crasht ie nogal atm
group := fmt.Sprintf("%v%v", JSONQuery.GroupBys[0].GroupType[0], JSONQuery.GroupBys[0].GroupID)
cluster[group] = true
by := fmt.Sprintf("%v%v", JSONQuery.GroupBys[0].ByType[0], JSONQuery.GroupBys[0].ByID)
cluster[by] = true
} else if len(JSONQuery.Modifiers) > 0 {
// I guess dat je ook een enkele entity met bepaalde constraints kan tellen ofzo? of kan averagen
// TODO
}
// Relation toevoegen aan de map
// Is er geen relation doe dan groupby
// is die er ook niet dan rip
for {
stop := true
// kijk langs alle relations en group bys of ie verbonden is aan de cluster en nog niet in de set zit
// Is dat zo run m opnieuw en kijk of daar weer dingen aan verbonden zijn
for _, rel := range JSONQuery.Relations {
// check of de rel er al in zit, dan kan ie geskipped worden
// zo nee kijk of een van de entities of group by's erin zit, dan is deze dus verbonden
rela := fmt.Sprintf("r%v", rel.ID)
if cluster[rela] {
// If it is already in the cluster then we dont care
continue
}
partOfCluster := false
// Now comes the check to see if one of its endpoints is in the cluster, meaning everything is in the cluster
if rel.ToID != -1 {
to := fmt.Sprintf("%v%v", rel.ToType[0], rel.ToID)
if cluster[to] {
partOfCluster = true
}
}
if rel.FromID != -1 {
from := fmt.Sprintf("%v%v", rel.FromType[0], rel.FromID)
cluster[from] = true
if cluster[from] {
partOfCluster = true
}
}
if partOfCluster {
if rel.ToID != -1 {
to := fmt.Sprintf("%v%v", rel.ToType[0], rel.ToID)
cluster[to] = true
}
if rel.FromID != -1 {
from := fmt.Sprintf("%v%v", rel.FromType[0], rel.FromID)
cluster[from] = true
}
stop = false
}
}
// Now the same for Group by's
for _, gb := range JSONQuery.GroupBys {
gby := fmt.Sprintf("g%v", gb.ID)
if cluster[gby] {
continue
}
// It should have been checked that the connections of the group by are valid, since a group by must have all connections filled (in contrary of a relation)
group := fmt.Sprintf("%v%v", gb.GroupType[0], gb.GroupID)
by := fmt.Sprintf("%v%v", gb.ByType[0], gb.ByID)
if cluster[group] || cluster[by] {
cluster[gby] = true
cluster[group] = true
cluster[by] = true
stop = false
}
}
// ** then for modifiers? although modifiers havent changed yet, since their results must also be used in queries
// Modifiers will change, so that is a problem for later
if stop {
// No new entities were added to the cluster, thus it is finished
break
}
}
// Now walk through the JSON and divide it into the cluster and rest
restJSON := entity.IncomingQueryJSON{DatabaseName: JSONQuery.DatabaseName, Limit: JSONQuery.Limit}
clusterJSON := entity.IncomingQueryJSON{DatabaseName: JSONQuery.DatabaseName, Limit: JSONQuery.Limit}
isRest := false
// Loop through entities
for _, ent := range JSONQuery.Entities {
name := fmt.Sprintf("e%v", ent.ID)
if cluster[name] {
clusterJSON.Entities = append(clusterJSON.Entities, ent)
clusterJSON.Return.Entities = append(clusterJSON.Return.Entities, ent.ID)
} else {
restJSON.Entities = append(restJSON.Entities, ent)
restJSON.Return.Entities = append(restJSON.Return.Entities, ent.ID)
isRest = true
}
}
// Loop through relations
for _, rel := range JSONQuery.Relations {
name := fmt.Sprintf("r%v", rel.ID)
if cluster[name] {
clusterJSON.Relations = append(clusterJSON.Relations, rel)
clusterJSON.Return.Relations = append(clusterJSON.Return.Relations, rel.ID)
} else {
restJSON.Relations = append(restJSON.Relations, rel)
restJSON.Return.Relations = append(restJSON.Return.Relations, rel.ID)
isRest = true
}
}
// Loop through groupby's
for _, gb := range JSONQuery.GroupBys {
name := fmt.Sprintf("g%v", gb.ID)
if cluster[name] {
clusterJSON.GroupBys = append(clusterJSON.GroupBys, gb)
clusterJSON.Return.GroupBys = append(clusterJSON.Return.GroupBys, gb.ID)
} else {
restJSON.GroupBys = append(restJSON.GroupBys, gb)
restJSON.Return.GroupBys = append(restJSON.Return.GroupBys, gb.ID)
isRest = true
}
}
// ** Loop through modifiers
// Loop through filters
// Filters were not done in the clustering, since they live on top of a connection, meaning they do not extend the cluster
// This also means that if a From or a To is in the cluster, the other (and thus the filter) is in the cluster as well
for _, filter := range JSONQuery.Filters {
from := fmt.Sprintf("%v%v", filter.FromType[0], filter.FromID)
if cluster[from] {
clusterJSON.Filters = append(clusterJSON.Filters, filter)
} else {
restJSON.Filters = append(restJSON.Filters, filter)
isRest = true
}
}
return &clusterJSON, &restJSON, isRest
// Nadat cluster is gevonden: maak twee nieuwe jsons aan: cluster en rest
// Loop door de OG json en voeg alles aan of de cluster of de rest toe
// Return cluster, rest en een bool die zegt of er een cluster is
// Wss is het in 99% van de gevallen maar 1 cluster of een cluster met een verdwaalde node, maar toch
}
// ** MOGELIJK OBSOLETE, hangt af van de hierarchiefunctie
/* checkQueryValidity performs checks to see if the query is valid.
Returns a boolean indicating if the query is valid, the error will containt a custom message saying what is wrong with the query.
It is obviously possible the query is still invalid, but that is for the database to find out.
*/
func checkQueryValidity(JSONQuery *entity.IncomingQueryJSON) (bool, error) {
// The first test is to see if there are at least 2 returns, since only one return is not possible (we do not allow relation only queries)
ret := JSONQuery.Return
numOfReturns := len(ret.Entities) + len(ret.GroupBys) + len(ret.Relations)
if numOfReturns < 2 {
return false, errors.New("Insufficient return values")
}
return true, nil
}