mirror of
https://gitee.com/milvus-io/milvus.git
synced 2026-01-03 17:31:58 +08:00
**What type of PR is this?**
- [x] Feature
**What this PR does / why we need it:**
This PR supports boolean expression as DSL.
1. The goal of this PR is to support predicates
like `A > 3 && not B < 5 or C in [1, 2, 3]`.
2. Defines `plan.proto`, as Intermediate Representation (IR)
used between go and cpp.
3. Support expr parser, convert predicate expr to IR
in proxynode, while doing static check there
4. Support IR to AST in cpp, enable the execution
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
package proxynode
|
|
|
|
import (
|
|
"testing"
|
|
|
|
ant_ast "github.com/antonmedv/expr/ast"
|
|
ant_parser "github.com/antonmedv/expr/parser"
|
|
|
|
"github.com/golang/protobuf/proto"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/milvus-io/milvus/internal/proto/planpb"
|
|
"github.com/milvus-io/milvus/internal/proto/schemapb"
|
|
"github.com/milvus-io/milvus/internal/util/typeutil"
|
|
)
|
|
|
|
func newTestSchema() *schemapb.CollectionSchema {
|
|
return &schemapb.CollectionSchema{
|
|
Name: "test",
|
|
Description: "schema for test used",
|
|
AutoID: true,
|
|
Fields: []*schemapb.FieldSchema{
|
|
{FieldID: 0, Name: "FieldID", IsPrimaryKey: false, Description: "field no.1", DataType: schemapb.DataType_Int64},
|
|
{FieldID: 101, Name: "vectorField", IsPrimaryKey: false, Description: "field no.2", DataType: schemapb.DataType_FloatVector},
|
|
{FieldID: 100, Name: "int64Field", IsPrimaryKey: false, Description: "field no.1", DataType: schemapb.DataType_Int64},
|
|
},
|
|
}
|
|
}
|
|
|
|
func TestParseQueryExpr_Naive(t *testing.T) {
|
|
exprStr := "int64Field > 3"
|
|
schemaPb := newTestSchema()
|
|
schema, err := typeutil.CreateSchemaHelper(schemaPb)
|
|
assert.Nil(t, err)
|
|
exprProto, err := parseQueryExpr(schema, &exprStr)
|
|
assert.Nil(t, err)
|
|
str := proto.MarshalTextString(exprProto)
|
|
println(str)
|
|
}
|
|
|
|
func TestParsePlanNode_Naive(t *testing.T) {
|
|
exprStr := "int64Field > 3"
|
|
schema := newTestSchema()
|
|
queryInfo := &planpb.QueryInfo{
|
|
Topk: 10,
|
|
MetricType: "L2",
|
|
SearchParams: "{\"nprobe\": 10}",
|
|
}
|
|
|
|
// Note: use pointer to string to represent nullable string
|
|
// TODO: change it to better solution
|
|
planProto, err := CreateQueryPlan(schema, &exprStr, "vectorField", queryInfo)
|
|
|
|
assert.Nil(t, err)
|
|
dbgStr := proto.MarshalTextString(planProto)
|
|
println(dbgStr)
|
|
}
|
|
|
|
func TestExternalParser(t *testing.T) {
|
|
ast, err := ant_parser.Parse("!(1 < a < 2 or b in [1, 2, 3]) or (c < 3 and b > 5) or ")
|
|
|
|
var node ant_ast.Node = nil
|
|
if node == nil {
|
|
// TODO
|
|
}
|
|
assert.Nil(t, err)
|
|
|
|
println(ast.Node.Location().Column)
|
|
}
|