package planparserv2 import ( "fmt" "github.com/milvus-io/milvus-proto/go-api/schemapb" "github.com/milvus-io/milvus/internal/proto/planpb" "github.com/milvus-io/milvus/internal/util/typeutil" "github.com/antlr/antlr4/runtime/Go/antlr" ) func handleExpr(schema *typeutil.SchemaHelper, exprStr string) interface{} { if exprStr == "" { return nil } inputStream := antlr.NewInputStream(exprStr) errorListener := &errorListener{} lexer := getLexer(inputStream, errorListener) if errorListener.err != nil { return errorListener.err } parser := getParser(lexer, errorListener) if errorListener.err != nil { return errorListener.err } ast := parser.Expr() if errorListener.err != nil { return errorListener.err } // lexer & parser won't be used by this thread, can be put into pool. putLexer(lexer) putParser(parser) visitor := NewParserVisitor(schema) return ast.Accept(visitor) } func ParseExpr(schema *typeutil.SchemaHelper, exprStr string) (*planpb.Expr, error) { if len(exprStr) <= 0 { return nil, nil } ret := handleExpr(schema, exprStr) if err := getError(ret); err != nil { return nil, fmt.Errorf("cannot parse expression: %s, error: %s", exprStr, err) } predicate := getExpr(ret) if predicate == nil { return nil, fmt.Errorf("cannot parse expression: %s", exprStr) } if !typeutil.IsBoolType(predicate.dataType) { return nil, fmt.Errorf("predicate is not a boolean expression: %s, data type: %s", exprStr, predicate.dataType) } return predicate.expr, nil } func CreateRetrievePlan(schemaPb *schemapb.CollectionSchema, exprStr string) (*planpb.PlanNode, error) { schema, err := typeutil.CreateSchemaHelper(schemaPb) if err != nil { return nil, err } expr, err := ParseExpr(schema, exprStr) if err != nil { return nil, err } planNode := &planpb.PlanNode{ Node: &planpb.PlanNode_Predicates{ Predicates: expr, }, } return planNode, nil } func CreateSearchPlan(schemaPb *schemapb.CollectionSchema, exprStr string, vectorFieldName string, queryInfo *planpb.QueryInfo) (*planpb.PlanNode, error) { schema, err := typeutil.CreateSchemaHelper(schemaPb) if err != nil { return nil, err } expr, err := ParseExpr(schema, exprStr) if err != nil { return nil, err } vectorField, err := schema.GetFieldFromName(vectorFieldName) if err != nil { return nil, err } fieldID := vectorField.FieldID dataType := vectorField.DataType if !typeutil.IsVectorType(dataType) { return nil, fmt.Errorf("field (%s) to search is not of vector data type", vectorFieldName) } planNode := &planpb.PlanNode{ Node: &planpb.PlanNode_VectorAnns{ VectorAnns: &planpb.VectorANNS{ IsBinary: dataType == schemapb.DataType_BinaryVector, Predicates: expr, QueryInfo: queryInfo, PlaceholderTag: "$0", FieldId: fieldID, }, }, } return planNode, nil }