Skip to content
Snippets Groups Projects
Commit bab97cb0 authored by Geurtjens,D. (Douwe Geurtjens)'s avatar Geurtjens,D. (Douwe Geurtjens)
Browse files

Merge branch 'Better-Error-Handling' into 'develop'

Better error handling and beter seperation for clean code architecture

See merge request GravenvanPolaris/query-conversion!1
parents 67763da6 a4049969
No related branches found
No related tags found
1 merge request!1Big merge
......@@ -25,19 +25,18 @@ ConvertQuery converts an IncomingQueryJSON object into AQL
func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, error) {
// TODO: MICHAEL WANT A SINGLE ENTITY TO RETURN A SUMMARY OF ATTRIBUTE VALUES (HISTOGRAM THINGIES)
// Check to make sure all indexes exist
// The largest possible id for an entity
entityCount := len(JSONQuery.Entities) - 1
// The largest possible id for a relation
relationCount := len(JSONQuery.Relations) - 1
// The count of entities
entityCount := len(JSONQuery.Entities)
// The count of relations
relationCount := len(JSONQuery.Relations)
// There are no entities or relations, our query is empty
if entityCount < 0 && relationCount < 0 {
if entityCount <= 0 && relationCount <= 0 {
fmt.Println("Empty query sent, returning default response")
return defaultReturn()
}
// There are no enities or there are no relations
if entityCount < 0 || relationCount < 0 {
fmt.Println("No relations or entities sent, returning default response")
return defaultReturn()
if entityCount <= 0 || relationCount <= 0 {
return nil, errors.New("no relations or entities sent")
}
potentialErrors := entity.ValidateStruct(*JSONQuery)
......@@ -49,7 +48,7 @@ func (s *Service) ConvertQuery(JSONQuery *entity.IncomingQueryJSON) (*string, er
return nil, errors.New("JSONQuery invalid")
}
entityMap, relationMap, _ := fixIndices(JSONQuery)
entityMap, relationMap, _ := entity.FixIndices(JSONQuery)
var tree []entity.Tree
var topNode entity.QueryEntityStruct
......
......@@ -1531,19 +1531,9 @@ func TestNoRelationsField(t *testing.T) {
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
convertedResult, err := service.ConvertQuery(&JSONQuery)
// Assert that there is no error
assert.NoError(t, err)
_, err := service.ConvertQuery(&JSONQuery)
// Assert that the result and the expected result are the same
correctConvertedResult := `LET nodes = first(RETURN UNION_DISTINCT([],[]))
LET edges = first(RETURN UNION_DISTINCT([],[]))
RETURN {"vertices":nodes, "edges":edges }`
regExCleaner := regexp.MustCompile(`\s+`)
correctCleanedResult := regExCleaner.ReplaceAllString(string(correctConvertedResult), " ")
convertedCleanedResult := regExCleaner.ReplaceAllString(*convertedResult, " ")
assert.Equal(t, correctCleanedResult, convertedCleanedResult)
assert.Equal(t, errors.New("no relations or entities sent"), err)
}
/*
......@@ -1607,3 +1597,321 @@ func TestIncorrectRelationFrom(t *testing.T) {
// Assert that there is an error
assert.Equal(t, errors.New("JSONQuery invalid"), err)
}
/*
Tests two separated chains consisting of 1 relation each
t: *testing.T, makes go recognise this as a test
*/
func TestSeparatedChainSingleRelationPerChain(t *testing.T) {
// Setup for test
// Create query conversion service
service := NewService()
query := []byte(`{
"databaseName": "TweedeKamer",
"return": {
"entities": [
0,
1,
2,
3
],
"relations": [
0
]
},
"entities": [
{
"name": "parliament",
"ID": 0,
"constraints": []
},
{
"name": "parties",
"ID": 1,
"constraints": []
},
{
"name": "parliament",
"ID": 2,
"constraints": []
},
{
"name": "parties",
"ID": 3,
"constraints": []
}
],
"relations": [
{
"ID": 0,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 0,
"toType": "entity",
"toID": 1,
"constraints":[]
},
{
"ID": 1,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 2,
"toType": "entity",
"toID": 3,
"constraints":[]
}
],
"groupBys": [],
"limit": 5000,
"modifiers": []
}`)
// Unmarshall the incoming message into an IncomingJSONQuery object
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
_, err := service.ConvertQuery(&JSONQuery)
// Assert that there is an error
assert.Equal(t, errors.New("JSONQuery invalid"), err)
}
/*
Tests two separated chains consisting of 1 relation each
t: *testing.T, makes go recognise this as a test
*/
func TestSeparatedChainDoubleRelationPerChain(t *testing.T) {
// Setup for test
// Create query conversion service
service := NewService()
query := []byte(`{
"databaseName": "TweedeKamer",
"return": {
"entities": [
0,
1,
2,
3,
4,
5
],
"relations": [
0
]
},
"entities": [
{
"name": "parliament",
"ID": 0,
"constraints": []
},
{
"name": "parties",
"ID": 1,
"constraints": []
},
{
"name": "parliament",
"ID": 2,
"constraints": []
},
{
"name": "parties",
"ID": 3,
"constraints": []
},
{
"name": "resolutions",
"ID": 4,
"constraints": []
},
{
"name": "resolutions",
"ID": 5,
"constraints": []
}
],
"relations": [
{
"ID": 0,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 0,
"toType": "entity",
"toID": 1,
"constraints":[]
},
{
"ID": 1,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 2,
"toType": "entity",
"toID": 3,
"constraints":[]
},
{
"ID": 2,
"name": "submits",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 0,
"toType": "entity",
"toID": 4,
"constraints":[]
},
{
"ID": 3,
"name": "submits",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 2,
"toType": "entity",
"toID": 5,
"constraints":[]
}
],
"groupBys": [],
"limit": 5000,
"modifiers": []
}`)
// Unmarshall the incoming message into an IncomingJSONQuery object
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
_, err := service.ConvertQuery(&JSONQuery)
// Assert that there is an error
assert.Equal(t, errors.New("JSONQuery invalid"), err)
}
/*
Tests two separated chains with unequal relations per chain
t: *testing.T, makes go recognise this as a test
*/
func TestSeparatedChainUnequalRelationPerChain(t *testing.T) {
// Setup for test
// Create query conversion service
service := NewService()
query := []byte(`{
"databaseName": "TweedeKamer",
"return": {
"entities": [
0,
1,
2,
3,
4
],
"relations": [
0
]
},
"entities": [
{
"name": "parliament",
"ID": 0,
"constraints": []
},
{
"name": "parties",
"ID": 1,
"constraints": []
},
{
"name": "parliament",
"ID": 2,
"constraints": []
},
{
"name": "parties",
"ID": 3,
"constraints": []
},
{
"name": "resolutions",
"ID": 4,
"constraints": []
}
],
"relations": [
{
"ID": 0,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 0,
"toType": "entity",
"toID": 1,
"constraints":[]
},
{
"ID": 1,
"name": "member_of",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 2,
"toType": "entity",
"toID": 3,
"constraints":[]
},
{
"ID": 2,
"name": "submits",
"depth": {
"min": 1,
"max": 1
},
"fromType": "entity",
"fromID": 2,
"toType": "entity",
"toID": 4,
"constraints":[]
}
],
"groupBys": [],
"limit": 5000,
"modifiers": []
}`)
// Unmarshall the incoming message into an IncomingJSONQuery object
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
_, err := service.ConvertQuery(&JSONQuery)
// Assert that there is an error
assert.Equal(t, errors.New("JSONQuery invalid"), err)
}
......@@ -140,7 +140,7 @@ func TestHierarchyBasic(t *testing.T) {
var JSONQuery entity.IncomingQueryJSON
json.Unmarshal(query, &JSONQuery)
// Get the hierarchy and turn it into JSON so we can turn it into strings later
entityMap, relationMap, _ := fixIndices(&JSONQuery)
entityMap, relationMap, _ := entity.FixIndices(&JSONQuery)
treeList, topNode := createHierarchy(&JSONQuery, entityMap, relationMap)
jsonTopNode, err := json.Marshal(topNode)
if err != nil {
......
package aql
package entity
import (
"git.science.uu.nl/graphpolaris/query-conversion/entity"
)
func fixIndices(JSONQuery *entity.IncomingQueryJSON) (map[int]int, map[int]int, map[int]int) {
/*
A function that maps pill IDs to a range of 0..x
*/
func FixIndices(JSONQuery *IncomingQueryJSON) (map[int]int, map[int]int, map[int]int) {
entityMap := make(map[int]int)
for i, e := range JSONQuery.Entities {
entityMap[e.ID] = i
......
......@@ -22,6 +22,10 @@ func ValidateStruct(JSONQuery IncomingQueryJSON) []error {
if len(JSONQuery.GroupBys) != 0 {
ret = append(ret, getIllegalToFromInGroupBy(JSONQuery, minEntityID, maxEntityID, minRelationID, maxRelationID)...)
}
if len(ret) == 0 {
ret = append(ret, separatedChainExists(JSONQuery)...)
}
return ret
}
......@@ -145,3 +149,19 @@ func getMinAndMaxGroupByID(groupBys []QueryGroupByStruct) (int, int) {
return min, max
}
// Get chains that are not connected to the main chain
func separatedChainExists(JSONQuery IncomingQueryJSON) []error {
ret := make([]error, 0)
entityCount := len(JSONQuery.Entities)
relationCount := len(JSONQuery.Relations)
// A relation always has 2 entities if it's on its own
// If there is a chain (e-r-e-r-e) then there will be one more entity than relation
// If there is two seperate chains you will always end up adding at least 2 entities more than relations
// (e-r-e-r-e) and (e-r-e) has 3 relations but 5 entities, thus we know they are separate
if relationCount != entityCount-1 {
err := errors.New("separated chain found")
ret = append(ret, err)
}
return ret
}
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