mirror of https://github.com/milvus-io/milvus.git
Fix UnaryRange expression on integer overflow case (#24893)
Signed-off-by: longjiquan <jiquan.long@zilliz.com>pull/24909/head
parent
7f7fe85592
commit
7faf934f91
|
@ -101,6 +101,7 @@ Parser::ParseRangeNode(const Json& out_body) {
|
|||
switch (data_type) {
|
||||
case DataType::BOOL:
|
||||
return ParseRangeNodeImpl<bool>(field_name, body);
|
||||
|
||||
case DataType::INT8:
|
||||
return ParseRangeNodeImpl<int8_t>(field_name, body);
|
||||
case DataType::INT16:
|
||||
|
@ -109,6 +110,7 @@ Parser::ParseRangeNode(const Json& out_body) {
|
|||
return ParseRangeNodeImpl<int32_t>(field_name, body);
|
||||
case DataType::INT64:
|
||||
return ParseRangeNodeImpl<int64_t>(field_name, body);
|
||||
|
||||
case DataType::FLOAT:
|
||||
return ParseRangeNodeImpl<float>(field_name, body);
|
||||
case DataType::DOUBLE:
|
||||
|
@ -323,19 +325,32 @@ Parser::ParseRangeNodeImpl(const FieldName& field_name, const Json& body) {
|
|||
|
||||
if constexpr (std::is_same_v<T, bool>) {
|
||||
Assert(item.value().is_boolean());
|
||||
return std::make_unique<UnaryRangeExprImpl<T>>(
|
||||
ColumnInfo(schema.get_field_id(field_name),
|
||||
schema[field_name].get_data_type()),
|
||||
mapping_.at(op_name),
|
||||
item.value(),
|
||||
proto::plan::GenericValue::ValCase::kBoolVal);
|
||||
} else if constexpr (std::is_integral_v<T>) {
|
||||
Assert(item.value().is_number_integer());
|
||||
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||
return std::make_unique<UnaryRangeExprImpl<int64_t>>(
|
||||
ColumnInfo(schema.get_field_id(field_name),
|
||||
schema[field_name].get_data_type()),
|
||||
mapping_.at(op_name),
|
||||
item.value(),
|
||||
proto::plan::GenericValue::ValCase::kInt64Val);
|
||||
} else if constexpr (std::is_floating_point_v<T>) {
|
||||
Assert(item.value().is_number());
|
||||
return std::make_unique<UnaryRangeExprImpl<T>>(
|
||||
ColumnInfo(schema.get_field_id(field_name),
|
||||
schema[field_name].get_data_type()),
|
||||
mapping_.at(op_name),
|
||||
item.value(),
|
||||
proto::plan::GenericValue::ValCase::kFloatVal);
|
||||
} else {
|
||||
static_assert(always_false<T>, "unsupported type");
|
||||
}
|
||||
return std::make_unique<UnaryRangeExprImpl<T>>(
|
||||
ColumnInfo(schema.get_field_id(field_name),
|
||||
schema[field_name].get_data_type()),
|
||||
mapping_.at(op_name),
|
||||
item.value(),
|
||||
proto::plan::GenericValue::ValCase::VAL_NOT_SET);
|
||||
} else if (body.size() == 2) {
|
||||
bool has_lower_value = false;
|
||||
bool has_upper_value = false;
|
||||
|
|
|
@ -279,22 +279,16 @@ ProtoParser::ParseUnaryRangeExpr(const proto::plan::UnaryRangeExpr& expr_pb) {
|
|||
return ExtractUnaryRangeExprImpl<bool>(
|
||||
field_id, data_type, expr_pb);
|
||||
}
|
||||
case DataType::INT8: {
|
||||
return ExtractUnaryRangeExprImpl<int8_t>(
|
||||
field_id, data_type, expr_pb);
|
||||
}
|
||||
case DataType::INT16: {
|
||||
return ExtractUnaryRangeExprImpl<int16_t>(
|
||||
field_id, data_type, expr_pb);
|
||||
}
|
||||
case DataType::INT32: {
|
||||
return ExtractUnaryRangeExprImpl<int32_t>(
|
||||
field_id, data_type, expr_pb);
|
||||
}
|
||||
|
||||
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||
case DataType::INT8:
|
||||
case DataType::INT16:
|
||||
case DataType::INT32:
|
||||
case DataType::INT64: {
|
||||
return ExtractUnaryRangeExprImpl<int64_t>(
|
||||
field_id, data_type, expr_pb);
|
||||
}
|
||||
|
||||
case DataType::FLOAT: {
|
||||
return ExtractUnaryRangeExprImpl<float>(
|
||||
field_id, data_type, expr_pb);
|
||||
|
|
|
@ -53,10 +53,21 @@ Match<std::string_view>(const std::string_view& str,
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
inline bool
|
||||
gt_ub(int64_t t) {
|
||||
return t > std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
inline bool
|
||||
lt_lb(int64_t t) {
|
||||
return t < std::numeric_limits<T>::min();
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||
inline bool
|
||||
out_of_range(int64_t t) {
|
||||
return t > std::numeric_limits<T>::max() ||
|
||||
t < std::numeric_limits<T>::min();
|
||||
return gt_ub<T>(t) || lt_lb<T>(t);
|
||||
}
|
||||
} // namespace milvus::query
|
||||
|
|
|
@ -82,6 +82,10 @@ class ExecExprVisitor : public ExprVisitor {
|
|||
IndexFunc index_func,
|
||||
ElementFunc element_func) -> BitsetType;
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||
|
|
|
@ -66,6 +66,10 @@ class ExecExprVisitor : ExprVisitor {
|
|||
IndexFunc func,
|
||||
ElementFunc element_func) -> BitsetType;
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||
|
@ -351,7 +355,7 @@ ExecExprVisitor::ExecDataRangeVisitorImpl(FieldId field_id,
|
|||
#pragma ide diagnostic ignored "Simplify"
|
||||
template <typename T>
|
||||
auto
|
||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw)
|
||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw)
|
||||
-> BitsetType {
|
||||
typedef std::
|
||||
conditional_t<std::is_same_v<T, std::string_view>, std::string, T>
|
||||
|
@ -423,6 +427,58 @@ ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw)
|
|||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw)
|
||||
-> BitsetType {
|
||||
if constexpr (std::is_integral_v<T>) {
|
||||
auto& expr = static_cast<UnaryRangeExprImpl<int64_t>&>(expr_raw);
|
||||
auto val = expr.value_;
|
||||
|
||||
if (!out_of_range<T>(val)) {
|
||||
return ExecUnaryRangeVisitorDispatcherImpl<T>(expr_raw);
|
||||
}
|
||||
|
||||
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||
switch (expr.op_type_) {
|
||||
case proto::plan::GreaterThan:
|
||||
case proto::plan::GreaterEqual: {
|
||||
BitsetType r(row_count_);
|
||||
if (lt_lb<T>(val)) {
|
||||
r.set();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
case proto::plan::LessThan:
|
||||
case proto::plan::LessEqual: {
|
||||
BitsetType r(row_count_);
|
||||
if (gt_ub<T>(val)) {
|
||||
r.set();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
case proto::plan::Equal: {
|
||||
BitsetType r(row_count_);
|
||||
r.reset();
|
||||
return r;
|
||||
}
|
||||
|
||||
case proto::plan::NotEqual: {
|
||||
BitsetType r(row_count_);
|
||||
r.set();
|
||||
return r;
|
||||
}
|
||||
|
||||
default: {
|
||||
PanicInfo("unsupported range node");
|
||||
}
|
||||
}
|
||||
}
|
||||
return ExecUnaryRangeVisitorDispatcherImpl<T>(expr_raw);
|
||||
}
|
||||
|
||||
template <typename ExprValueType>
|
||||
auto
|
||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcherJson(UnaryRangeExpr& expr_raw)
|
||||
|
|
|
@ -173,18 +173,15 @@ ShowExprVisitor::visit(UnaryRangeExpr& expr) {
|
|||
case DataType::BOOL:
|
||||
json_opt_ = UnaryRangeExtract<bool>(expr);
|
||||
return;
|
||||
|
||||
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||
case DataType::INT8:
|
||||
json_opt_ = UnaryRangeExtract<int8_t>(expr);
|
||||
return;
|
||||
case DataType::INT16:
|
||||
json_opt_ = UnaryRangeExtract<int16_t>(expr);
|
||||
return;
|
||||
case DataType::INT32:
|
||||
json_opt_ = UnaryRangeExtract<int32_t>(expr);
|
||||
return;
|
||||
case DataType::INT64:
|
||||
json_opt_ = UnaryRangeExtract<int64_t>(expr);
|
||||
return;
|
||||
|
||||
case DataType::DOUBLE:
|
||||
json_opt_ = UnaryRangeExtract<double>(expr);
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue