mirror of https://github.com/pikami/cosmium.git
Implement ARRAY_CONCAT, ARRAY_LENGTH, ARRAY_SLICE, SetIntersect, SetUnion functions
This commit is contained in:
parent
b29608e4c8
commit
1c5e5ce85d
|
@ -111,6 +111,12 @@ const (
|
||||||
FunctionCallIsPrimitive FunctionCallType = "IsPrimitive"
|
FunctionCallIsPrimitive FunctionCallType = "IsPrimitive"
|
||||||
FunctionCallIsString FunctionCallType = "IsString"
|
FunctionCallIsString FunctionCallType = "IsString"
|
||||||
|
|
||||||
|
FunctionCallArrayConcat FunctionCallType = "ArrayConcat"
|
||||||
|
FunctionCallArrayLength FunctionCallType = "ArrayLength"
|
||||||
|
FunctionCallArraySlice FunctionCallType = "ArraySlice"
|
||||||
|
FunctionCallSetIntersect FunctionCallType = "SetIntersect"
|
||||||
|
FunctionCallSetUnion FunctionCallType = "SetUnion"
|
||||||
|
|
||||||
FunctionCallIn FunctionCallType = "In"
|
FunctionCallIn FunctionCallType = "In"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -312,19 +312,9 @@ BooleanLiteral <- ("true"i / "false"i) {
|
||||||
|
|
||||||
FunctionCall <- StringFunctions
|
FunctionCall <- StringFunctions
|
||||||
/ TypeCheckingFunctions
|
/ TypeCheckingFunctions
|
||||||
|
/ ArrayFunctions
|
||||||
/ InFunction
|
/ InFunction
|
||||||
|
|
||||||
TypeCheckingFunctions <- IsDefined
|
|
||||||
/ IsArray
|
|
||||||
/ IsBool
|
|
||||||
/ IsFiniteNumber
|
|
||||||
/ IsInteger
|
|
||||||
/ IsNull
|
|
||||||
/ IsNumber
|
|
||||||
/ IsObject
|
|
||||||
/ IsPrimitive
|
|
||||||
/ IsString
|
|
||||||
|
|
||||||
StringFunctions <- StringEqualsExpression
|
StringFunctions <- StringEqualsExpression
|
||||||
/ ToStringExpression
|
/ ToStringExpression
|
||||||
/ ConcatExpression
|
/ ConcatExpression
|
||||||
|
@ -342,6 +332,23 @@ StringFunctions <- StringEqualsExpression
|
||||||
/ SubstringExpression
|
/ SubstringExpression
|
||||||
/ TrimExpression
|
/ TrimExpression
|
||||||
|
|
||||||
|
TypeCheckingFunctions <- IsDefined
|
||||||
|
/ IsArray
|
||||||
|
/ IsBool
|
||||||
|
/ IsFiniteNumber
|
||||||
|
/ IsInteger
|
||||||
|
/ IsNull
|
||||||
|
/ IsNumber
|
||||||
|
/ IsObject
|
||||||
|
/ IsPrimitive
|
||||||
|
/ IsString
|
||||||
|
|
||||||
|
ArrayFunctions <- ArrayConcatExpression
|
||||||
|
/ ArrayLengthExpression
|
||||||
|
/ ArraySliceExpression
|
||||||
|
/ SetIntersectExpression
|
||||||
|
/ SetUnionExpression
|
||||||
|
|
||||||
UpperExpression <- "UPPER"i ws "(" ex:SelectItem ")" {
|
UpperExpression <- "UPPER"i ws "(" ex:SelectItem ")" {
|
||||||
return createFunctionCall(parsers.FunctionCallUpper, []interface{}{ex})
|
return createFunctionCall(parsers.FunctionCallUpper, []interface{}{ex})
|
||||||
}
|
}
|
||||||
|
@ -465,6 +472,26 @@ IsString <- "IS_STRING"i ws "(" ws ex:SelectItem ws ")" {
|
||||||
return createFunctionCall(parsers.FunctionCallIsString, []interface{}{ex})
|
return createFunctionCall(parsers.FunctionCallIsString, []interface{}{ex})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayConcatExpression <- "ARRAY_CONCAT"i ws "(" ws arrays:SelectItem others:(ws "," ws ex:SelectItem { return ex, nil })+ ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArrayConcat, append([]interface{}{arrays}, others.([]interface{})...))
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayLengthExpression <- "ARRAY_LENGTH"i ws "(" ws array:SelectItem ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArrayLength, []interface{}{array})
|
||||||
|
}
|
||||||
|
|
||||||
|
ArraySliceExpression <- "ARRAY_SLICE"i ws "(" ws array:SelectItem ws "," ws start:SelectItem length:(ws "," ws ex:SelectItem { return ex, nil })? ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallArraySlice, []interface{}{array, start, length})
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntersectExpression <- "SetIntersect"i ws "(" ws set1:SelectItem ws "," ws set2:SelectItem ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallSetIntersect, []interface{}{set1, set2})
|
||||||
|
}
|
||||||
|
|
||||||
|
SetUnionExpression <- "SetUnion"i ws "(" ws set1:SelectItem ws "," ws set2:SelectItem ws ")" {
|
||||||
|
return createFunctionCall(parsers.FunctionCallSetUnion, []interface{}{set1, set2})
|
||||||
|
}
|
||||||
|
|
||||||
InFunction <- ex1:SelectProperty ws "IN"i ws "(" ws ex2:SelectItem others:(ws "," ws ex:SelectItem { return ex, nil })* ws ")" {
|
InFunction <- ex1:SelectProperty ws "IN"i ws "(" ws ex2:SelectItem others:(ws "," ws ex:SelectItem { return ex, nil })* ws ")" {
|
||||||
arguments := append([]interface{}{ex1, ex2}, others.([]interface{})...)
|
arguments := append([]interface{}{ex1, ex2}, others.([]interface{})...)
|
||||||
return parsers.FunctionCall{Type: parsers.FunctionCallIn, Arguments: arguments}, nil
|
return parsers.FunctionCall{Type: parsers.FunctionCallIn, Arguments: arguments}, nil
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
package nosql_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Parse_ArrayFunctions(t *testing.T) {
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_CONCAT()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_CONCAT(c.a1, c.a2) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayConcat,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "a1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "a2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_LENGTH()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_LENGTH(c.array) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayLength,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "array"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function ARRAY_SLICE()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT ARRAY_SLICE(c.array, 0, 2) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArraySlice,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "array"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeInteger,
|
||||||
|
Value: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeInteger,
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function SetIntersect()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT SetIntersect(c.set1, c.set2) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallSetIntersect,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "set1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "set2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should parse function SetUnion()", func(t *testing.T) {
|
||||||
|
testQueryParse(
|
||||||
|
t,
|
||||||
|
`SELECT SetUnion(c.set1, c.set2) FROM c`,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallSetUnion,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "set1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "set2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
package memoryexecutor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
)
|
||||||
|
|
||||||
|
func array_Concat(arguments []interface{}, queryParameters map[string]interface{}, row RowType) []interface{} {
|
||||||
|
var result []interface{}
|
||||||
|
for _, arg := range arguments {
|
||||||
|
array := parseArray(arg, queryParameters, row)
|
||||||
|
result = append(result, array...)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func array_Length(arguments []interface{}, queryParameters map[string]interface{}, row RowType) int {
|
||||||
|
array := parseArray(arguments[0], queryParameters, row)
|
||||||
|
if array == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
func array_Slice(arguments []interface{}, queryParameters map[string]interface{}, row RowType) []interface{} {
|
||||||
|
var ok bool
|
||||||
|
var start int
|
||||||
|
var length int
|
||||||
|
array := parseArray(arguments[0], queryParameters, row)
|
||||||
|
startEx := getFieldValue(arguments[1].(parsers.SelectItem), queryParameters, row)
|
||||||
|
|
||||||
|
if arguments[2] != nil {
|
||||||
|
lengthEx := getFieldValue(arguments[2].(parsers.SelectItem), queryParameters, row)
|
||||||
|
|
||||||
|
if length, ok = lengthEx.(int); !ok {
|
||||||
|
fmt.Println("array_Slice - got length parameters of wrong type")
|
||||||
|
return []interface{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if start, ok = startEx.(int); !ok {
|
||||||
|
fmt.Println("array_Slice - got start parameters of wrong type")
|
||||||
|
return []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if start < 0 {
|
||||||
|
start = len(array) + start
|
||||||
|
}
|
||||||
|
|
||||||
|
if start < 0 {
|
||||||
|
start = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if array == nil || start >= len(array) {
|
||||||
|
return []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
end := start + length
|
||||||
|
if end > len(array) {
|
||||||
|
end = len(array)
|
||||||
|
}
|
||||||
|
return array[start:end]
|
||||||
|
}
|
||||||
|
|
||||||
|
func set_Intersect(arguments []interface{}, queryParameters map[string]interface{}, row RowType) []interface{} {
|
||||||
|
set1 := parseArray(arguments[0], queryParameters, row)
|
||||||
|
set2 := parseArray(arguments[1], queryParameters, row)
|
||||||
|
|
||||||
|
intersection := make(map[interface{}]struct{})
|
||||||
|
if set1 == nil || set2 == nil {
|
||||||
|
return []interface{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range set1 {
|
||||||
|
intersection[item] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []interface{}
|
||||||
|
for _, item := range set2 {
|
||||||
|
if _, exists := intersection[item]; exists {
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func set_Union(arguments []interface{}, queryParameters map[string]interface{}, row RowType) []interface{} {
|
||||||
|
set1 := parseArray(arguments[0], queryParameters, row)
|
||||||
|
set2 := parseArray(arguments[1], queryParameters, row)
|
||||||
|
|
||||||
|
var result []interface{}
|
||||||
|
union := make(map[interface{}]struct{})
|
||||||
|
for _, item := range set1 {
|
||||||
|
if _, ok := union[item]; !ok {
|
||||||
|
union[item] = struct{}{}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range set2 {
|
||||||
|
if _, ok := union[item]; !ok {
|
||||||
|
union[item] = struct{}{}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseArray(argument interface{}, queryParameters map[string]interface{}, row RowType) []interface{} {
|
||||||
|
exItem := argument.(parsers.SelectItem)
|
||||||
|
ex := getFieldValue(exItem, queryParameters, row)
|
||||||
|
|
||||||
|
arrValue := reflect.ValueOf(ex)
|
||||||
|
if arrValue.Kind() != reflect.Slice {
|
||||||
|
fmt.Println("parseArray got parameters of wrong type")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result := make([]interface{}, arrValue.Len())
|
||||||
|
|
||||||
|
for i := 0; i < arrValue.Len(); i++ {
|
||||||
|
result[i] = arrValue.Index(i).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,212 @@
|
||||||
|
package memoryexecutor_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pikami/cosmium/parsers"
|
||||||
|
memoryexecutor "github.com/pikami/cosmium/query_executors/memory_executor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Execute_ArrayFunctions(t *testing.T) {
|
||||||
|
mockData := []memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "arr1": []int{1, 2, 3}, "arr2": []int{3, 4, 5}},
|
||||||
|
map[string]interface{}{"id": "456", "arr1": []int{4, 5, 6}, "arr2": []int{5, 6, 7, 8}},
|
||||||
|
map[string]interface{}{"id": "789", "arr1": []int{7, 8, 9}, "arr2": []int{7, 8, 9, 10, 11}},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("Should execute function CONCAT()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "Concat",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayConcat,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "Concat": []interface{}{1, 2, 3, 3, 4, 5}},
|
||||||
|
map[string]interface{}{"id": "456", "Concat": []interface{}{4, 5, 6, 5, 6, 7, 8}},
|
||||||
|
map[string]interface{}{"id": "789", "Concat": []interface{}{7, 8, 9, 7, 8, 9, 10, 11}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function ARRAY_LENGTH()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "Length",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArrayLength,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "Length": 3},
|
||||||
|
map[string]interface{}{"id": "456", "Length": 4},
|
||||||
|
map[string]interface{}{"id": "789", "Length": 5},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function ARRAY_SLICE()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "Slice",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallArraySlice,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeInteger,
|
||||||
|
Value: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Type: parsers.SelectItemTypeConstant,
|
||||||
|
Value: parsers.Constant{
|
||||||
|
Type: parsers.ConstantTypeInteger,
|
||||||
|
Value: 2,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "Slice": []interface{}{4, 5}},
|
||||||
|
map[string]interface{}{"id": "456", "Slice": []interface{}{6, 7}},
|
||||||
|
map[string]interface{}{"id": "789", "Slice": []interface{}{8, 9}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function SET_INTERSECT()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "Intersection",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallSetIntersect,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "Intersection": []interface{}{3}},
|
||||||
|
map[string]interface{}{"id": "456", "Intersection": []interface{}{5, 6}},
|
||||||
|
map[string]interface{}{"id": "789", "Intersection": []interface{}{7, 8, 9}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Should execute function SET_UNION()", func(t *testing.T) {
|
||||||
|
testQueryExecute(
|
||||||
|
t,
|
||||||
|
parsers.SelectStmt{
|
||||||
|
SelectItems: []parsers.SelectItem{
|
||||||
|
{
|
||||||
|
Path: []string{"c", "id"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Alias: "Union",
|
||||||
|
Type: parsers.SelectItemTypeFunctionCall,
|
||||||
|
Value: parsers.FunctionCall{
|
||||||
|
Type: parsers.FunctionCallSetUnion,
|
||||||
|
Arguments: []interface{}{
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr1"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
parsers.SelectItem{
|
||||||
|
Path: []string{"c", "arr2"},
|
||||||
|
Type: parsers.SelectItemTypeField,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Table: parsers.Table{Value: "c"},
|
||||||
|
},
|
||||||
|
mockData,
|
||||||
|
[]memoryexecutor.RowType{
|
||||||
|
map[string]interface{}{"id": "123", "Union": []interface{}{1, 2, 3, 4, 5}},
|
||||||
|
map[string]interface{}{"id": "456", "Union": []interface{}{4, 5, 6, 7, 8}},
|
||||||
|
map[string]interface{}{"id": "789", "Union": []interface{}{7, 8, 9, 10, 11}},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
|
@ -236,6 +236,17 @@ func getFieldValue(field parsers.SelectItem, queryParameters map[string]interfac
|
||||||
case parsers.FunctionCallIsString:
|
case parsers.FunctionCallIsString:
|
||||||
return typeChecking_IsString(typedValue.Arguments, queryParameters, row)
|
return typeChecking_IsString(typedValue.Arguments, queryParameters, row)
|
||||||
|
|
||||||
|
case parsers.FunctionCallArrayConcat:
|
||||||
|
return array_Concat(typedValue.Arguments, queryParameters, row)
|
||||||
|
case parsers.FunctionCallArrayLength:
|
||||||
|
return array_Length(typedValue.Arguments, queryParameters, row)
|
||||||
|
case parsers.FunctionCallArraySlice:
|
||||||
|
return array_Slice(typedValue.Arguments, queryParameters, row)
|
||||||
|
case parsers.FunctionCallSetIntersect:
|
||||||
|
return set_Intersect(typedValue.Arguments, queryParameters, row)
|
||||||
|
case parsers.FunctionCallSetUnion:
|
||||||
|
return set_Union(typedValue.Arguments, queryParameters, row)
|
||||||
|
|
||||||
case parsers.FunctionCallIn:
|
case parsers.FunctionCallIn:
|
||||||
return misc_In(typedValue.Arguments, queryParameters, row)
|
return misc_In(typedValue.Arguments, queryParameters, row)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue