enhance: Support more relational operators for binary expressions (#30902)

issue: #30677

Signed-off-by: Cai Zhang <cai.zhang@zilliz.com>
This commit is contained in:
cai.zhang 2024-03-01 16:57:00 +08:00 committed by GitHub
parent ee8d6f236c
commit 1aa97a5c21
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 3037 additions and 119 deletions

View File

@ -119,7 +119,10 @@ PhyBinaryArithOpEvalRangeExpr::ExecRangeVisitorImplForJson() {
auto op_type = expr_->op_type_;
auto arith_type = expr_->arith_op_type_;
auto value = GetValueFromProto<ValueType>(expr_->value_);
auto right_operand = GetValueFromProto<ValueType>(expr_->right_operand_);
auto right_operand =
arith_type != proto::plan::ArithOpType::ArrayLength
? GetValueFromProto<ValueType>(expr_->right_operand_)
: ValueType();
#define BinaryArithRangeJSONCompare(cmp) \
do { \
@ -260,6 +263,202 @@ PhyBinaryArithOpEvalRangeExpr::ExecRangeVisitorImplForJson() {
}
break;
}
case proto::plan::OpType::GreaterThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeJSONCompare(x.value() + right_operand >
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeJSONCompare(x.value() - right_operand >
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeJSONCompare(x.value() * right_operand >
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeJSONCompare(x.value() / right_operand >
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeJSONCompare(
static_cast<ValueType>(
fmod(x.value(), right_operand)) > val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
int array_length = 0;
auto doc = data[i].doc();
auto array = doc.at_pointer(pointer).get_array();
if (!array.error()) {
array_length = array.count_elements();
}
res[i] = array_length > val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::GreaterEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeJSONCompare(x.value() + right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeJSONCompare(x.value() - right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeJSONCompare(x.value() * right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeJSONCompare(x.value() / right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeJSONCompare(
static_cast<ValueType>(
fmod(x.value(), right_operand)) >= val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
int array_length = 0;
auto doc = data[i].doc();
auto array = doc.at_pointer(pointer).get_array();
if (!array.error()) {
array_length = array.count_elements();
}
res[i] = array_length >= val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeJSONCompare(x.value() + right_operand <
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeJSONCompare(x.value() - right_operand <
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeJSONCompare(x.value() * right_operand <
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeJSONCompare(x.value() / right_operand <
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeJSONCompare(
static_cast<ValueType>(
fmod(x.value(), right_operand)) < val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
int array_length = 0;
auto doc = data[i].doc();
auto array = doc.at_pointer(pointer).get_array();
if (!array.error()) {
array_length = array.count_elements();
}
res[i] = array_length < val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeJSONCompare(x.value() + right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeJSONCompare(x.value() - right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeJSONCompare(x.value() * right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeJSONCompare(x.value() / right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeJSONCompare(
static_cast<ValueType>(
fmod(x.value(), right_operand)) <= val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
int array_length = 0;
auto doc = data[i].doc();
auto array = doc.at_pointer(pointer).get_array();
if (!array.error()) {
array_length = array.count_elements();
}
res[i] = array_length <= val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
default:
PanicInfo(OpTypeInvalid,
"unsupported operator type for binary "
@ -413,6 +612,178 @@ PhyBinaryArithOpEvalRangeExpr::ExecRangeVisitorImplForArray() {
}
break;
}
case proto::plan::OpType::GreaterThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeArrayCompare(value + right_operand >
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeArrayCompare(value - right_operand >
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeArrayCompare(value * right_operand >
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeArrayCompare(value / right_operand >
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeArrayCompare(
static_cast<ValueType>(fmod(value, right_operand)) >
val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
res[i] = data[i].length() > val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::GreaterEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeArrayCompare(value + right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeArrayCompare(value - right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeArrayCompare(value * right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeArrayCompare(value / right_operand >=
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeArrayCompare(
static_cast<ValueType>(
fmod(value, right_operand)) >= val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
res[i] = data[i].length() >= val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeArrayCompare(value + right_operand <
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeArrayCompare(value - right_operand <
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeArrayCompare(value * right_operand <
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeArrayCompare(value / right_operand <
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeArrayCompare(
static_cast<ValueType>(fmod(value, right_operand)) <
val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
res[i] = data[i].length() < val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
BinaryArithRangeArrayCompare(value + right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Sub: {
BinaryArithRangeArrayCompare(value - right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Mul: {
BinaryArithRangeArrayCompare(value * right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Div: {
BinaryArithRangeArrayCompare(value / right_operand <=
val);
break;
}
case proto::plan::ArithOpType::Mod: {
BinaryArithRangeArrayCompare(
static_cast<ValueType>(
fmod(value, right_operand)) <= val);
break;
}
case proto::plan::ArithOpType::ArrayLength: {
for (size_t i = 0; i < size; ++i) {
res[i] = data[i].length() <= val;
}
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
default:
PanicInfo(OpTypeInvalid,
"unsupported operator type for binary "
@ -579,6 +950,230 @@ PhyBinaryArithOpEvalRangeExpr::ExecRangeVisitorImplForIndex() {
}
break;
}
case proto::plan::OpType::GreaterThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Add>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Sub>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Mul>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Div>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Mod>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::GreaterEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Add>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Sub>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Mul>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Div>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpIndexFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Mod>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Add>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Sub>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Mul>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Div>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Mod>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Add>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Sub>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Mul>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Div>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpIndexFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Mod>
func;
res = std::move(func(
index_ptr, sub_batch_size, value, right_operand));
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
default:
PanicInfo(OpTypeInvalid,
"unsupported operator type for binary "
@ -727,6 +1322,210 @@ PhyBinaryArithOpEvalRangeExpr::ExecRangeVisitorImplForData() {
}
break;
}
case proto::plan::OpType::GreaterThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Add>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Sub>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Mul>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Div>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterThan,
proto::plan::ArithOpType::Mod>
func;
func(data, size, value, right_operand, res);
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::GreaterEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Add>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Sub>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Mul>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Div>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpElementFunc<T,
proto::plan::OpType::GreaterEqual,
proto::plan::ArithOpType::Mod>
func;
func(data, size, value, right_operand, res);
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessThan: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpElementFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Add>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpElementFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Sub>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpElementFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Mul>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpElementFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Div>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpElementFunc<T,
proto::plan::OpType::LessThan,
proto::plan::ArithOpType::Mod>
func;
func(data, size, value, right_operand, res);
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
case proto::plan::OpType::LessEqual: {
switch (arith_type) {
case proto::plan::ArithOpType::Add: {
ArithOpElementFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Add>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Sub: {
ArithOpElementFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Sub>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mul: {
ArithOpElementFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Mul>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Div: {
ArithOpElementFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Div>
func;
func(data, size, value, right_operand, res);
break;
}
case proto::plan::ArithOpType::Mod: {
ArithOpElementFunc<T,
proto::plan::OpType::LessEqual,
proto::plan::ArithOpType::Mod>
func;
func(data, size, value, right_operand, res);
break;
}
default:
PanicInfo(
OpTypeInvalid,
fmt::format("unsupported arith type for binary "
"arithmetic eval expr: {}",
arith_type));
}
break;
}
default:
PanicInfo(OpTypeInvalid,
"unsupported operator type for binary "

View File

@ -88,6 +88,94 @@ struct ArithOpElementFunc {
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::GreaterThan) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (src[i] + right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (src[i] - right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (src[i] * right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (src[i] / right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] = (fmod(src[i], right_operand)) > val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::GreaterEqual) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (src[i] + right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (src[i] - right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (src[i] * right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (src[i] / right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] = (fmod(src[i], right_operand)) >= val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::LessThan) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (src[i] + right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (src[i] - right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (src[i] * right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (src[i] / right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] = (fmod(src[i], right_operand)) < val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::LessEqual) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (src[i] + right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (src[i] - right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (src[i] * right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (src[i] / right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] = (fmod(src[i], right_operand)) <= val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
}
}
}
@ -157,6 +245,98 @@ struct ArithOpIndexFunc {
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::GreaterThan) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (index->Reverse_Lookup(i) + right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (index->Reverse_Lookup(i) - right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (index->Reverse_Lookup(i) * right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (index->Reverse_Lookup(i) / right_operand) > val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] =
(fmod(index->Reverse_Lookup(i), right_operand)) > val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::GreaterEqual) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (index->Reverse_Lookup(i) + right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (index->Reverse_Lookup(i) - right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (index->Reverse_Lookup(i) * right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (index->Reverse_Lookup(i) / right_operand) >= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] =
(fmod(index->Reverse_Lookup(i), right_operand)) >= val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::LessThan) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (index->Reverse_Lookup(i) + right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (index->Reverse_Lookup(i) - right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (index->Reverse_Lookup(i) * right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (index->Reverse_Lookup(i) / right_operand) < val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] =
(fmod(index->Reverse_Lookup(i), right_operand)) < val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
} else if constexpr (cmp_op == proto::plan::OpType::LessEqual) {
if constexpr (arith_op == proto::plan::ArithOpType::Add) {
res[i] = (index->Reverse_Lookup(i) + right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Sub) {
res[i] = (index->Reverse_Lookup(i) - right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mul) {
res[i] = (index->Reverse_Lookup(i) * right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Div) {
res[i] = (index->Reverse_Lookup(i) / right_operand) <= val;
} else if constexpr (arith_op ==
proto::plan::ArithOpType::Mod) {
res[i] =
(fmod(index->Reverse_Lookup(i), right_operand)) <= val;
} else {
PanicInfo(
OpTypeInvalid,
fmt::format(
"unsupported arith type:{} for ArithOpElementFunc",
arith_op));
}
}
}
return res_vec;

View File

@ -1274,6 +1274,74 @@ TEST(Expr, TestArrayBinaryArith) {
auto val = array.get_data<int64_t>(0);
return val + 2 != 5;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
nested_path:"0"
element_type:Int8
>
arith_op:Add
right_operand:<int64_val:2 >
op:GreaterThan
value:<int64_val:5 >
>)",
"int",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val + 2 > 5;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
nested_path:"0"
element_type:Int8
>
arith_op:Add
right_operand:<int64_val:2 >
op:GreaterEqual
value:<int64_val:5 >
>)",
"int",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val + 2 >= 5;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
nested_path:"0"
element_type:Int8
>
arith_op:Add
right_operand:<int64_val:2 >
op:LessThan
value:<int64_val:5 >
>)",
"int",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val + 2 < 5;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
nested_path:"0"
element_type:Int8
>
arith_op:Add
right_operand:<int64_val:2 >
op:LessEqual
value:<int64_val:5 >
>)",
"int",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val + 2 <= 5;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
@ -1308,6 +1376,74 @@ TEST(Expr, TestArrayBinaryArith) {
auto val = array.get_data<int64_t>(0);
return val - 1 != 144;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Sub
right_operand:<int64_val:1 >
op:GreaterThan
value:<int64_val:144 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val - 1 > 144;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Sub
right_operand:<int64_val:1 >
op:GreaterEqual
value:<int64_val:144 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val - 1 >= 144;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Sub
right_operand:<int64_val:1 >
op:LessThan
value:<int64_val:144 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val - 1 < 144;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Sub
right_operand:<int64_val:1 >
op:LessEqual
value:<int64_val:144 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val - 1 <= 144;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 103
@ -1410,6 +1546,74 @@ TEST(Expr, TestArrayBinaryArith) {
auto val = array.get_data<int64_t>(0);
return val * 2 != 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mul
right_operand:<int64_val:2 >
op:GreaterThan
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val * 2 > 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mul
right_operand:<int64_val:2 >
op:GreaterEqual
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val * 2 >= 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mul
right_operand:<int64_val:2 >
op:LessThan
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val * 2 < 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mul
right_operand:<int64_val:2 >
op:LessEqual
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val * 2 <= 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
@ -1444,6 +1648,74 @@ TEST(Expr, TestArrayBinaryArith) {
auto val = array.get_data<int64_t>(0);
return val / 2 != 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Div
right_operand:<int64_val:2 >
op:GreaterThan
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val / 2 > 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Div
right_operand:<int64_val:2 >
op:GreaterEqual
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val / 2 >= 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Div
right_operand:<int64_val:2 >
op:LessThan
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val / 2 < 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Div
right_operand:<int64_val:2 >
op:LessEqual
value:<int64_val:20 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val / 2 <= 20;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
@ -1478,6 +1750,74 @@ TEST(Expr, TestArrayBinaryArith) {
auto val = array.get_data<int64_t>(0);
return val % 3 != 2;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mod
right_operand:<int64_val:3 >
op:GreaterThan
value:<int64_val:2 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val % 3 > 2;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mod
right_operand:<int64_val:3 >
op:GreaterEqual
value:<int64_val:2 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val % 3 >= 2;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mod
right_operand:<int64_val:3 >
op:LessThan
value:<int64_val:2 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val % 3 < 2;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 102
data_type: Array
nested_path:"0"
element_type:Int64
>
arith_op:Mod
right_operand:<int64_val:3 >
op:LessEqual
value:<int64_val:2 >
>)",
"long",
[](milvus::Array& array) {
auto val = array.get_data<int64_t>(0);
return val % 3 <= 2;
}},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 103
@ -1704,6 +2044,54 @@ TEST(Expr, TestArrayBinaryArith) {
>)",
"int",
[](milvus::Array& array) { return array.length() != 8; }},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
element_type:Int8
>
arith_op:ArrayLength
op:GreaterThan
value:<int64_val:8 >
>)",
"int",
[](milvus::Array& array) { return array.length() > 8; }},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
element_type:Int8
>
arith_op:ArrayLength
op:GreaterEqual
value:<int64_val:8 >
>)",
"int",
[](milvus::Array& array) { return array.length() >= 8; }},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
element_type:Int8
>
arith_op:ArrayLength
op:LessThan
value:<int64_val:8 >
>)",
"int",
[](milvus::Array& array) { return array.length() < 8; }},
{R"(binary_arith_op_eval_range_expr: <
column_info: <
field_id: 101
data_type: Array
element_type:Int8
>
arith_op:ArrayLength
op:LessEqual
value:<int64_val:8 >
>)",
"int",
[](milvus::Array& array) { return array.length() <= 8; }},
};
std::string raw_plan_tmp = R"(vector_anns: <

File diff suppressed because it is too large Load Diff

View File

@ -218,6 +218,15 @@ func TestExpr_BinaryArith(t *testing.T) {
`Int64Field % 10 != 9`,
`Int64Field + 1.1 == 2.1`,
`A % 10 != 2`,
`Int8Field + 1 < 2`,
`Int16Field - 3 <= 4`,
`Int32Field * 5 > 6`,
`Int64Field / 7 >= 8`,
`FloatField + 11 < 12`,
`DoubleField - 13 <= 14`,
`A * 15 > 16`,
`JSONField['A'] / 17 >= 18`,
`ArrayField[0] % 19 >= 20`,
}
for _, exprStr := range exprStrs {
assertValidExpr(t, helper, exprStr)
@ -225,13 +234,6 @@ func TestExpr_BinaryArith(t *testing.T) {
// TODO: enable these after execution backend is ready.
unsupported := []string{
`Int8Field + 1 < 2`,
`Int16Field - 3 <= 4`,
`Int32Field * 5 > 6`,
`Int64Field / 7 >= 8`,
`FloatField + 11 < 12`,
`DoubleField - 13 < 14`,
`A - 15 < 16`,
`JSONField + 15 == 16`,
`15 + JSONField == 16`,
`ArrayField + 15 == 16`,
@ -1172,6 +1174,10 @@ func Test_ArrayLength(t *testing.T) {
`array_length(B) != 1`,
`not (array_length(C[0]) == 1)`,
`not (array_length(C["D"]) != 1)`,
`array_length(StringArrayField) < 1`,
`array_length(StringArrayField) <= 1`,
`array_length(StringArrayField) > 5`,
`array_length(StringArrayField) >= 5`,
}
for _, expr = range exprs {
_, err = CreateSearchPlan(schema, expr, "FloatVectorField", &planpb.QueryInfo{
@ -1193,7 +1199,6 @@ func Test_ArrayLength(t *testing.T) {
`0 < array_length(a-b) < 2`,
`0 < array_length(StringArrayField) < 1`,
`100 > array_length(ArrayField) > 10`,
`array_length(StringArrayField) < 1`,
`array_length(A) % 10 == 2`,
`array_length(A) / 10 == 2`,
`array_length(A) + 1 == 2`,

View File

@ -259,14 +259,6 @@ func combineArrayLengthExpr(op planpb.OpType, arithOp planpb.ArithOpType, column
}
func handleBinaryArithExpr(op planpb.OpType, arithExpr *planpb.BinaryArithExpr, valueExpr *planpb.ValueExpr) (*planpb.Expr, error) {
switch op {
case planpb.OpType_Equal, planpb.OpType_NotEqual:
break
default:
// TODO: enable this after execution is ready.
return nil, fmt.Errorf("%s is not supported in execution backend", op)
}
leftExpr, leftValue := arithExpr.Left.GetColumnExpr(), arithExpr.Left.GetValueExpr()
rightExpr, rightValue := arithExpr.Right.GetColumnExpr(), arithExpr.Right.GetValueExpr()
arithOp := arithExpr.GetOp()

View File

@ -0,0 +1,240 @@
// Licensed to the LF AI & Data foundation under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package expression
import (
"context"
"encoding/json"
"fmt"
"testing"
"github.com/golang/protobuf/proto"
"github.com/stretchr/testify/suite"
"go.uber.org/zap"
"github.com/milvus-io/milvus-proto/go-api/v2/milvuspb"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/pkg/common"
"github.com/milvus-io/milvus/pkg/log"
"github.com/milvus-io/milvus/pkg/util/funcutil"
"github.com/milvus-io/milvus/pkg/util/merr"
"github.com/milvus-io/milvus/pkg/util/metric"
"github.com/milvus-io/milvus/tests/integration"
)
type ExpressionSuite struct {
integration.MiniClusterSuite
dbName string
collectionName string
dim int
rowNum int
}
func (s *ExpressionSuite) setParams() {
prefix := "TestExpression"
s.dbName = ""
s.collectionName = prefix + funcutil.GenRandomStr()
s.dim = 128
s.rowNum = 100
}
func newJSONData(fieldName string, rowNum int) *schemapb.FieldData {
jsonData := make([][]byte, 0, rowNum)
for i := 0; i < rowNum; i++ {
data := map[string]interface{}{
"A": i,
"B": rowNum - i,
"C": []int{i, rowNum - i},
"D": fmt.Sprintf("name-%d", i),
"E": map[string]interface{}{
"F": i,
"G": i + 10,
},
"str1": `abc\"def-` + string(rune(i)),
"str2": fmt.Sprintf("abc\"def-%d", i),
"str3": fmt.Sprintf("abc\ndef-%d", i),
"str4": fmt.Sprintf("abc\367-%d", i),
}
if i%2 == 0 {
data = map[string]interface{}{
"B": rowNum - i,
"C": []int{i, rowNum - i},
"D": fmt.Sprintf("name-%d", i),
"E": map[string]interface{}{
"F": i,
"G": i + 10,
},
}
}
if i == 100 {
data = nil
}
jsonBytes, err := json.MarshalIndent(data, "", " ")
if err != nil {
return nil
}
jsonData = append(jsonData, jsonBytes)
}
return &schemapb.FieldData{
Type: schemapb.DataType_JSON,
FieldName: fieldName,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_JsonData{
JsonData: &schemapb.JSONArray{
Data: jsonData,
},
},
},
},
}
}
func (s *ExpressionSuite) insertFlushIndexLoad(ctx context.Context, fieldData []*schemapb.FieldData) {
hashKeys := integration.GenerateHashKeys(s.rowNum)
insertResult, err := s.Cluster.Proxy.Insert(ctx, &milvuspb.InsertRequest{
DbName: s.dbName,
CollectionName: s.collectionName,
FieldsData: fieldData,
HashKeys: hashKeys,
NumRows: uint32(s.rowNum),
})
s.NoError(err)
s.NoError(merr.Error(insertResult.GetStatus()))
// flush
flushResp, err := s.Cluster.Proxy.Flush(ctx, &milvuspb.FlushRequest{
DbName: s.dbName,
CollectionNames: []string{s.collectionName},
})
s.NoError(err)
segmentIDs, has := flushResp.GetCollSegIDs()[s.collectionName]
ids := segmentIDs.GetData()
s.Require().NotEmpty(segmentIDs)
s.Require().True(has)
flushTs, has := flushResp.GetCollFlushTs()[s.collectionName]
s.True(has)
segments, err := s.Cluster.MetaWatcher.ShowSegments()
s.NoError(err)
s.NotEmpty(segments)
for _, segment := range segments {
log.Info("ShowSegments result", zap.String("segment", segment.String()))
}
s.WaitForFlush(ctx, ids, flushTs, s.dbName, s.collectionName)
// create index
createIndexStatus, err := s.Cluster.Proxy.CreateIndex(context.TODO(), &milvuspb.CreateIndexRequest{
CollectionName: s.collectionName,
FieldName: integration.FloatVecField,
IndexName: "_default",
ExtraParams: integration.ConstructIndexParam(s.dim, integration.IndexFaissIvfFlat, metric.IP),
})
s.NoError(err)
err = merr.Error(createIndexStatus)
s.NoError(err)
s.WaitForIndexBuilt(context.TODO(), s.collectionName, integration.FloatVecField)
log.Info("=========================Index created=========================")
// load
loadStatus, err := s.Cluster.Proxy.LoadCollection(ctx, &milvuspb.LoadCollectionRequest{
DbName: s.dbName,
CollectionName: s.collectionName,
})
s.NoError(err)
err = merr.Error(loadStatus)
s.NoError(err)
s.WaitForLoad(context.TODO(), s.collectionName)
log.Info("=========================Collection loaded=========================")
}
func (s *ExpressionSuite) setupData() {
c := s.Cluster
ctx, cancel := context.WithCancel(c.GetContext())
defer cancel()
schema := integration.ConstructSchema(s.collectionName, s.dim, true)
schema.EnableDynamicField = true
marshaledSchema, err := proto.Marshal(schema)
s.NoError(err)
createCollectionStatus, err := c.Proxy.CreateCollection(ctx, &milvuspb.CreateCollectionRequest{
DbName: s.dbName,
CollectionName: s.collectionName,
Schema: marshaledSchema,
ShardsNum: 2,
})
s.NoError(err)
err = merr.Error(createCollectionStatus)
s.NoError(err)
showCollectionsResp, err := c.Proxy.ShowCollections(ctx, &milvuspb.ShowCollectionsRequest{})
s.NoError(err)
err = merr.Error(showCollectionsResp.GetStatus())
s.NoError(err)
describeCollectionResp, err := c.Proxy.DescribeCollection(ctx, &milvuspb.DescribeCollectionRequest{CollectionName: s.collectionName})
s.NoError(err)
err = merr.Error(describeCollectionResp.GetStatus())
s.NoError(err)
s.True(describeCollectionResp.Schema.EnableDynamicField)
s.Equal(2, len(describeCollectionResp.GetSchema().GetFields()))
fVecColumn := integration.NewFloatVectorFieldData(integration.FloatVecField, s.rowNum, s.dim)
jsonData := newJSONData(common.MetaFieldName, s.rowNum)
jsonData.IsDynamic = true
s.insertFlushIndexLoad(ctx, []*schemapb.FieldData{fVecColumn, jsonData})
}
type testCase struct {
expr string
topK int
resNum int
}
func (s *ExpressionSuite) searchWithExpression() {
testcases := []testCase{
{"A + 5 > 0", 10, 10},
{"B - 5 >= 0", 10, 10},
{"C[0] * 5 < 500", 10, 10},
{"E['F'] / 5 <= 100", 10, 10},
{"E['G'] % 5 == 4", 10, 10},
{"A / 5 != 4", 10, 10},
}
for _, c := range testcases {
params := integration.GetSearchParams(integration.IndexFaissIDMap, metric.IP)
searchReq := integration.ConstructSearchRequest(s.dbName, s.collectionName, c.expr,
integration.FloatVecField, schemapb.DataType_FloatVector, nil, metric.IP, params, 1, s.dim, c.topK, -1)
searchResult, err := s.Cluster.Proxy.Search(context.Background(), searchReq)
s.NoError(err)
err = merr.Error(searchResult.GetStatus())
s.NoError(err)
s.Equal(c.resNum, len(searchResult.GetResults().GetScores()))
log.Info(fmt.Sprintf("=========================Search done with expr:%s =========================", c.expr))
}
}
func (s *ExpressionSuite) TestExpression() {
s.setParams()
s.setupData()
s.searchWithExpression()
}
func TestExpression(t *testing.T) {
suite.Run(t, new(ExpressionSuite))
}

View File

@ -627,12 +627,8 @@ class TestCollectionSearchInvalid(TestcaseBase):
# 2. search
expression = "int32_array[0] - 1 < 1"
error = {ct.err_code: 65535,
ct.err_msg: f"failed to create query plan: cannot parse expression: {expression}, "
f"error: LessThan is not supported in execution backend"}
collection_w.search(vectors[:default_nq], default_search_field,
default_search_params, nb, expression,
check_task=CheckTasks.err_res, check_items=error)
default_search_params, nb, expression)
@pytest.mark.tags(CaseLabel.L2)
def test_search_partition_invalid_type(self, get_invalid_partition):