Implement ARRAY_CONCAT, ARRAY_LENGTH, ARRAY_SLICE, SetIntersect, SetUnion functions

This commit is contained in:
Pijus Kamandulis
2024-02-25 00:25:51 +02:00
parent b29608e4c8
commit 1c5e5ce85d
7 changed files with 1553 additions and 510 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -312,19 +312,9 @@ BooleanLiteral <- ("true"i / "false"i) {
FunctionCall <- StringFunctions
/ TypeCheckingFunctions
/ ArrayFunctions
/ InFunction
TypeCheckingFunctions <- IsDefined
/ IsArray
/ IsBool
/ IsFiniteNumber
/ IsInteger
/ IsNull
/ IsNumber
/ IsObject
/ IsPrimitive
/ IsString
StringFunctions <- StringEqualsExpression
/ ToStringExpression
/ ConcatExpression
@@ -342,6 +332,23 @@ StringFunctions <- StringEqualsExpression
/ SubstringExpression
/ TrimExpression
TypeCheckingFunctions <- IsDefined
/ IsArray
/ IsBool
/ IsFiniteNumber
/ IsInteger
/ IsNull
/ IsNumber
/ IsObject
/ IsPrimitive
/ IsString
ArrayFunctions <- ArrayConcatExpression
/ ArrayLengthExpression
/ ArraySliceExpression
/ SetIntersectExpression
/ SetUnionExpression
UpperExpression <- "UPPER"i ws "(" ex:SelectItem ")" {
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})
}
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 ")" {
arguments := append([]interface{}{ex1, ex2}, others.([]interface{})...)
return parsers.FunctionCall{Type: parsers.FunctionCallIn, Arguments: arguments}, nil

View File

@@ -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"},
},
)
})
}