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) {
|
switch (data_type) {
|
||||||
case DataType::BOOL:
|
case DataType::BOOL:
|
||||||
return ParseRangeNodeImpl<bool>(field_name, body);
|
return ParseRangeNodeImpl<bool>(field_name, body);
|
||||||
|
|
||||||
case DataType::INT8:
|
case DataType::INT8:
|
||||||
return ParseRangeNodeImpl<int8_t>(field_name, body);
|
return ParseRangeNodeImpl<int8_t>(field_name, body);
|
||||||
case DataType::INT16:
|
case DataType::INT16:
|
||||||
|
@ -109,6 +110,7 @@ Parser::ParseRangeNode(const Json& out_body) {
|
||||||
return ParseRangeNodeImpl<int32_t>(field_name, body);
|
return ParseRangeNodeImpl<int32_t>(field_name, body);
|
||||||
case DataType::INT64:
|
case DataType::INT64:
|
||||||
return ParseRangeNodeImpl<int64_t>(field_name, body);
|
return ParseRangeNodeImpl<int64_t>(field_name, body);
|
||||||
|
|
||||||
case DataType::FLOAT:
|
case DataType::FLOAT:
|
||||||
return ParseRangeNodeImpl<float>(field_name, body);
|
return ParseRangeNodeImpl<float>(field_name, body);
|
||||||
case DataType::DOUBLE:
|
case DataType::DOUBLE:
|
||||||
|
@ -323,19 +325,32 @@ Parser::ParseRangeNodeImpl(const FieldName& field_name, const Json& body) {
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, bool>) {
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
Assert(item.value().is_boolean());
|
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>) {
|
} else if constexpr (std::is_integral_v<T>) {
|
||||||
Assert(item.value().is_number_integer());
|
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>) {
|
} else if constexpr (std::is_floating_point_v<T>) {
|
||||||
Assert(item.value().is_number());
|
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 {
|
} else {
|
||||||
static_assert(always_false<T>, "unsupported type");
|
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) {
|
} else if (body.size() == 2) {
|
||||||
bool has_lower_value = false;
|
bool has_lower_value = false;
|
||||||
bool has_upper_value = false;
|
bool has_upper_value = false;
|
||||||
|
|
|
@ -279,22 +279,16 @@ ProtoParser::ParseUnaryRangeExpr(const proto::plan::UnaryRangeExpr& expr_pb) {
|
||||||
return ExtractUnaryRangeExprImpl<bool>(
|
return ExtractUnaryRangeExprImpl<bool>(
|
||||||
field_id, data_type, expr_pb);
|
field_id, data_type, expr_pb);
|
||||||
}
|
}
|
||||||
case DataType::INT8: {
|
|
||||||
return ExtractUnaryRangeExprImpl<int8_t>(
|
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||||
field_id, data_type, expr_pb);
|
case DataType::INT8:
|
||||||
}
|
case DataType::INT16:
|
||||||
case DataType::INT16: {
|
case DataType::INT32:
|
||||||
return ExtractUnaryRangeExprImpl<int16_t>(
|
|
||||||
field_id, data_type, expr_pb);
|
|
||||||
}
|
|
||||||
case DataType::INT32: {
|
|
||||||
return ExtractUnaryRangeExprImpl<int32_t>(
|
|
||||||
field_id, data_type, expr_pb);
|
|
||||||
}
|
|
||||||
case DataType::INT64: {
|
case DataType::INT64: {
|
||||||
return ExtractUnaryRangeExprImpl<int64_t>(
|
return ExtractUnaryRangeExprImpl<int64_t>(
|
||||||
field_id, data_type, expr_pb);
|
field_id, data_type, expr_pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case DataType::FLOAT: {
|
case DataType::FLOAT: {
|
||||||
return ExtractUnaryRangeExprImpl<float>(
|
return ExtractUnaryRangeExprImpl<float>(
|
||||||
field_id, data_type, expr_pb);
|
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>>>
|
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||||
inline bool
|
inline bool
|
||||||
out_of_range(int64_t t) {
|
out_of_range(int64_t t) {
|
||||||
return t > std::numeric_limits<T>::max() ||
|
return gt_ub<T>(t) || lt_lb<T>(t);
|
||||||
t < std::numeric_limits<T>::min();
|
|
||||||
}
|
}
|
||||||
} // namespace milvus::query
|
} // namespace milvus::query
|
||||||
|
|
|
@ -82,6 +82,10 @@ class ExecExprVisitor : public ExprVisitor {
|
||||||
IndexFunc index_func,
|
IndexFunc index_func,
|
||||||
ElementFunc element_func) -> BitsetType;
|
ElementFunc element_func) -> BitsetType;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto
|
||||||
|
ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto
|
auto
|
||||||
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||||
|
|
|
@ -66,6 +66,10 @@ class ExecExprVisitor : ExprVisitor {
|
||||||
IndexFunc func,
|
IndexFunc func,
|
||||||
ElementFunc element_func) -> BitsetType;
|
ElementFunc element_func) -> BitsetType;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto
|
||||||
|
ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto
|
auto
|
||||||
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw) -> BitsetType;
|
||||||
|
@ -351,7 +355,7 @@ ExecExprVisitor::ExecDataRangeVisitorImpl(FieldId field_id,
|
||||||
#pragma ide diagnostic ignored "Simplify"
|
#pragma ide diagnostic ignored "Simplify"
|
||||||
template <typename T>
|
template <typename T>
|
||||||
auto
|
auto
|
||||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcher(UnaryRangeExpr& expr_raw)
|
ExecExprVisitor::ExecUnaryRangeVisitorDispatcherImpl(UnaryRangeExpr& expr_raw)
|
||||||
-> BitsetType {
|
-> BitsetType {
|
||||||
typedef std::
|
typedef std::
|
||||||
conditional_t<std::is_same_v<T, std::string_view>, std::string, T>
|
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
|
#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>
|
template <typename ExprValueType>
|
||||||
auto
|
auto
|
||||||
ExecExprVisitor::ExecUnaryRangeVisitorDispatcherJson(UnaryRangeExpr& expr_raw)
|
ExecExprVisitor::ExecUnaryRangeVisitorDispatcherJson(UnaryRangeExpr& expr_raw)
|
||||||
|
|
|
@ -173,18 +173,15 @@ ShowExprVisitor::visit(UnaryRangeExpr& expr) {
|
||||||
case DataType::BOOL:
|
case DataType::BOOL:
|
||||||
json_opt_ = UnaryRangeExtract<bool>(expr);
|
json_opt_ = UnaryRangeExtract<bool>(expr);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// see also: https://github.com/milvus-io/milvus/issues/23646.
|
||||||
case DataType::INT8:
|
case DataType::INT8:
|
||||||
json_opt_ = UnaryRangeExtract<int8_t>(expr);
|
|
||||||
return;
|
|
||||||
case DataType::INT16:
|
case DataType::INT16:
|
||||||
json_opt_ = UnaryRangeExtract<int16_t>(expr);
|
|
||||||
return;
|
|
||||||
case DataType::INT32:
|
case DataType::INT32:
|
||||||
json_opt_ = UnaryRangeExtract<int32_t>(expr);
|
|
||||||
return;
|
|
||||||
case DataType::INT64:
|
case DataType::INT64:
|
||||||
json_opt_ = UnaryRangeExtract<int64_t>(expr);
|
json_opt_ = UnaryRangeExtract<int64_t>(expr);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case DataType::DOUBLE:
|
case DataType::DOUBLE:
|
||||||
json_opt_ = UnaryRangeExtract<double>(expr);
|
json_opt_ = UnaryRangeExtract<double>(expr);
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue