diff --git a/internal/parser/planparserv2/node_ret.go b/internal/parser/planparserv2/node_ret.go index 9d0ca3dd10..a8d32b40e2 100644 --- a/internal/parser/planparserv2/node_ret.go +++ b/internal/parser/planparserv2/node_ret.go @@ -8,6 +8,10 @@ import ( type ExprWithType struct { expr *planpb.Expr dataType schemapb.DataType + // ExprWithType can be a node only when nodeDependent is set to false. + // For example, a column expression or a value expression itself cannot be an expression node independently. + // Unless our execution backend can support them. + nodeDependent bool } func getError(obj interface{}) error { diff --git a/internal/parser/planparserv2/parser_visitor.go b/internal/parser/planparserv2/parser_visitor.go index 966b3bbaf7..40480b2422 100644 --- a/internal/parser/planparserv2/parser_visitor.go +++ b/internal/parser/planparserv2/parser_visitor.go @@ -53,7 +53,8 @@ func (v *ParserVisitor) translateIdentifier(identifier string) (*ExprWithType, e }, }, }, - dataType: field.DataType, + dataType: field.DataType, + nodeDependent: true, }, nil } @@ -83,6 +84,7 @@ func (v *ParserVisitor) VisitBoolean(ctx *parser.BooleanContext) interface{} { }, }, }, + nodeDependent: true, } } @@ -102,6 +104,7 @@ func (v *ParserVisitor) VisitInteger(ctx *parser.IntegerContext) interface{} { }, }, }, + nodeDependent: true, } } @@ -121,6 +124,7 @@ func (v *ParserVisitor) VisitFloating(ctx *parser.FloatingContext) interface{} { }, }, }, + nodeDependent: true, } } @@ -143,6 +147,7 @@ func (v *ParserVisitor) VisitString(ctx *parser.StringContext) interface{} { }, }, }, + nodeDependent: true, } } @@ -213,8 +218,9 @@ func (v *ParserVisitor) VisitAddSub(ctx *parser.AddSubContext) interface{} { return err } return &ExprWithType{ - expr: expr, - dataType: dataType, + expr: expr, + dataType: dataType, + nodeDependent: true, } } @@ -304,8 +310,9 @@ func (v *ParserVisitor) VisitMulDivMod(ctx *parser.MulDivModContext) interface{} return err } return &ExprWithType{ - expr: expr, - dataType: dataType, + expr: expr, + dataType: dataType, + nodeDependent: true, } } @@ -1019,7 +1026,8 @@ func (v *ParserVisitor) VisitJSONIdentifier(ctx *parser.JSONIdentifierContext) i }, }, }, - dataType: jsonField.GetDataType(), + dataType: jsonField.GetDataType(), + nodeDependent: true, } } @@ -1134,6 +1142,7 @@ func (v *ParserVisitor) VisitArray(ctx *parser.ArrayContext) interface{} { }, }, }, + nodeDependent: true, } } diff --git a/internal/parser/planparserv2/plan_parser_v2.go b/internal/parser/planparserv2/plan_parser_v2.go index d4975f97df..a549afadaf 100644 --- a/internal/parser/planparserv2/plan_parser_v2.go +++ b/internal/parser/planparserv2/plan_parser_v2.go @@ -62,7 +62,7 @@ func ParseExpr(schema *typeutil.SchemaHelper, exprStr string) (*planpb.Expr, err if predicate == nil { return nil, fmt.Errorf("cannot parse expression: %s", exprStr) } - if !typeutil.IsBoolType(predicate.dataType) { + if !canBeExecuted(predicate) { return nil, fmt.Errorf("predicate is not a boolean expression: %s, data type: %s", exprStr, predicate.dataType) } diff --git a/internal/parser/planparserv2/plan_parser_v2_test.go b/internal/parser/planparserv2/plan_parser_v2_test.go index 0eb10c3449..afa6da4d57 100644 --- a/internal/parser/planparserv2/plan_parser_v2_test.go +++ b/internal/parser/planparserv2/plan_parser_v2_test.go @@ -474,6 +474,10 @@ func TestExpr_Invalid(t *testing.T) { `1 ** 2`, `1 << 2`, `1 | 2`, + // -------------------- cannot be independent ---------------------- + `BoolField`, + `true`, + `false`, } for _, exprStr := range exprStrs { _, err := ParseExpr(helper, exprStr) diff --git a/internal/parser/planparserv2/utils.go b/internal/parser/planparserv2/utils.go index 831bc05e6f..dbd78bfe29 100644 --- a/internal/parser/planparserv2/utils.go +++ b/internal/parser/planparserv2/utils.go @@ -377,3 +377,7 @@ func IsAlwaysTruePlan(plan *planpb.PlanNode) bool { } return false } + +func canBeExecuted(e *ExprWithType) bool { + return typeutil.IsBoolType(e.dataType) && !e.nodeDependent +} diff --git a/internal/parser/planparserv2/utils_test.go b/internal/parser/planparserv2/utils_test.go index 73d012efe4..aa86b0c26c 100644 --- a/internal/parser/planparserv2/utils_test.go +++ b/internal/parser/planparserv2/utils_test.go @@ -131,3 +131,46 @@ func TestIsAlwaysTruePlan(t *testing.T) { }) } } + +func Test_canBeExecuted(t *testing.T) { + type args struct { + e *ExprWithType + } + tests := []struct { + name string + args args + want bool + }{ + { + args: args{ + e: &ExprWithType{ + dataType: schemapb.DataType_Int64, + }, + }, + want: false, + }, + { + args: args{ + e: &ExprWithType{ + dataType: schemapb.DataType_Bool, + nodeDependent: true, + }, + }, + want: false, + }, + { + args: args{ + e: &ExprWithType{ + dataType: schemapb.DataType_Bool, + nodeDependent: false, + }, + }, + want: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, canBeExecuted(tt.args.e), "canBeExecuted(%v)", tt.args.e) + }) + } +}