Implement IS_ARRAY, IS_BOOL, IS_FINITE_NUMBER, IS_INTEGER, IS_NULL, IS_NUMBER, IS_OBJECT, IS_PRIMITIVE, IS_STRING functions

This commit is contained in:
Pijus Kamandulis 2024-02-24 22:29:33 +02:00
parent 2431307a12
commit b29608e4c8
7 changed files with 1789 additions and 368 deletions

View File

@ -81,14 +81,12 @@ type FunctionCallType string
const ( const (
FunctionCallStringEquals FunctionCallType = "StringEquals" FunctionCallStringEquals FunctionCallType = "StringEquals"
FunctionCallIsDefined FunctionCallType = "IsDefined"
FunctionCallConcat FunctionCallType = "Concat" FunctionCallConcat FunctionCallType = "Concat"
FunctionCallContains FunctionCallType = "Contains" FunctionCallContains FunctionCallType = "Contains"
FunctionCallEndsWith FunctionCallType = "EndsWith" FunctionCallEndsWith FunctionCallType = "EndsWith"
FunctionCallStartsWith FunctionCallType = "StartsWith" FunctionCallStartsWith FunctionCallType = "StartsWith"
FunctionCallIndexOf FunctionCallType = "IndexOf" FunctionCallIndexOf FunctionCallType = "IndexOf"
FunctionCallToString FunctionCallType = "ToString" FunctionCallToString FunctionCallType = "ToString"
FunctionCallIn FunctionCallType = "In"
FunctionCallUpper FunctionCallType = "Upper" FunctionCallUpper FunctionCallType = "Upper"
FunctionCallLower FunctionCallType = "Lower" FunctionCallLower FunctionCallType = "Lower"
FunctionCallLeft FunctionCallType = "Left" FunctionCallLeft FunctionCallType = "Left"
@ -101,6 +99,19 @@ const (
FunctionCallRTrim FunctionCallType = "RTrim" FunctionCallRTrim FunctionCallType = "RTrim"
FunctionCallSubstring FunctionCallType = "Substring" FunctionCallSubstring FunctionCallType = "Substring"
FunctionCallTrim FunctionCallType = "Trim" FunctionCallTrim FunctionCallType = "Trim"
FunctionCallIsDefined FunctionCallType = "IsDefined"
FunctionCallIsArray FunctionCallType = "IsArray"
FunctionCallIsBool FunctionCallType = "IsBool"
FunctionCallIsFiniteNumber FunctionCallType = "IsFiniteNumber"
FunctionCallIsInteger FunctionCallType = "IsInteger"
FunctionCallIsNull FunctionCallType = "IsNull"
FunctionCallIsNumber FunctionCallType = "IsNumber"
FunctionCallIsObject FunctionCallType = "IsObject"
FunctionCallIsPrimitive FunctionCallType = "IsPrimitive"
FunctionCallIsString FunctionCallType = "IsString"
FunctionCallIn FunctionCallType = "In"
) )
type FunctionCall struct { type FunctionCall struct {

File diff suppressed because it is too large Load Diff

View File

@ -310,7 +310,20 @@ BooleanLiteral <- ("true"i / "false"i) {
return parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: boolValue}, nil return parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: boolValue}, nil
} }
FunctionCall <- StringFunctions / IsDefined / InFunction FunctionCall <- StringFunctions
/ TypeCheckingFunctions
/ InFunction
TypeCheckingFunctions <- IsDefined
/ IsArray
/ IsBool
/ IsFiniteNumber
/ IsInteger
/ IsNull
/ IsNumber
/ IsObject
/ IsPrimitive
/ IsString
StringFunctions <- StringEqualsExpression StringFunctions <- StringEqualsExpression
/ ToStringExpression / ToStringExpression
@ -413,7 +426,43 @@ ThreeArgumentStringFunction <- ("CONTAINS"i / "ENDSWITH"i / "STARTSWITH"i / "IND
} }
IsDefined <- "IS_DEFINED"i ws "(" ws ex:SelectItem ws ")" { IsDefined <- "IS_DEFINED"i ws "(" ws ex:SelectItem ws ")" {
return parsers.FunctionCall{Type: parsers.FunctionCallIsDefined, Arguments: []interface{}{ex}}, nil return createFunctionCall(parsers.FunctionCallIsDefined, []interface{}{ex})
}
IsArray <- "IS_ARRAY"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsArray, []interface{}{ex})
}
IsBool <- "IS_BOOL"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsBool, []interface{}{ex})
}
IsFiniteNumber <- "IS_FINITE_NUMBER"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsFiniteNumber, []interface{}{ex})
}
IsInteger <- "IS_INTEGER"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsInteger, []interface{}{ex})
}
IsNull <- "IS_NULL"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsNull, []interface{}{ex})
}
IsNumber <- "IS_NUMBER"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsNumber, []interface{}{ex})
}
IsObject <- "IS_OBJECT"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsObject, []interface{}{ex})
}
IsPrimitive <- "IS_PRIMITIVE"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsPrimitive, []interface{}{ex})
}
IsString <- "IS_STRING"i ws "(" ws ex:SelectItem ws ")" {
return createFunctionCall(parsers.FunctionCallIsString, []interface{}{ex})
} }
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 ")" {

View File

@ -43,4 +43,328 @@ func Test_Execute_TypeCheckingFunctions(t *testing.T) {
}, },
) )
}) })
t.Run("Should parse function IS_ARRAY", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_ARRAY(c.arr) FROM c WHERE IS_ARRAY(c.arr)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsArray,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "arr"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsArray,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "arr"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_BOOL", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_BOOL(c.flag) FROM c WHERE IS_BOOL(c.flag)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsBool,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "flag"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsBool,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "flag"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_FINITE_NUMBER", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_FINITE_NUMBER(c.value) FROM c WHERE IS_FINITE_NUMBER(c.amount)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsFiniteNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsFiniteNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "amount"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_INTEGER", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_INTEGER(c.number) FROM c WHERE IS_INTEGER(c.number)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsInteger,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "number"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsInteger,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "number"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_NULL", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_NULL(c.value) FROM c WHERE IS_NULL(c.value)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNull,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNull,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_NUMBER", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_NUMBER(c.value) FROM c WHERE IS_NUMBER(c.value)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_OBJECT", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_OBJECT(c.obj) FROM c WHERE IS_OBJECT(c.obj)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsObject,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsObject,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_PRIMITIVE", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_PRIMITIVE(c.value) FROM c WHERE IS_PRIMITIVE(c.value)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsPrimitive,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsPrimitive,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
t.Run("Should parse function IS_STRING", func(t *testing.T) {
testQueryParse(
t,
`SELECT IS_STRING(c.value) FROM c WHERE IS_STRING(c.value)`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsString,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.SelectItem{
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsString,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "value"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
)
})
} }

