Skip to content

Commit

Permalink
Support template to parse expression
Browse files Browse the repository at this point in the history
Signed-off-by: Cai Zhang <[email protected]>
  • Loading branch information
xiaocai2333 committed Oct 24, 2024
1 parent 2abc28e commit 6dbffba
Show file tree
Hide file tree
Showing 29 changed files with 2,844 additions and 1,363 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ replace (
github.com/go-kit/kit => github.com/go-kit/kit v0.1.0
// github.com/milvus-io/milvus-storage/go => ../milvus-storage/go
github.com/ianlancetaylor/cgosymbolizer => github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119
github.com/milvus-io/milvus-proto/go-api/v2 => github.com/xiaocai2333/milvus-proto/go-api/v2 v2.0.0-20241023082201-84555c82bbf5
github.com/milvus-io/milvus/pkg => ./pkg
github.com/streamnative/pulsarctl => github.com/xiaofan-luan/pulsarctl v0.5.1
github.com/tecbot/gorocksdb => github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,10 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xiaocai2333/milvus-proto/go-api/v2 v2.0.0-20241022065545-5c0861132474 h1:1yoYwya6hkC6/KwsDVxMrhsyZ1/vxl5R8zI3QaznCbc=
github.com/xiaocai2333/milvus-proto/go-api/v2 v2.0.0-20241022065545-5c0861132474/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/xiaocai2333/milvus-proto/go-api/v2 v2.0.0-20241023082201-84555c82bbf5 h1:HqO1Z+jq9adLpq3LUodFkHrhd0dYghNh96wtsLKNmT4=
github.com/xiaocai2333/milvus-proto/go-api/v2 v2.0.0-20241023082201-84555c82bbf5/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/xiaofan-luan/pulsarctl v0.5.1 h1:2V+IWFarElzcln5WBbU3VNu3zC8Q7RS6rMpVs9oUfLg=
github.com/xiaofan-luan/pulsarctl v0.5.1/go.mod h1:kfeG1rRglz+QDSxyBB21H2Q4hMnzfirW32bs8yx/Q0Q=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
Expand Down
19 changes: 11 additions & 8 deletions internal/parser/planparserv2/Plan.g4
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ expr:
| FloatingConstant # Floating
| BooleanConstant # Boolean
| StringLiteral # String
| Identifier # Identifier
| (Identifier|Meta) # Identifier
| JSONIdentifier # JSONIdentifier
| LBRACE Identifier RBRACE # TemplateVariable
| '(' expr ')' # Parens
| '[' expr (',' expr)* ','? ']' # Array
| EmptyArray # EmptyArray
| expr LIKE StringLiteral # Like
| expr POW expr # Power
| op = (ADD | SUB | BNOT | NOT) expr # Unary
// | '(' typeName ')' expr # Cast
| expr op = (MUL | DIV | MOD) expr # MulDivMod
| expr op = (ADD | SUB) expr # AddSub
| expr op = (SHL | SHR) expr # Shift
| expr op = (IN | NIN) ('[' expr (',' expr)* ','? ']') # Term
| expr op = (IN | NIN) EmptyTerm # EmptyTerm
| expr op = NOT? IN expr # Term
| (JSONContains | ArrayContains)'('expr',' expr')' # JSONContains
| (JSONContainsAll | ArrayContainsAll)'('expr',' expr')' # JSONContainsAll
| (JSONContainsAny | ArrayContainsAny)'('expr',' expr')' # JSONContainsAny
Expand All @@ -42,6 +43,8 @@ expr:
// INT64: 'int64';
// FLOAT: 'float';
// DOUBLE: 'double';
LBRACE: '{';
RBRACE: '}';

LT: '<';
LE: '<=';
Expand Down Expand Up @@ -71,9 +74,8 @@ OR: '||' | 'or';
BNOT: '~';
NOT: '!' | 'not';

IN: 'in';
NIN: 'not in';
EmptyTerm: '[' (Whitespace | Newline)* ']';
IN: 'in' | 'IN';
EmptyArray: '[' (Whitespace | Newline)* ']';

JSONContains: 'json_contains' | 'JSON_CONTAINS';
JSONContainsAll: 'json_contains_all' | 'JSON_CONTAINS_ALL';
Expand All @@ -96,10 +98,11 @@ FloatingConstant:
DecimalFloatingConstant
| HexadecimalFloatingConstant;

Identifier: Nondigit (Nondigit | Digit)* | '$meta';
Identifier: Nondigit (Nondigit | Digit)*;
Meta: '$meta';

StringLiteral: EncodingPrefix? ('"' DoubleSCharSequence? '"' | '\'' SingleSCharSequence? '\'');
JSONIdentifier: Identifier('[' (StringLiteral | DecimalConstant) ']')+;
JSONIdentifier: (Identifier | Meta)('[' (StringLiteral | DecimalConstant) ']')+;

fragment EncodingPrefix: 'u8' | 'u' | 'U' | 'L';

Expand Down
4 changes: 2 additions & 2 deletions internal/parser/planparserv2/check_identical_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ func TestCheckIdentical(t *testing.T) {
exprStr1 := `not (((Int64Field > 0) and (FloatField <= 20.0)) or ((Int32Field in [1, 2, 3]) and (VarCharField < "str")))`
exprStr2 := `Int32Field in [1, 2, 3]`

expr1, err := ParseExpr(helper, exprStr1)
expr1, err := ParseExpr(helper, exprStr1, nil)
assert.NoError(t, err)
expr2, err := ParseExpr(helper, exprStr2)
expr2, err := ParseExpr(helper, exprStr2, nil)
assert.NoError(t, err)

assert.True(t, CheckPredicatesIdentical(expr1, expr1))
Expand Down
129 changes: 129 additions & 0 deletions internal/parser/planparserv2/convert_field_data_to_generic_value.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package planparserv2

import (
"encoding/json"
"fmt"
"strings"

"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/internal/proto/planpb"
)

func ConvertFieldDataToGenericValue(templateName string, templateValue *schemapb.ScalarField, dataType schemapb.DataType) ([]*planpb.GenericValue, error) {
if templateValue == nil {
return nil, fmt.Errorf("expression template variable values is nil, template name: {%s}", templateName)
}
values := make([]*planpb.GenericValue, 0)
switch dataType {
case schemapb.DataType_Bool:
elements := templateValue.GetBoolData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_BoolVal{
BoolVal: element,
},
})
}
case schemapb.DataType_Int8, schemapb.DataType_Int16, schemapb.DataType_Int32:
elements := templateValue.GetIntData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_Int64Val{
Int64Val: int64(element),
},
})
}
case schemapb.DataType_Int64:
elements := templateValue.GetLongData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_Int64Val{
Int64Val: element,
},
})
}
case schemapb.DataType_Float:
elements := templateValue.GetFloatData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_FloatVal{
FloatVal: float64(element),
},
})
}
case schemapb.DataType_Double:
elements := templateValue.GetDoubleData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_FloatVal{
FloatVal: element,
},
})
}
case schemapb.DataType_String, schemapb.DataType_VarChar:
elements := templateValue.GetStringData().GetData()
for _, element := range elements {
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_StringVal{
StringVal: element,
},
})
}
case schemapb.DataType_Array:
elements := templateValue.GetArrayData().GetData()
for _, element := range elements {
arrayElements, err := ConvertFieldDataToGenericValue("", element, templateValue.GetArrayData().GetElementType())
if err != nil {
return nil, err
}
values = append(values, &planpb.GenericValue{
Val: &planpb.GenericValue_ArrayVal{
ArrayVal: &planpb.Array{
Array: arrayElements,
SameType: templateValue.GetArrayData().GetElementType() != schemapb.DataType_JSON,
ElementType: templateValue.GetArrayData().GetElementType(),
},
},
})
}
case schemapb.DataType_JSON:
elements := templateValue.GetJsonData().GetData()
for _, element := range elements {
var j interface{}
desc := json.NewDecoder(strings.NewReader(string(element)))
desc.UseNumber()
err := desc.Decode(&j)
if err != nil {
return nil, err
}
value, _, err := parseJSONValue(j)
if err != nil {
return nil, err
}
values = append(values, value)
}
default:
return nil, fmt.Errorf("expression elements can only be scalars")

}

return values, nil
}

func UnmarshalExpressionValues(input []*schemapb.FieldData) (map[string]*planpb.GenericValue, error) {
result := make(map[string]*planpb.GenericValue, len(input))
for _, data := range input {
if _, ok := result[data.GetFieldName()]; ok {
return nil, fmt.Errorf("the number of elements in the template variable name is incorrect: {%s}", data.GetFieldName())
}
rv, err := ConvertFieldDataToGenericValue(data.GetFieldName(), data.GetScalars(), data.GetType())
if err != nil {
return nil, err
}
if len(rv) != 1 {
return nil, fmt.Errorf("the number of elements in the template variable name is incorrect: {%s}", data.GetFieldName())
}
result[data.GetFieldName()] = rv[0]
}
return result, nil
}
Loading

0 comments on commit 6dbffba

Please sign in to comment.