View File

@ -214,8 +214,28 @@ func getFieldValue(field parsers.SelectItem, queryParameters map[string]interfac
return strings_Substring(typedValue.Arguments, queryParameters, row) return strings_Substring(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallTrim: case parsers.FunctionCallTrim:
return strings_Trim(typedValue.Arguments, queryParameters, row) return strings_Trim(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsDefined: case parsers.FunctionCallIsDefined:
return typeChecking_IsDefined(typedValue.Arguments, queryParameters, row) return typeChecking_IsDefined(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsArray:
return typeChecking_IsArray(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsBool:
return typeChecking_IsBool(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsFiniteNumber:
return typeChecking_IsFiniteNumber(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsInteger:
return typeChecking_IsInteger(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsNull:
return typeChecking_IsNull(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsNumber:
return typeChecking_IsNumber(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsObject:
return typeChecking_IsObject(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsPrimitive:
return typeChecking_IsPrimitive(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIsString:
return typeChecking_IsString(typedValue.Arguments, queryParameters, row)
case parsers.FunctionCallIn: case parsers.FunctionCallIn:
return misc_In(typedValue.Arguments, queryParameters, row) return misc_In(typedValue.Arguments, queryParameters, row)
} }

View File

@ -1,6 +1,8 @@
package memoryexecutor package memoryexecutor
import ( import (
"math"
"github.com/pikami/cosmium/parsers" "github.com/pikami/cosmium/parsers"
) )
@ -10,3 +12,85 @@ func typeChecking_IsDefined(arguments []interface{}, queryParameters map[string]
return ex != nil return ex != nil
} }
func typeChecking_IsArray(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isArray := ex.([]interface{})
return isArray
}
func typeChecking_IsBool(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isBool := ex.(bool)
return isBool
}
func typeChecking_IsFiniteNumber(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
switch num := ex.(type) {
case int:
return true
case float64:
return !math.IsInf(num, 0) && !math.IsNaN(num)
default:
return false
}
}
func typeChecking_IsInteger(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isInt := ex.(int)
return isInt
}
func typeChecking_IsNull(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
return ex == nil
}
func typeChecking_IsNumber(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isFloat := ex.(float64)
_, isInt := ex.(int)
return isFloat || isInt
}
func typeChecking_IsObject(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isObject := ex.(map[string]interface{})
return isObject
}
func typeChecking_IsPrimitive(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
switch ex.(type) {
case bool, string, float64, int, nil:
return true
default:
return false
}
}
func typeChecking_IsString(arguments []interface{}, queryParameters map[string]interface{}, row RowType) bool {
exItem := arguments[0].(parsers.SelectItem)
ex := getFieldValue(exItem, queryParameters, row)
_, isStr := ex.(string)
return isStr
}

View File

@ -1,6 +1,7 @@
package memoryexecutor_test package memoryexecutor_test
import ( import (
"math"
"testing" "testing"
"github.com/pikami/cosmium/parsers" "github.com/pikami/cosmium/parsers"
@ -9,9 +10,14 @@ import (
func Test_Execute_TypeCheckingFunctions(t *testing.T) { func Test_Execute_TypeCheckingFunctions(t *testing.T) {
mockData := []memoryexecutor.RowType{ mockData := []memoryexecutor.RowType{
map[string]interface{}{"id": "123", "pk": "aaa"}, map[string]interface{}{"id": "1", "obj": nil},
map[string]interface{}{"id": "456"}, map[string]interface{}{"id": "2", "obj": "str"},
map[string]interface{}{"id": "789", "pk": ""}, map[string]interface{}{"id": "3", "obj": 1},
map[string]interface{}{"id": "4", "obj": 1.2},
map[string]interface{}{"id": "5", "obj": true},
map[string]interface{}{"id": "6", "obj": []interface{}{1, 2, 3}},
map[string]interface{}{"id": "7", "obj": map[string]interface{}{"a": "a"}},
map[string]interface{}{"id": "8", "obj": math.Inf(1)},
} }
t.Run("Should execute function IS_DEFINED(path)", func(t *testing.T) { t.Run("Should execute function IS_DEFINED(path)", func(t *testing.T) {
@ -21,13 +27,13 @@ func Test_Execute_TypeCheckingFunctions(t *testing.T) {
SelectItems: []parsers.SelectItem{ SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}}, {Path: []string{"c", "id"}},
{ {
Alias: "defined", Alias: "IsDefined",
Type: parsers.SelectItemTypeFunctionCall, Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{ Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsDefined, Type: parsers.FunctionCallIsDefined,
Arguments: []interface{}{ Arguments: []interface{}{
parsers.SelectItem{ parsers.SelectItem{
Path: []string{"c", "pk"}, Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField, Type: parsers.SelectItemTypeField,
}, },
}, },
@ -38,9 +44,338 @@ func Test_Execute_TypeCheckingFunctions(t *testing.T) {
}, },
mockData, mockData,
[]memoryexecutor.RowType{ []memoryexecutor.RowType{
map[string]interface{}{"id": "123", "defined": true}, map[string]interface{}{"id": "1", "IsDefined": false},
map[string]interface{}{"id": "456", "defined": false}, map[string]interface{}{"id": "2", "IsDefined": true},
map[string]interface{}{"id": "789", "defined": true}, map[string]interface{}{"id": "3", "IsDefined": true},
map[string]interface{}{"id": "4", "IsDefined": true},
map[string]interface{}{"id": "5", "IsDefined": true},
map[string]interface{}{"id": "6", "IsDefined": true},
map[string]interface{}{"id": "7", "IsDefined": true},
map[string]interface{}{"id": "8", "IsDefined": true},
},
)
})
t.Run("Should execute function IS_ARRAY(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsArray",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsArray,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsArray": false},
map[string]interface{}{"id": "2", "IsArray": false},
map[string]interface{}{"id": "3", "IsArray": false},
map[string]interface{}{"id": "4", "IsArray": false},
map[string]interface{}{"id": "5", "IsArray": false},
map[string]interface{}{"id": "6", "IsArray": true},
map[string]interface{}{"id": "7", "IsArray": false},
map[string]interface{}{"id": "8", "IsArray": false},
},
)
})
t.Run("Should execute function IS_BOOL(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsBool",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsBool,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsBool": false},
map[string]interface{}{"id": "2", "IsBool": false},
map[string]interface{}{"id": "3", "IsBool": false},
map[string]interface{}{"id": "4", "IsBool": false},
map[string]interface{}{"id": "5", "IsBool": true},
map[string]interface{}{"id": "6", "IsBool": false},
map[string]interface{}{"id": "7", "IsBool": false},
map[string]interface{}{"id": "8", "IsBool": false},
},
)
})
t.Run("Should execute function IS_FINITENUMBER(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsFiniteNumber",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsFiniteNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsFiniteNumber": false},
map[string]interface{}{"id": "2", "IsFiniteNumber": false},
map[string]interface{}{"id": "3", "IsFiniteNumber": true},
map[string]interface{}{"id": "4", "IsFiniteNumber": true},
map[string]interface{}{"id": "5", "IsFiniteNumber": false},
map[string]interface{}{"id": "6", "IsFiniteNumber": false},
map[string]interface{}{"id": "7", "IsFiniteNumber": false},
map[string]interface{}{"id": "8", "IsFiniteNumber": false},
},
)
})
t.Run("Should execute function IS_INTEGER(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsInteger",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsInteger,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsInteger": false},
map[string]interface{}{"id": "2", "IsInteger": false},
map[string]interface{}{"id": "3", "IsInteger": true},
map[string]interface{}{"id": "4", "IsInteger": false},
map[string]interface{}{"id": "5", "IsInteger": false},
map[string]interface{}{"id": "6", "IsInteger": false},
map[string]interface{}{"id": "7", "IsInteger": false},
map[string]interface{}{"id": "8", "IsInteger": false},
},
)
})
t.Run("Should execute function IS_NULL(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsNull",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNull,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsNull": true},
map[string]interface{}{"id": "2", "IsNull": false},
map[string]interface{}{"id": "3", "IsNull": false},
map[string]interface{}{"id": "4", "IsNull": false},
map[string]interface{}{"id": "5", "IsNull": false},
map[string]interface{}{"id": "6", "IsNull": false},
map[string]interface{}{"id": "7", "IsNull": false},
map[string]interface{}{"id": "8", "IsNull": false},
},
)
})
t.Run("Should execute function IS_NUMBER(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsNumber",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsNumber,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsNumber": false},
map[string]interface{}{"id": "2", "IsNumber": false},
map[string]interface{}{"id": "3", "IsNumber": true},
map[string]interface{}{"id": "4", "IsNumber": true},
map[string]interface{}{"id": "5", "IsNumber": false},
map[string]interface{}{"id": "6", "IsNumber": false},
map[string]interface{}{"id": "7", "IsNumber": false},
map[string]interface{}{"id": "8", "IsNumber": true},
},
)
})
t.Run("Should execute function IS_OBJECT(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsObject",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsObject,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsObject": false},
map[string]interface{}{"id": "2", "IsObject": false},
map[string]interface{}{"id": "3", "IsObject": false},
map[string]interface{}{"id": "4", "IsObject": false},
map[string]interface{}{"id": "5", "IsObject": false},
map[string]interface{}{"id": "6", "IsObject": false},
map[string]interface{}{"id": "7", "IsObject": true},
map[string]interface{}{"id": "8", "IsObject": false},
},
)
})
t.Run("Should execute function IS_PRIMITIVE(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsPrimitive",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsPrimitive,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsPrimitive": true},
map[string]interface{}{"id": "2", "IsPrimitive": true},
map[string]interface{}{"id": "3", "IsPrimitive": true},
map[string]interface{}{"id": "4", "IsPrimitive": true},
map[string]interface{}{"id": "5", "IsPrimitive": true},
map[string]interface{}{"id": "6", "IsPrimitive": false},
map[string]interface{}{"id": "7", "IsPrimitive": false},
map[string]interface{}{"id": "8", "IsPrimitive": true},
},
)
})
t.Run("Should execute function IS_STRING(path)", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{
Alias: "IsString",
Type: parsers.SelectItemTypeFunctionCall,
Value: parsers.FunctionCall{
Type: parsers.FunctionCallIsString,
Arguments: []interface{}{
parsers.SelectItem{
Path: []string{"c", "obj"},
Type: parsers.SelectItemTypeField,
},
},
},
},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "1", "IsString": false},
map[string]interface{}{"id": "2", "IsString": true},
map[string]interface{}{"id": "3", "IsString": false},
map[string]interface{}{"id": "4", "IsString": false},
map[string]interface{}{"id": "5", "IsString": false},
map[string]interface{}{"id": "6", "IsString": false},
map[string]interface{}{"id": "7", "IsString": false},
map[string]interface{}{"id": "8", "IsString": false},
}, },
) )
}) })