Support TermExpr, NotExpr, LogicalExpr (#5096)

1. Support Term, like `A in [1, 2, 3]`
2. Support Not, like `! A < 3`
3. Support logical combination, like `A < 3 && B > 5 or C == 0`

Type: Feature

Signed-off-by: fluorinedog <fluorinedog@gmail.com>
This commit is contained in:
FluorineDog 2021-04-30 15:19:52 +08:00 committed by GitHub
parent b46ae44087
commit 396b3f33e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 1242 additions and 247 deletions

View File

@ -83,6 +83,30 @@ datatype_is_vector(DataType datatype) {
return datatype == DataType::VECTOR_BINARY || datatype == DataType::VECTOR_FLOAT; return datatype == DataType::VECTOR_BINARY || datatype == DataType::VECTOR_FLOAT;
} }
inline bool
datatype_is_interger(DataType datatype) {
switch (datatype) {
case DataType::INT8:
case DataType::INT16:
case DataType::INT32:
case DataType::INT64:
return true;
default:
return false;
}
}
inline bool
datatype_is_floating(DataType datatype) {
switch (datatype) {
case DataType::DOUBLE:
case DataType::FLOAT:
return true;
default:
return false;
}
}
class FieldMeta { class FieldMeta {
public: public:
FieldMeta(const FieldMeta&) = delete; FieldMeta(const FieldMeta&) = delete;

View File

@ -15,9 +15,8 @@
#include <google/protobuf/wire_format.h> #include <google/protobuf/wire_format.h>
// @@protoc_insertion_point(includes) // @@protoc_insertion_point(includes)
#include <google/protobuf/port_def.inc> #include <google/protobuf/port_def.inc>
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BinaryExpr_plan_2eproto; extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_BinaryExpr_plan_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ColumnInfo_plan_2eproto; extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ColumnInfo_plan_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Expr_plan_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GenericValue_plan_2eproto; extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_GenericValue_plan_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_QueryInfo_plan_2eproto; extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_QueryInfo_plan_2eproto;
extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_RangeExpr_plan_2eproto; extern PROTOBUF_INTERNAL_EXPORT_plan_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_RangeExpr_plan_2eproto;
@ -80,16 +79,30 @@ class PlanNodeDefaultTypeInternal {
static void InitDefaultsscc_info_BinaryExpr_plan_2eproto() { static void InitDefaultsscc_info_BinaryExpr_plan_2eproto() {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
{
void* ptr = &::milvus::proto::plan::_UnaryExpr_default_instance_;
new (ptr) ::milvus::proto::plan::UnaryExpr();
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
}
{ {
void* ptr = &::milvus::proto::plan::_BinaryExpr_default_instance_; void* ptr = &::milvus::proto::plan::_BinaryExpr_default_instance_;
new (ptr) ::milvus::proto::plan::BinaryExpr(); new (ptr) ::milvus::proto::plan::BinaryExpr();
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr); ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
} }
{
void* ptr = &::milvus::proto::plan::_Expr_default_instance_;
new (ptr) ::milvus::proto::plan::Expr();
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
}
::milvus::proto::plan::UnaryExpr::InitAsDefaultInstance();
::milvus::proto::plan::BinaryExpr::InitAsDefaultInstance(); ::milvus::proto::plan::BinaryExpr::InitAsDefaultInstance();
::milvus::proto::plan::Expr::InitAsDefaultInstance();
} }
::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_BinaryExpr_plan_2eproto = ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_BinaryExpr_plan_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_BinaryExpr_plan_2eproto}, {}}; {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsscc_info_BinaryExpr_plan_2eproto}, {
&scc_info_RangeExpr_plan_2eproto.base,
&scc_info_TermExpr_plan_2eproto.base,}};
static void InitDefaultsscc_info_ColumnInfo_plan_2eproto() { static void InitDefaultsscc_info_ColumnInfo_plan_2eproto() {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
@ -105,29 +118,6 @@ static void InitDefaultsscc_info_ColumnInfo_plan_2eproto() {
::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ColumnInfo_plan_2eproto = ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ColumnInfo_plan_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_ColumnInfo_plan_2eproto}, {}}; {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsscc_info_ColumnInfo_plan_2eproto}, {}};
static void InitDefaultsscc_info_Expr_plan_2eproto() {
GOOGLE_PROTOBUF_VERIFY_VERSION;
{
void* ptr = &::milvus::proto::plan::_UnaryExpr_default_instance_;
new (ptr) ::milvus::proto::plan::UnaryExpr();
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
}
{
void* ptr = &::milvus::proto::plan::_Expr_default_instance_;
new (ptr) ::milvus::proto::plan::Expr();
::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
}
::milvus::proto::plan::UnaryExpr::InitAsDefaultInstance();
::milvus::proto::plan::Expr::InitAsDefaultInstance();
}
::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<3> scc_info_Expr_plan_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 3, InitDefaultsscc_info_Expr_plan_2eproto}, {
&scc_info_RangeExpr_plan_2eproto.base,
&scc_info_TermExpr_plan_2eproto.base,
&scc_info_BinaryExpr_plan_2eproto.base,}};
static void InitDefaultsscc_info_GenericValue_plan_2eproto() { static void InitDefaultsscc_info_GenericValue_plan_2eproto() {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
@ -216,7 +206,7 @@ static void InitDefaultsscc_info_VectorANNS_plan_2eproto() {
::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_VectorANNS_plan_2eproto = ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_VectorANNS_plan_2eproto =
{{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsscc_info_VectorANNS_plan_2eproto}, { {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, InitDefaultsscc_info_VectorANNS_plan_2eproto}, {
&scc_info_Expr_plan_2eproto.base, &scc_info_BinaryExpr_plan_2eproto.base,
&scc_info_QueryInfo_plan_2eproto.base,}}; &scc_info_QueryInfo_plan_2eproto.base,}};
static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_plan_2eproto[10]; static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_plan_2eproto[10];
@ -275,6 +265,9 @@ const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_plan_2eproto::offsets[] PROTOB
~0u, // no _extensions_ ~0u, // no _extensions_
~0u, // no _oneof_case_ ~0u, // no _oneof_case_
~0u, // no _weak_field_map_ ~0u, // no _weak_field_map_
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::BinaryExpr, op_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::BinaryExpr, left_),
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::BinaryExpr, right_),
~0u, // no _has_bits_ ~0u, // no _has_bits_
PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::Expr, _internal_metadata_), PROTOBUF_FIELD_OFFSET(::milvus::proto::plan::Expr, _internal_metadata_),
~0u, // no _extensions_ ~0u, // no _extensions_
@ -311,9 +304,9 @@ static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOB
{ 32, -1, sizeof(::milvus::proto::plan::TermExpr)}, { 32, -1, sizeof(::milvus::proto::plan::TermExpr)},
{ 39, -1, sizeof(::milvus::proto::plan::UnaryExpr)}, { 39, -1, sizeof(::milvus::proto::plan::UnaryExpr)},
{ 46, -1, sizeof(::milvus::proto::plan::BinaryExpr)}, { 46, -1, sizeof(::milvus::proto::plan::BinaryExpr)},
{ 51, -1, sizeof(::milvus::proto::plan::Expr)}, { 54, -1, sizeof(::milvus::proto::plan::Expr)},
{ 61, -1, sizeof(::milvus::proto::plan::VectorANNS)}, { 64, -1, sizeof(::milvus::proto::plan::VectorANNS)},
{ 71, -1, sizeof(::milvus::proto::plan::PlanNode)}, { 74, -1, sizeof(::milvus::proto::plan::PlanNode)},
}; };
static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
@ -350,30 +343,32 @@ const char descriptor_table_protodef_plan_2eproto[] PROTOBUF_SECTION_VARIABLE(pr
"aryExpr\0220\n\002op\030\001 \001(\0162$.milvus.proto.plan." "aryExpr\0220\n\002op\030\001 \001(\0162$.milvus.proto.plan."
"UnaryExpr.UnaryOp\022&\n\005child\030\002 \001(\0132\027.milvu" "UnaryExpr.UnaryOp\022&\n\005child\030\002 \001(\0132\027.milvu"
"s.proto.plan.Expr\"\037\n\007UnaryOp\022\013\n\007Invalid\020" "s.proto.plan.Expr\"\037\n\007UnaryOp\022\013\n\007Invalid\020"
"\000\022\007\n\003Not\020\001\"D\n\nBinaryExpr\"6\n\010BinaryOp\022\013\n\007" "\000\022\007\n\003Not\020\001\"\307\001\n\nBinaryExpr\0222\n\002op\030\001 \001(\0162&."
"Invalid\020\000\022\016\n\nLogicalAnd\020\001\022\r\n\tLogicalOr\020\002" "milvus.proto.plan.BinaryExpr.BinaryOp\022%\n"
"\"\336\001\n\004Expr\0222\n\nrange_expr\030\001 \001(\0132\034.milvus.p" "\004left\030\002 \001(\0132\027.milvus.proto.plan.Expr\022&\n\005"
"roto.plan.RangeExprH\000\0220\n\tterm_expr\030\002 \001(\013" "right\030\003 \001(\0132\027.milvus.proto.plan.Expr\"6\n\010"
"2\033.milvus.proto.plan.TermExprH\000\0222\n\nunary" "BinaryOp\022\013\n\007Invalid\020\000\022\016\n\nLogicalAnd\020\001\022\r\n"
"_expr\030\003 \001(\0132\034.milvus.proto.plan.UnaryExp" "\tLogicalOr\020\002\"\336\001\n\004Expr\0222\n\nrange_expr\030\001 \001("
"rH\000\0224\n\013binary_expr\030\004 \001(\0132\035.milvus.proto." "\0132\034.milvus.proto.plan.RangeExprH\000\0220\n\tter"
"plan.BinaryExprH\000B\006\n\004expr\"\251\001\n\nVectorANNS" "m_expr\030\002 \001(\0132\033.milvus.proto.plan.TermExp"
"\022\021\n\tis_binary\030\001 \001(\010\022\020\n\010field_id\030\002 \001(\003\022+\n" "rH\000\0222\n\nunary_expr\030\003 \001(\0132\034.milvus.proto.p"
"\npredicates\030\003 \001(\0132\027.milvus.proto.plan.Ex" "lan.UnaryExprH\000\0224\n\013binary_expr\030\004 \001(\0132\035.m"
"pr\0220\n\nquery_info\030\004 \001(\0132\034.milvus.proto.pl" "ilvus.proto.plan.BinaryExprH\000B\006\n\004expr\"\251\001"
"an.QueryInfo\022\027\n\017placeholder_tag\030\005 \001(\t\"H\n" "\n\nVectorANNS\022\021\n\tis_binary\030\001 \001(\010\022\020\n\010field"
"\010PlanNode\0224\n\013vector_anns\030\001 \001(\0132\035.milvus." "_id\030\002 \001(\003\022+\n\npredicates\030\003 \001(\0132\027.milvus.p"
"proto.plan.VectorANNSH\000B\006\n\004nodeB3Z1githu" "roto.plan.Expr\0220\n\nquery_info\030\004 \001(\0132\034.mil"
"b.com/milvus-io/milvus/internal/proto/pl" "vus.proto.plan.QueryInfo\022\027\n\017placeholder_"
"anpbb\006proto3" "tag\030\005 \001(\t\"H\n\010PlanNode\0224\n\013vector_anns\030\001 \001"
"(\0132\035.milvus.proto.plan.VectorANNSH\000B\006\n\004n"
"odeB3Z1github.com/milvus-io/milvus/inter"
"nal/proto/planpbb\006proto3"
; ;
static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_plan_2eproto_deps[1] = { static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_plan_2eproto_deps[1] = {
&::descriptor_table_schema_2eproto, &::descriptor_table_schema_2eproto,
}; };
static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_plan_2eproto_sccs[9] = { static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_plan_2eproto_sccs[8] = {
&scc_info_BinaryExpr_plan_2eproto.base, &scc_info_BinaryExpr_plan_2eproto.base,
&scc_info_ColumnInfo_plan_2eproto.base, &scc_info_ColumnInfo_plan_2eproto.base,
&scc_info_Expr_plan_2eproto.base,
&scc_info_GenericValue_plan_2eproto.base, &scc_info_GenericValue_plan_2eproto.base,
&scc_info_PlanNode_plan_2eproto.base, &scc_info_PlanNode_plan_2eproto.base,
&scc_info_QueryInfo_plan_2eproto.base, &scc_info_QueryInfo_plan_2eproto.base,
@ -384,8 +379,8 @@ static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_pla
static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_plan_2eproto_once; static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_plan_2eproto_once;
static bool descriptor_table_plan_2eproto_initialized = false; static bool descriptor_table_plan_2eproto_initialized = false;
const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_plan_2eproto = { const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_plan_2eproto = {
&descriptor_table_plan_2eproto_initialized, descriptor_table_protodef_plan_2eproto, "plan.proto", 1412, &descriptor_table_plan_2eproto_initialized, descriptor_table_protodef_plan_2eproto, "plan.proto", 1544,
&descriptor_table_plan_2eproto_once, descriptor_table_plan_2eproto_sccs, descriptor_table_plan_2eproto_deps, 9, 1, &descriptor_table_plan_2eproto_once, descriptor_table_plan_2eproto_sccs, descriptor_table_plan_2eproto_deps, 8, 1,
schemas, file_default_instances, TableStruct_plan_2eproto::offsets, schemas, file_default_instances, TableStruct_plan_2eproto::offsets,
file_level_metadata_plan_2eproto, 10, file_level_enum_descriptors_plan_2eproto, file_level_service_descriptors_plan_2eproto, file_level_metadata_plan_2eproto, 10, file_level_enum_descriptors_plan_2eproto, file_level_service_descriptors_plan_2eproto,
}; };
@ -2295,7 +2290,7 @@ UnaryExpr::UnaryExpr(const UnaryExpr& from)
} }
void UnaryExpr::SharedCtor() { void UnaryExpr::SharedCtor() {
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Expr_plan_2eproto.base); ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_BinaryExpr_plan_2eproto.base);
::memset(&child_, 0, static_cast<size_t>( ::memset(&child_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&op_) - reinterpret_cast<char*>(&op_) -
reinterpret_cast<char*>(&child_)) + sizeof(op_)); reinterpret_cast<char*>(&child_)) + sizeof(op_));
@ -2314,7 +2309,7 @@ void UnaryExpr::SetCachedSize(int size) const {
_cached_size_.Set(size); _cached_size_.Set(size);
} }
const UnaryExpr& UnaryExpr::default_instance() { const UnaryExpr& UnaryExpr::default_instance() {
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Expr_plan_2eproto.base); ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BinaryExpr_plan_2eproto.base);
return *internal_default_instance(); return *internal_default_instance();
} }
@ -2578,11 +2573,25 @@ void UnaryExpr::InternalSwap(UnaryExpr* other) {
// =================================================================== // ===================================================================
void BinaryExpr::InitAsDefaultInstance() { void BinaryExpr::InitAsDefaultInstance() {
::milvus::proto::plan::_BinaryExpr_default_instance_._instance.get_mutable()->left_ = const_cast< ::milvus::proto::plan::Expr*>(
::milvus::proto::plan::Expr::internal_default_instance());
::milvus::proto::plan::_BinaryExpr_default_instance_._instance.get_mutable()->right_ = const_cast< ::milvus::proto::plan::Expr*>(
::milvus::proto::plan::Expr::internal_default_instance());
} }
class BinaryExpr::_Internal { class BinaryExpr::_Internal {
public: public:
static const ::milvus::proto::plan::Expr& left(const BinaryExpr* msg);
static const ::milvus::proto::plan::Expr& right(const BinaryExpr* msg);
}; };
const ::milvus::proto::plan::Expr&
BinaryExpr::_Internal::left(const BinaryExpr* msg) {
return *msg->left_;
}
const ::milvus::proto::plan::Expr&
BinaryExpr::_Internal::right(const BinaryExpr* msg) {
return *msg->right_;
}
BinaryExpr::BinaryExpr() BinaryExpr::BinaryExpr()
: ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) { : ::PROTOBUF_NAMESPACE_ID::Message(), _internal_metadata_(nullptr) {
SharedCtor(); SharedCtor();
@ -2592,10 +2601,25 @@ BinaryExpr::BinaryExpr(const BinaryExpr& from)
: ::PROTOBUF_NAMESPACE_ID::Message(), : ::PROTOBUF_NAMESPACE_ID::Message(),
_internal_metadata_(nullptr) { _internal_metadata_(nullptr) {
_internal_metadata_.MergeFrom(from._internal_metadata_); _internal_metadata_.MergeFrom(from._internal_metadata_);
if (from.has_left()) {
left_ = new ::milvus::proto::plan::Expr(*from.left_);
} else {
left_ = nullptr;
}
if (from.has_right()) {
right_ = new ::milvus::proto::plan::Expr(*from.right_);
} else {
right_ = nullptr;
}
op_ = from.op_;
// @@protoc_insertion_point(copy_constructor:milvus.proto.plan.BinaryExpr) // @@protoc_insertion_point(copy_constructor:milvus.proto.plan.BinaryExpr)
} }
void BinaryExpr::SharedCtor() { void BinaryExpr::SharedCtor() {
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_BinaryExpr_plan_2eproto.base);
::memset(&left_, 0, static_cast<size_t>(
reinterpret_cast<char*>(&op_) -
reinterpret_cast<char*>(&left_)) + sizeof(op_));
} }
BinaryExpr::~BinaryExpr() { BinaryExpr::~BinaryExpr() {
@ -2604,6 +2628,8 @@ BinaryExpr::~BinaryExpr() {
} }
void BinaryExpr::SharedDtor() { void BinaryExpr::SharedDtor() {
if (this != internal_default_instance()) delete left_;
if (this != internal_default_instance()) delete right_;
} }
void BinaryExpr::SetCachedSize(int size) const { void BinaryExpr::SetCachedSize(int size) const {
@ -2621,6 +2647,15 @@ void BinaryExpr::Clear() {
// Prevent compiler warnings about cached_has_bits being unused // Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits; (void) cached_has_bits;
if (GetArenaNoVirtual() == nullptr && left_ != nullptr) {
delete left_;
}
left_ = nullptr;
if (GetArenaNoVirtual() == nullptr && right_ != nullptr) {
delete right_;
}
right_ = nullptr;
op_ = 0;
_internal_metadata_.Clear(); _internal_metadata_.Clear();
} }
@ -2632,7 +2667,30 @@ const char* BinaryExpr::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID:
ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
CHK_(ptr); CHK_(ptr);
switch (tag >> 3) { switch (tag >> 3) {
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
case 1:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) {
::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint(&ptr);
CHK_(ptr);
set_op(static_cast<::milvus::proto::plan::BinaryExpr_BinaryOp>(val));
} else goto handle_unusual;
continue;
// .milvus.proto.plan.Expr left = 2;
case 2:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
ptr = ctx->ParseMessage(mutable_left(), ptr);
CHK_(ptr);
} else goto handle_unusual;
continue;
// .milvus.proto.plan.Expr right = 3;
case 3:
if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) {
ptr = ctx->ParseMessage(mutable_right(), ptr);
CHK_(ptr);
} else goto handle_unusual;
continue;
default: { default: {
handle_unusual:
if ((tag & 7) == 4 || tag == 0) { if ((tag & 7) == 4 || tag == 0) {
ctx->SetLastTag(tag); ctx->SetLastTag(tag);
goto success; goto success;
@ -2660,12 +2718,53 @@ bool BinaryExpr::MergePartialFromCodedStream(
::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); ::std::pair<::PROTOBUF_NAMESPACE_ID::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u);
tag = p.first; tag = p.first;
if (!p.second) goto handle_unusual; if (!p.second) goto handle_unusual;
switch (::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::GetTagFieldNumber(tag)) {
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
case 1: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (8 & 0xFF)) {
int value = 0;
DO_((::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadPrimitive<
int, ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::TYPE_ENUM>(
input, &value)));
set_op(static_cast< ::milvus::proto::plan::BinaryExpr_BinaryOp >(value));
} else {
goto handle_unusual;
}
break;
}
// .milvus.proto.plan.Expr left = 2;
case 2: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (18 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
input, mutable_left()));
} else {
goto handle_unusual;
}
break;
}
// .milvus.proto.plan.Expr right = 3;
case 3: {
if (static_cast< ::PROTOBUF_NAMESPACE_ID::uint8>(tag) == (26 & 0xFF)) {
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::ReadMessage(
input, mutable_right()));
} else {
goto handle_unusual;
}
break;
}
default: {
handle_unusual: handle_unusual:
if (tag == 0) { if (tag == 0) {
goto success; goto success;
} }
DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField( DO_(::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SkipField(
input, tag, _internal_metadata_.mutable_unknown_fields())); input, tag, _internal_metadata_.mutable_unknown_fields()));
break;
}
}
} }
success: success:
// @@protoc_insertion_point(parse_success:milvus.proto.plan.BinaryExpr) // @@protoc_insertion_point(parse_success:milvus.proto.plan.BinaryExpr)
@ -2683,6 +2782,24 @@ void BinaryExpr::SerializeWithCachedSizes(
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits; (void) cached_has_bits;
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
if (this->op() != 0) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnum(
1, this->op(), output);
}
// .milvus.proto.plan.Expr left = 2;
if (this->has_left()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray(
2, _Internal::left(this), output);
}
// .milvus.proto.plan.Expr right = 3;
if (this->has_right()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteMessageMaybeToArray(
3, _Internal::right(this), output);
}
if (_internal_metadata_.have_unknown_fields()) { if (_internal_metadata_.have_unknown_fields()) {
::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields( ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFields(
_internal_metadata_.unknown_fields(), output); _internal_metadata_.unknown_fields(), output);
@ -2696,6 +2813,26 @@ void BinaryExpr::SerializeWithCachedSizes(
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits; (void) cached_has_bits;
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
if (this->op() != 0) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
1, this->op(), target);
}
// .milvus.proto.plan.Expr left = 2;
if (this->has_left()) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(
2, _Internal::left(this), target);
}
// .milvus.proto.plan.Expr right = 3;
if (this->has_right()) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
InternalWriteMessageToArray(
3, _Internal::right(this), target);
}
if (_internal_metadata_.have_unknown_fields()) { if (_internal_metadata_.have_unknown_fields()) {
target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray( target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SerializeUnknownFieldsToArray(
_internal_metadata_.unknown_fields(), target); _internal_metadata_.unknown_fields(), target);
@ -2717,6 +2854,26 @@ size_t BinaryExpr::ByteSizeLong() const {
// Prevent compiler warnings about cached_has_bits being unused // Prevent compiler warnings about cached_has_bits being unused
(void) cached_has_bits; (void) cached_has_bits;
// .milvus.proto.plan.Expr left = 2;
if (this->has_left()) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
*left_);
}
// .milvus.proto.plan.Expr right = 3;
if (this->has_right()) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
*right_);
}
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
if (this->op() != 0) {
total_size += 1 +
::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->op());
}
int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size); int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
SetCachedSize(cached_size); SetCachedSize(cached_size);
return total_size; return total_size;
@ -2744,6 +2901,15 @@ void BinaryExpr::MergeFrom(const BinaryExpr& from) {
::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0; ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
(void) cached_has_bits; (void) cached_has_bits;
if (from.has_left()) {
mutable_left()->::milvus::proto::plan::Expr::MergeFrom(from.left());
}
if (from.has_right()) {
mutable_right()->::milvus::proto::plan::Expr::MergeFrom(from.right());
}
if (from.op() != 0) {
set_op(from.op());
}
} }
void BinaryExpr::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) { void BinaryExpr::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
@ -2767,6 +2933,9 @@ bool BinaryExpr::IsInitialized() const {
void BinaryExpr::InternalSwap(BinaryExpr* other) { void BinaryExpr::InternalSwap(BinaryExpr* other) {
using std::swap; using std::swap;
_internal_metadata_.Swap(&other->_internal_metadata_); _internal_metadata_.Swap(&other->_internal_metadata_);
swap(left_, other->left_);
swap(right_, other->right_);
swap(op_, other->op_);
} }
::PROTOBUF_NAMESPACE_ID::Metadata BinaryExpr::GetMetadata() const { ::PROTOBUF_NAMESPACE_ID::Metadata BinaryExpr::GetMetadata() const {
@ -2901,7 +3070,7 @@ Expr::Expr(const Expr& from)
} }
void Expr::SharedCtor() { void Expr::SharedCtor() {
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Expr_plan_2eproto.base); ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_BinaryExpr_plan_2eproto.base);
clear_has_expr(); clear_has_expr();
} }
@ -2920,7 +3089,7 @@ void Expr::SetCachedSize(int size) const {
_cached_size_.Set(size); _cached_size_.Set(size);
} }
const Expr& Expr::default_instance() { const Expr& Expr::default_instance() {
::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Expr_plan_2eproto.base); ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_BinaryExpr_plan_2eproto.base);
return *internal_default_instance(); return *internal_default_instance();
} }

View File

@ -1321,11 +1321,40 @@ class BinaryExpr :
// accessors ------------------------------------------------------- // accessors -------------------------------------------------------
enum : int {
kLeftFieldNumber = 2,
kRightFieldNumber = 3,
kOpFieldNumber = 1,
};
// .milvus.proto.plan.Expr left = 2;
bool has_left() const;
void clear_left();
const ::milvus::proto::plan::Expr& left() const;
::milvus::proto::plan::Expr* release_left();
::milvus::proto::plan::Expr* mutable_left();
void set_allocated_left(::milvus::proto::plan::Expr* left);
// .milvus.proto.plan.Expr right = 3;
bool has_right() const;
void clear_right();
const ::milvus::proto::plan::Expr& right() const;
::milvus::proto::plan::Expr* release_right();
::milvus::proto::plan::Expr* mutable_right();
void set_allocated_right(::milvus::proto::plan::Expr* right);
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
void clear_op();
::milvus::proto::plan::BinaryExpr_BinaryOp op() const;
void set_op(::milvus::proto::plan::BinaryExpr_BinaryOp value);
// @@protoc_insertion_point(class_scope:milvus.proto.plan.BinaryExpr) // @@protoc_insertion_point(class_scope:milvus.proto.plan.BinaryExpr)
private: private:
class _Internal; class _Internal;
::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_; ::PROTOBUF_NAMESPACE_ID::internal::InternalMetadataWithArena _internal_metadata_;
::milvus::proto::plan::Expr* left_;
::milvus::proto::plan::Expr* right_;
int op_;
mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
friend struct ::TableStruct_plan_2eproto; friend struct ::TableStruct_plan_2eproto;
}; };
@ -2368,6 +2397,122 @@ inline void UnaryExpr::set_allocated_child(::milvus::proto::plan::Expr* child) {
// BinaryExpr // BinaryExpr
// .milvus.proto.plan.BinaryExpr.BinaryOp op = 1;
inline void BinaryExpr::clear_op() {
op_ = 0;
}
inline ::milvus::proto::plan::BinaryExpr_BinaryOp BinaryExpr::op() const {
// @@protoc_insertion_point(field_get:milvus.proto.plan.BinaryExpr.op)
return static_cast< ::milvus::proto::plan::BinaryExpr_BinaryOp >(op_);
}
inline void BinaryExpr::set_op(::milvus::proto::plan::BinaryExpr_BinaryOp value) {
op_ = value;
// @@protoc_insertion_point(field_set:milvus.proto.plan.BinaryExpr.op)
}
// .milvus.proto.plan.Expr left = 2;
inline bool BinaryExpr::has_left() const {
return this != internal_default_instance() && left_ != nullptr;
}
inline void BinaryExpr::clear_left() {
if (GetArenaNoVirtual() == nullptr && left_ != nullptr) {
delete left_;
}
left_ = nullptr;
}
inline const ::milvus::proto::plan::Expr& BinaryExpr::left() const {
const ::milvus::proto::plan::Expr* p = left_;
// @@protoc_insertion_point(field_get:milvus.proto.plan.BinaryExpr.left)
return p != nullptr ? *p : *reinterpret_cast<const ::milvus::proto::plan::Expr*>(
&::milvus::proto::plan::_Expr_default_instance_);
}
inline ::milvus::proto::plan::Expr* BinaryExpr::release_left() {
// @@protoc_insertion_point(field_release:milvus.proto.plan.BinaryExpr.left)
::milvus::proto::plan::Expr* temp = left_;
left_ = nullptr;
return temp;
}
inline ::milvus::proto::plan::Expr* BinaryExpr::mutable_left() {
if (left_ == nullptr) {
auto* p = CreateMaybeMessage<::milvus::proto::plan::Expr>(GetArenaNoVirtual());
left_ = p;
}
// @@protoc_insertion_point(field_mutable:milvus.proto.plan.BinaryExpr.left)
return left_;
}
inline void BinaryExpr::set_allocated_left(::milvus::proto::plan::Expr* left) {
::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual();
if (message_arena == nullptr) {
delete left_;
}
if (left) {
::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = nullptr;
if (message_arena != submessage_arena) {
left = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
message_arena, left, submessage_arena);
}
} else {
}
left_ = left;
// @@protoc_insertion_point(field_set_allocated:milvus.proto.plan.BinaryExpr.left)
}
// .milvus.proto.plan.Expr right = 3;
inline bool BinaryExpr::has_right() const {
return this != internal_default_instance() && right_ != nullptr;
}
inline void BinaryExpr::clear_right() {
if (GetArenaNoVirtual() == nullptr && right_ != nullptr) {
delete right_;
}
right_ = nullptr;
}
inline const ::milvus::proto::plan::Expr& BinaryExpr::right() const {
const ::milvus::proto::plan::Expr* p = right_;
// @@protoc_insertion_point(field_get:milvus.proto.plan.BinaryExpr.right)
return p != nullptr ? *p : *reinterpret_cast<const ::milvus::proto::plan::Expr*>(
&::milvus::proto::plan::_Expr_default_instance_);
}
inline ::milvus::proto::plan::Expr* BinaryExpr::release_right() {
// @@protoc_insertion_point(field_release:milvus.proto.plan.BinaryExpr.right)
::milvus::proto::plan::Expr* temp = right_;
right_ = nullptr;
return temp;
}
inline ::milvus::proto::plan::Expr* BinaryExpr::mutable_right() {
if (right_ == nullptr) {
auto* p = CreateMaybeMessage<::milvus::proto::plan::Expr>(GetArenaNoVirtual());
right_ = p;
}
// @@protoc_insertion_point(field_mutable:milvus.proto.plan.BinaryExpr.right)
return right_;
}
inline void BinaryExpr::set_allocated_right(::milvus::proto::plan::Expr* right) {
::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaNoVirtual();
if (message_arena == nullptr) {
delete right_;
}
if (right) {
::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = nullptr;
if (message_arena != submessage_arena) {
right = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
message_arena, right, submessage_arena);
}
} else {
}
right_ = right;
// @@protoc_insertion_point(field_set_allocated:milvus.proto.plan.BinaryExpr.right)
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Expr // Expr

View File

@ -484,7 +484,6 @@ Plan::check_identical(Plan& other) {
Assert(&schema_ == &other.schema_); Assert(&schema_ == &other.schema_);
auto json = ShowPlanNodeVisitor().call_child(*this->plan_node_); auto json = ShowPlanNodeVisitor().call_child(*this->plan_node_);
auto other_json = ShowPlanNodeVisitor().call_child(*other.plan_node_); auto other_json = ShowPlanNodeVisitor().call_child(*other.plan_node_);
std::cout << json.dump(2) << std::endl << other_json.dump(2) << std::endl;
Assert(json.dump(2) == other_json.dump(2)); Assert(json.dump(2) == other_json.dump(2));
Assert(this->extra_info_opt_.has_value() == other.extra_info_opt_.has_value()); Assert(this->extra_info_opt_.has_value() == other.extra_info_opt_.has_value());
if (this->extra_info_opt_.has_value()) { if (this->extra_info_opt_.has_value()) {

View File

@ -14,44 +14,65 @@
#include "ExprImpl.h" #include "ExprImpl.h"
#include "pb/plan.pb.h" #include "pb/plan.pb.h"
#include <google/protobuf/text_format.h> #include <google/protobuf/text_format.h>
#include <query/generated/ExtractInfoPlanNodeVisitor.h>
#include "query/generated/ExtractInfoExprVisitor.h" #include "query/generated/ExtractInfoExprVisitor.h"
#include "common/Types.h"
namespace milvus::query { namespace milvus::query {
namespace planpb = milvus::proto::plan; namespace planpb = milvus::proto::plan;
ExprPtr template <typename T>
ProtoParser::ExprFromProto(const planpb::Expr& expr_proto) { std::unique_ptr<TermExprImpl<T>>
// TODO: make naive works ExtractTermExprImpl(FieldOffset field_offset, DataType data_type, const planpb::TermExpr& expr_proto) {
Assert(expr_proto.has_range_expr()); static_assert(std::is_fundamental_v<T>);
auto result = std::make_unique<TermExprImpl<T>>();
auto& range_expr = expr_proto.range_expr();
auto& columen_info = range_expr.column_info();
auto field_id = FieldId(columen_info.field_id());
auto field_offset = schema.get_offset(field_id);
auto data_type = schema[field_offset].get_data_type();
involved_fields.set(field_offset.get(), true);
// auto& field_meta = schema[field_offset];
ExprPtr result = [&]() {
switch ((DataType)columen_info.data_type()) {
case DataType::INT64: {
auto result = std::make_unique<RangeExprImpl<int64_t>>();
result->field_offset_ = field_offset; result->field_offset_ = field_offset;
result->data_type_ = data_type; result->data_type_ = data_type;
Assert(range_expr.ops_size() == range_expr.values_size()); auto size = expr_proto.values_size();
auto sz = range_expr.ops_size(); for (int i = 0; i < size; ++i) {
// TODO simplify this auto& value_proto = expr_proto.values(i);
for (int i = 0; i < sz; ++i) { if constexpr (std::is_same_v<T, bool>) {
result->conditions_.emplace_back((RangeExpr::OpType)range_expr.ops(i), Assert(value_proto.val_case() == planpb::GenericValue::kBoolVal);
range_expr.values(i).int64_val()); result->terms_.emplace_back(static_cast<T>(value_proto.bool_val()));
} else if constexpr (std::is_integral_v<T>) {
Assert(value_proto.val_case() == planpb::GenericValue::kInt64Val);
result->terms_.emplace_back(static_cast<T>(value_proto.int64_val()));
} else if constexpr (std::is_floating_point_v<T>) {
Assert(value_proto.val_case() == planpb::GenericValue::kFloatVal);
result->terms_.emplace_back(static_cast<T>(value_proto.float_val()));
} else {
static_assert(always_false<T>);
}
} }
return result; return result;
} }
default: {
PanicInfo("unsupported yet"); template <typename T>
std::unique_ptr<RangeExprImpl<T>>
ExtractRangeExprImpl(FieldOffset field_offset, DataType data_type, const planpb::RangeExpr& expr_proto) {
static_assert(std::is_fundamental_v<T>);
auto result = std::make_unique<RangeExprImpl<T>>();
result->field_offset_ = field_offset;
result->data_type_ = data_type;
Assert(expr_proto.ops_size() == expr_proto.values_size());
auto sz = expr_proto.ops_size();
for (int i = 0; i < sz; ++i) {
auto op = static_cast<RangeExpr::OpType>(expr_proto.ops(i));
auto& value_proto = expr_proto.values(i);
if constexpr (std::is_same_v<T, bool>) {
Assert(value_proto.val_case() == planpb::GenericValue::kBoolVal);
result->conditions_.emplace_back(op, static_cast<T>(value_proto.bool_val()));
} else if constexpr (std::is_integral_v<T>) {
Assert(value_proto.val_case() == planpb::GenericValue::kInt64Val);
result->conditions_.emplace_back(op, static_cast<T>(value_proto.int64_val()));
} else if constexpr (std::is_floating_point_v<T>) {
Assert(value_proto.val_case() == planpb::GenericValue::kFloatVal);
result->conditions_.emplace_back(op, static_cast<T>(value_proto.float_val()));
} else {
static_assert(always_false<T>);
} }
} }
}();
return result; return result;
} }
@ -65,7 +86,7 @@ ProtoParser::PlanNodeFromProto(const planpb::PlanNode& plan_node_proto) {
if (!anns_proto.has_predicates()) { if (!anns_proto.has_predicates()) {
return std::nullopt; return std::nullopt;
} else { } else {
return ExprFromProto(anns_proto.predicates()); return ParseExpr(anns_proto.predicates());
} }
}(); }();
@ -75,7 +96,6 @@ ProtoParser::PlanNodeFromProto(const planpb::PlanNode& plan_node_proto) {
auto field_id = FieldId(anns_proto.field_id()); auto field_id = FieldId(anns_proto.field_id());
auto field_offset = schema.get_offset(field_id); auto field_offset = schema.get_offset(field_id);
query_info.field_offset_ = field_offset; query_info.field_offset_ = field_offset;
this->involved_fields.set(field_offset.get(), true);
query_info.metric_type_ = GetMetricType(query_info_proto.metric_type()); query_info.metric_type_ = GetMetricType(query_info_proto.metric_type());
query_info.topK_ = query_info_proto.topk(); query_info.topK_ = query_info_proto.topk();
@ -99,12 +119,138 @@ ProtoParser::CreatePlan(const proto::plan::PlanNode& plan_node_proto) {
auto plan = std::make_unique<Plan>(schema); auto plan = std::make_unique<Plan>(schema);
auto plan_node = PlanNodeFromProto(plan_node_proto); auto plan_node = PlanNodeFromProto(plan_node_proto);
ExtractedPlanInfo plan_info(schema.size());
ExtractInfoPlanNodeVisitor extractor(plan_info);
plan_node->accept(extractor);
plan->tag2field_["$0"] = plan_node->query_info_.field_offset_; plan->tag2field_["$0"] = plan_node->query_info_.field_offset_;
plan->plan_node_ = std::move(plan_node); plan->plan_node_ = std::move(plan_node);
ExtractedPlanInfo extract_info(schema.size()); plan->extra_info_opt_ = std::move(plan_info);
extract_info.involved_fields_ = std::move(involved_fields);
plan->extra_info_opt_ = std::move(extract_info);
return plan; return plan;
} }
ExprPtr
ProtoParser::ParseRangeExpr(const proto::plan::RangeExpr& expr_pb) {
auto& columen_info = expr_pb.column_info();
auto field_id = FieldId(columen_info.field_id());
auto field_offset = schema.get_offset(field_id);
auto data_type = schema[field_offset].get_data_type();
Assert(data_type == (DataType)columen_info.data_type());
// auto& field_meta = schema[field_offset];
auto result = [&]() -> ExprPtr {
switch (data_type) {
case DataType::BOOL: {
return ExtractRangeExprImpl<bool>(field_offset, data_type, expr_pb);
}
case DataType::INT8: {
return ExtractRangeExprImpl<int8_t>(field_offset, data_type, expr_pb);
}
case DataType::INT16: {
return ExtractRangeExprImpl<int16_t>(field_offset, data_type, expr_pb);
}
case DataType::INT32: {
return ExtractRangeExprImpl<int32_t>(field_offset, data_type, expr_pb);
}
case DataType::INT64: {
return ExtractRangeExprImpl<int64_t>(field_offset, data_type, expr_pb);
}
case DataType::FLOAT: {
return ExtractRangeExprImpl<float>(field_offset, data_type, expr_pb);
}
case DataType::DOUBLE: {
return ExtractRangeExprImpl<double>(field_offset, data_type, expr_pb);
}
default: {
PanicInfo("unsupported data type");
}
}
}();
return result;
}
ExprPtr
ProtoParser::ParseTermExpr(const proto::plan::TermExpr& expr_pb) {
auto& columen_info = expr_pb.column_info();
auto field_id = FieldId(columen_info.field_id());
auto field_offset = schema.get_offset(field_id);
auto data_type = schema[field_offset].get_data_type();
Assert(data_type == (DataType)columen_info.data_type());
// auto& field_meta = schema[field_offset];
auto result = [&]() -> ExprPtr {
switch (data_type) {
case DataType::BOOL: {
return ExtractTermExprImpl<bool>(field_offset, data_type, expr_pb);
}
case DataType::INT8: {
return ExtractTermExprImpl<int8_t>(field_offset, data_type, expr_pb);
}
case DataType::INT16: {
return ExtractTermExprImpl<int16_t>(field_offset, data_type, expr_pb);
}
case DataType::INT32: {
return ExtractTermExprImpl<int32_t>(field_offset, data_type, expr_pb);
}
case DataType::INT64: {
return ExtractTermExprImpl<int64_t>(field_offset, data_type, expr_pb);
}
case DataType::FLOAT: {
return ExtractTermExprImpl<float>(field_offset, data_type, expr_pb);
}
case DataType::DOUBLE: {
return ExtractTermExprImpl<double>(field_offset, data_type, expr_pb);
}
default: {
PanicInfo("unsupported data type");
}
}
}();
return result;
}
ExprPtr
ProtoParser::ParseUnaryExpr(const proto::plan::UnaryExpr& expr_pb) {
auto op = static_cast<BoolUnaryExpr::OpType>(expr_pb.op());
Assert(op == BoolUnaryExpr::OpType::LogicalNot);
auto expr = this->ParseExpr(expr_pb.child());
auto result = std::make_unique<BoolUnaryExpr>();
result->child_ = std::move(expr);
result->op_type_ = op;
return result;
}
ExprPtr
ProtoParser::ParseBinaryExpr(const proto::plan::BinaryExpr& expr_pb) {
auto op = static_cast<BoolBinaryExpr::OpType>(expr_pb.op());
auto left_expr = this->ParseExpr(expr_pb.left());
auto right_expr = this->ParseExpr(expr_pb.right());
auto result = std::make_unique<BoolBinaryExpr>();
result->op_type_ = op;
result->left_ = std::move(left_expr);
result->right_ = std::move(right_expr);
return result;
}
ExprPtr
ProtoParser::ParseExpr(const proto::plan::Expr& expr_pb) {
using ppe = proto::plan::Expr;
switch (expr_pb.expr_case()) {
case ppe::kBinaryExpr: {
return ParseBinaryExpr(expr_pb.binary_expr());
}
case ppe::kUnaryExpr: {
return ParseUnaryExpr(expr_pb.unary_expr());
}
case ppe::kTermExpr: {
return ParseTermExpr(expr_pb.term_expr());
}
case ppe::kRangeExpr: {
return ParseRangeExpr(expr_pb.range_expr());
}
default:
PanicInfo("unsupported expr proto node");
}
}
} // namespace milvus::query } // namespace milvus::query

View File

@ -20,11 +20,26 @@ namespace milvus::query {
class ProtoParser { class ProtoParser {
public: public:
explicit ProtoParser(const Schema& schema) : schema(schema), involved_fields(schema.size()) { explicit ProtoParser(const Schema& schema) : schema(schema) {
} }
// ExprPtr
// ExprFromProto(const proto::plan::Expr& expr_proto);
ExprPtr ExprPtr
ExprFromProto(const proto::plan::Expr& expr_proto); ParseRangeExpr(const proto::plan::RangeExpr& expr_pb);
ExprPtr
ParseTermExpr(const proto::plan::TermExpr& expr_pb);
ExprPtr
ParseUnaryExpr(const proto::plan::UnaryExpr& expr_pb);
ExprPtr
ParseBinaryExpr(const proto::plan::BinaryExpr& expr_pb);
ExprPtr
ParseExpr(const proto::plan::Expr& expr_pb);
std::unique_ptr<VectorPlanNode> std::unique_ptr<VectorPlanNode>
PlanNodeFromProto(const proto::plan::PlanNode& plan_node_proto); PlanNodeFromProto(const proto::plan::PlanNode& plan_node_proto);
@ -34,7 +49,7 @@ class ProtoParser {
private: private:
const Schema& schema; const Schema& schema;
boost::dynamic_bitset<> involved_fields; // boost::dynamic_bitset<> involved_fields;
}; };
} // namespace milvus::query } // namespace milvus::query

View File

@ -96,6 +96,7 @@ SegcoreConfig::parse_from(const std::string& config_path) {
result.table_[metric_type] = conf; result.table_[metric_type] = conf;
} }
} }
return result;
} catch (const SegcoreError& e) { } catch (const SegcoreError& e) {
// re-throw // re-throw
throw e; throw e;

View File

@ -17,27 +17,77 @@
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <random> #include <random>
#include <boost/format.hpp>
using namespace milvus; using namespace milvus;
using namespace milvus::query; using namespace milvus::query;
namespace planpb = proto::plan; namespace planpb = proto::plan;
using std::string;
TEST(PlanProto, Naive) { namespace spb = proto::schema;
auto schema = std::make_unique<Schema>(); static SchemaPtr
schema->AddField(FieldName("vectorfield"), FieldId(101), DataType::VECTOR_FLOAT, 16, MetricType::METRIC_L2); getStandardSchema() {
schema->AddField(FieldName("int64field"), FieldId(100), DataType::INT64); auto schema = std::make_shared<Schema>();
std::string proto_text = R"( schema->AddField(FieldName("FloatVectorField"), FieldId(100 + spb::DataType::FloatVector), DataType::VECTOR_FLOAT,
16, MetricType::METRIC_L2);
schema->AddField(FieldName("BinaryVectorField"), FieldId(100 + spb::DataType::BinaryVector),
DataType::VECTOR_BINARY, 16, MetricType::METRIC_Jaccard);
schema->AddField(FieldName("Int64Field"), FieldId(100 + spb::DataType::Int64), DataType::INT64);
schema->AddField(FieldName("Int32Field"), FieldId(100 + spb::DataType::Int32), DataType::INT32);
schema->AddField(FieldName("Int16Field"), FieldId(100 + spb::DataType::Int16), DataType::INT16);
schema->AddField(FieldName("Int8Field"), FieldId(100 + spb::DataType::Int8), DataType::INT8);
schema->AddField(FieldName("DoubleField"), FieldId(100 + spb::DataType::Double), DataType::DOUBLE);
schema->AddField(FieldName("FloatField"), FieldId(100 + spb::DataType::Float), DataType::FLOAT);
return schema;
}
class PlanProtoTest : public ::testing::TestWithParam<std::tuple<spb::DataType>> {
public:
PlanProtoTest() {
schema = getStandardSchema();
}
protected:
SchemaPtr schema;
};
INSTANTIATE_TEST_CASE_P(InstName,
PlanProtoTest,
::testing::Values( //
std::make_tuple(spb::DataType::Double), //
std::make_tuple(spb::DataType::Float), //
std::make_tuple(spb::DataType::Int64), //
std::make_tuple(spb::DataType::Int32), //
std::make_tuple(spb::DataType::Int16), //
std::make_tuple(spb::DataType::Int8) //
));
TEST_P(PlanProtoTest, Range) {
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
auto data_type = std::get<0>(GetParam());
auto data_type_str = spb::DataType_Name(data_type);
auto field_id = 100 + (int)data_type;
auto field_name = data_type_str + "Field";
string value_tag = "bool_val";
if (datatype_is_floating((DataType)data_type)) {
value_tag = "float_val";
} else if (datatype_is_interger((DataType)data_type)) {
value_tag = "int64_val";
}
auto fmt1 = boost::format(R"(
vector_anns: < vector_anns: <
field_id: 101 field_id: 201
predicates: < predicates: <
range_expr: < range_expr: <
column_info: < column_info: <
field_id: 100 field_id: %1%
data_type: Int64 data_type: %2%
> >
ops: GreaterThan ops: GreaterThan
values: < values: <
int64_val: 3 %3%: 3
> >
> >
> >
@ -48,31 +98,34 @@ vector_anns: <
> >
placeholder_tag: "$0" placeholder_tag: "$0"
> >
)"; )") % field_id % data_type_str %
value_tag;
auto proto_text = fmt1.str();
planpb::PlanNode node_proto; planpb::PlanNode node_proto;
google::protobuf::TextFormat::ParseFromString(proto_text, &node_proto); google::protobuf::TextFormat::ParseFromString(proto_text, &node_proto);
std::cout << node_proto.DebugString(); // std::cout << node_proto.DebugString();
auto plan = ProtoParser(*schema).CreatePlan(node_proto); auto plan = ProtoParser(*schema).CreatePlan(node_proto);
ShowPlanNodeVisitor visitor; ShowPlanNodeVisitor visitor;
auto json = visitor.call_child(*plan->plan_node_); auto json = visitor.call_child(*plan->plan_node_);
std::cout << json.dump(2); // std::cout << json.dump(2);
auto extra_info = plan->extra_info_opt_.value(); auto extra_info = plan->extra_info_opt_.value();
std::string dsl_text = R"( std::string dsl_text = boost::str(boost::format(R"(
{ {
"bool": { "bool": {
"must": [ "must": [
{ {
"range": { "range": {
"int64field": { "%1%": {
"GT": 3 "GT": 3
} }
} }
}, },
{ {
"vector": { "vector": {
"vectorfield": { "FloatVectorField": {
"metric_type": "L2", "metric_type": "L2",
"params": { "params": {
"nprobe": 10 "nprobe": 10
@ -85,7 +138,324 @@ vector_anns: <
] ]
} }
} }
)"; )") % field_name);
auto ref_plan = CreatePlan(*schema, dsl_text); auto ref_plan = CreatePlan(*schema, dsl_text);
plan->check_identical(*ref_plan); plan->check_identical(*ref_plan);
} }
TEST_P(PlanProtoTest, TermExpr) {
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
auto data_type = std::get<0>(GetParam());
auto data_type_str = spb::DataType_Name(data_type);
auto field_id = 100 + (int)data_type;
auto field_name = data_type_str + "Field";
string value_tag = "bool_val";
if (datatype_is_floating((DataType)data_type)) {
value_tag = "float_val";
} else if (datatype_is_interger((DataType)data_type)) {
value_tag = "int64_val";
}
auto fmt1 = boost::format(R"(
vector_anns: <
field_id: 201
predicates: <
term_expr: <
column_info: <
field_id: %1%
data_type: %2%
>
values: <
%3%: 1
>
values: <
%3%: 2
>
values: <
%3%: 3
>
>
>
query_info: <
topk: 10
metric_type: "L2"
search_params: "{\"nprobe\": 10}"
>
placeholder_tag: "$0"
>
)") % field_id % data_type_str %
value_tag;
auto proto_text = fmt1.str();
planpb::PlanNode node_proto;
google::protobuf::TextFormat::ParseFromString(proto_text, &node_proto);
// std::cout << node_proto.DebugString();
auto plan = ProtoParser(*schema).CreatePlan(node_proto);
ShowPlanNodeVisitor visitor;
auto json = visitor.call_child(*plan->plan_node_);
// std::cout << json.dump(2);
auto extra_info = plan->extra_info_opt_.value();
std::string dsl_text = boost::str(boost::format(R"(
{
"bool": {
"must": [
{
"term": {
"%1%": {
"values": [1,2,3]
}
}
},
{
"vector": {
"FloatVectorField": {
"metric_type": "L2",
"params": {
"nprobe": 10
},
"query": "$0",
"topk": 10
}
}
}
]
}
}
)") % field_name);
auto ref_plan = CreatePlan(*schema, dsl_text);
plan->check_identical(*ref_plan);
}
TEST(PlanProtoXTest, NotExpr) {
auto schema = getStandardSchema();
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
auto data_type = spb::DataType::Int64;
auto data_type_str = spb::DataType_Name(data_type);
auto field_id = 100 + (int)data_type;
auto field_name = data_type_str + "Field";
string value_tag = "bool_val";
if (datatype_is_floating((DataType)data_type)) {
value_tag = "float_val";
} else if (datatype_is_interger((DataType)data_type)) {
value_tag = "int64_val";
}
auto fmt1 = boost::format(R"(
vector_anns: <
field_id: 201
predicates: <
unary_expr: <
op: Not
child: <
range_expr: <
column_info: <
field_id: %1%
data_type: %2%
>
ops: GreaterThan
values: <
%3%: 3
>
>
>
>
>
query_info: <
topk: 10
metric_type: "L2"
search_params: "{\"nprobe\": 10}"
>
placeholder_tag: "$0"
>
)") % field_id % data_type_str %
value_tag;
auto proto_text = fmt1.str();
planpb::PlanNode node_proto;
google::protobuf::TextFormat::ParseFromString(proto_text, &node_proto);
// std::cout << node_proto.DebugString();
auto plan = ProtoParser(*schema).CreatePlan(node_proto);
ShowPlanNodeVisitor visitor;
auto json = visitor.call_child(*plan->plan_node_);
// std::cout << json.dump(2);
auto extra_info = plan->extra_info_opt_.value();
std::string dsl_text = boost::str(boost::format(R"(
{
"bool": {
"must": [
{
"should_not": [{
"range": {
"%1%": {
"GT": 3
}
}
}]
},
{
"vector": {
"FloatVectorField": {
"metric_type": "L2",
"params": {
"nprobe": 10
},
"query": "$0",
"topk": 10
}
}
}
]
}
}
)") % field_name);
auto ref_plan = CreatePlan(*schema, dsl_text);
auto ref_json = ShowPlanNodeVisitor().call_child(*ref_plan->plan_node_);
EXPECT_EQ(json.dump(2), ref_json.dump(2));
plan->check_identical(*ref_plan);
}
TEST(PlanProtoXTest, AndOrExpr) {
auto schema = getStandardSchema();
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
// xxx.query(predicates = "int64field > 3", topk = 10, ...)
auto data_type = spb::DataType::Int64;
auto data_type_str = spb::DataType_Name(data_type);
auto field_id = 100 + (int)data_type;
auto field_name = data_type_str + "Field";
string value_tag = "bool_val";
if (datatype_is_floating((DataType)data_type)) {
value_tag = "float_val";
} else if (datatype_is_interger((DataType)data_type)) {
value_tag = "int64_val";
}
auto fmt1 = boost::format(R"(
vector_anns: <
field_id: 201
predicates: <
binary_expr: <
op: LogicalAnd
left: <
range_expr: <
column_info: <
field_id: 105
data_type: Int64
>
ops: LessThan
values: <
int64_val: 3
>
>
>
right: <
binary_expr: <
op: LogicalOr
left: <
range_expr: <
column_info: <
field_id: 105
data_type: Int64
>
ops: GreaterThan
values: <
int64_val: 2
>
>
>
right: <
range_expr: <
column_info: <
field_id: 105
data_type: Int64
>
ops: Equal
values: <
int64_val: 1
>
>
>
>
>
>
>
query_info: <
topk: 10
metric_type: "L2"
search_params: "{\"nprobe\": 10}"
>
placeholder_tag: "$0"
>
)");
auto proto_text = fmt1.str();
planpb::PlanNode node_proto;
google::protobuf::TextFormat::ParseFromString(proto_text, &node_proto);
// std::cout << node_proto.DebugString();
auto plan = ProtoParser(*schema).CreatePlan(node_proto);
ShowPlanNodeVisitor visitor;
auto json = visitor.call_child(*plan->plan_node_);
// std::cout << json.dump(2);
auto extra_info = plan->extra_info_opt_.value();
std::string dsl_text = boost::str(boost::format(R"(
{
"bool": {
"must": [
{
"range": {
"%1%": {
"LT": 3
}
}
},
{
"should": [
{
"range": {
"%1%": {
"GT": 2
}
}
},
{
"range": {
"%1%": {
"EQ": 1
}
}
}
]
},
{
"vector": {
"FloatVectorField": {
"metric_type": "L2",
"params": {
"nprobe": 10
},
"query": "$0",
"topk": 10
}
}
}
]
}
}
)") % field_name);
auto ref_plan = CreatePlan(*schema, dsl_text);
auto ref_json = ShowPlanNodeVisitor().call_child(*ref_plan->plan_node_);
EXPECT_EQ(json.dump(2), ref_json.dump(2));
plan->check_identical(*ref_plan);
}

View File

@ -59,6 +59,9 @@ message BinaryExpr {
LogicalAnd = 1; LogicalAnd = 1;
LogicalOr = 2; LogicalOr = 2;
} }
BinaryOp op = 1;
Expr left = 2;
Expr right = 3;
} }
message Expr { message Expr {

View File

@ -461,6 +461,9 @@ func (m *UnaryExpr) GetChild() *Expr {
} }
type BinaryExpr struct { type BinaryExpr struct {
Op BinaryExpr_BinaryOp `protobuf:"varint,1,opt,name=op,proto3,enum=milvus.proto.plan.BinaryExpr_BinaryOp" json:"op,omitempty"`
Left *Expr `protobuf:"bytes,2,opt,name=left,proto3" json:"left,omitempty"`
Right *Expr `protobuf:"bytes,3,opt,name=right,proto3" json:"right,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -491,6 +494,27 @@ func (m *BinaryExpr) XXX_DiscardUnknown() {
var xxx_messageInfo_BinaryExpr proto.InternalMessageInfo var xxx_messageInfo_BinaryExpr proto.InternalMessageInfo
func (m *BinaryExpr) GetOp() BinaryExpr_BinaryOp {
if m != nil {
return m.Op
}
return BinaryExpr_Invalid
}
func (m *BinaryExpr) GetLeft() *Expr {
if m != nil {
return m.Left
}
return nil
}
func (m *BinaryExpr) GetRight() *Expr {
if m != nil {
return m.Right
}
return nil
}
type Expr struct { type Expr struct {
// Types that are valid to be assigned to Expr: // Types that are valid to be assigned to Expr:
// *Expr_RangeExpr // *Expr_RangeExpr
@ -756,55 +780,57 @@ func init() {
func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) } func init() { proto.RegisterFile("plan.proto", fileDescriptor_2d655ab2f7683c23) }
var fileDescriptor_2d655ab2f7683c23 = []byte{ var fileDescriptor_2d655ab2f7683c23 = []byte{
// 792 bytes of a gzipped FileDescriptorProto // 829 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x6f, 0xdb, 0x36, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x54, 0x4f, 0x6f, 0x23, 0x35,
0x14, 0xb7, 0x24, 0xff, 0x91, 0x9e, 0x5d, 0xd7, 0xe3, 0x65, 0xde, 0xb2, 0x22, 0x86, 0x3a, 0x60, 0x14, 0xcf, 0xcc, 0xe4, 0xcf, 0xcc, 0x4b, 0x36, 0x1b, 0x7c, 0x21, 0x50, 0x56, 0x8d, 0x66, 0x11,
0xbe, 0xd4, 0xc1, 0xdc, 0xae, 0x05, 0x3a, 0x74, 0x58, 0xb2, 0x16, 0x4d, 0x80, 0xc2, 0xe9, 0x34, 0x44, 0x42, 0x9b, 0x8a, 0xec, 0xd2, 0x95, 0x16, 0x2d, 0xa2, 0x85, 0xd5, 0xb6, 0xd2, 0x2a, 0x5d,
0x2f, 0x87, 0x5d, 0x04, 0x5a, 0x62, 0x6c, 0x62, 0x34, 0xc9, 0x50, 0x94, 0xd1, 0x9c, 0x77, 0xdb, 0x86, 0xd0, 0x03, 0x97, 0x91, 0x33, 0xe3, 0x24, 0x16, 0x8e, 0xed, 0x7a, 0x9c, 0xa8, 0x3d, 0x73,
0x6d, 0x9f, 0x63, 0x1f, 0x6b, 0x5f, 0x64, 0x20, 0xa9, 0xc8, 0x71, 0xe0, 0x04, 0x18, 0xb0, 0x1b, 0xe3, 0xc6, 0xe7, 0xe0, 0x0b, 0x71, 0xe7, 0x8b, 0x20, 0xdb, 0xd3, 0x49, 0x83, 0xd2, 0x22, 0x24,
0xdf, 0x9f, 0xdf, 0xfb, 0x91, 0xbf, 0xf7, 0xf8, 0x00, 0x24, 0xc3, 0x7c, 0x22, 0x95, 0xd0, 0x02, 0x6e, 0x7e, 0x7f, 0x7e, 0xef, 0xf7, 0xfe, 0xf9, 0x01, 0x48, 0x86, 0xf9, 0x48, 0x2a, 0xa1, 0x05,
0x7d, 0xb6, 0xa6, 0x6c, 0x53, 0x16, 0xce, 0x9a, 0x98, 0xc0, 0x97, 0xbd, 0x22, 0x5b, 0x91, 0x35, 0xfa, 0x60, 0x45, 0xd9, 0x66, 0x5d, 0x38, 0x69, 0x64, 0x0c, 0x1f, 0x77, 0x8a, 0x6c, 0x49, 0x56,
0x76, 0xae, 0x58, 0x42, 0xef, 0x3d, 0xe1, 0x44, 0xd1, 0xec, 0x02, 0xb3, 0x92, 0xa0, 0x03, 0x08, 0xd8, 0xa9, 0x62, 0x09, 0x9d, 0xb7, 0x84, 0x13, 0x45, 0xb3, 0x4b, 0xcc, 0xd6, 0x04, 0x1d, 0x40,
0x17, 0x42, 0xb0, 0x74, 0x83, 0xd9, 0xd0, 0x1b, 0x79, 0xe3, 0xf0, 0xb4, 0x91, 0x74, 0x8c, 0xe7, 0x38, 0x13, 0x82, 0xa5, 0x1b, 0xcc, 0xfa, 0xde, 0xc0, 0x1b, 0x86, 0x67, 0xb5, 0xa4, 0x65, 0x34,
0x02, 0x33, 0xf4, 0x04, 0x22, 0xca, 0xf5, 0xcb, 0x17, 0x36, 0xea, 0x8f, 0xbc, 0x71, 0x70, 0xda, 0x97, 0x98, 0xa1, 0x27, 0x10, 0x51, 0xae, 0x8f, 0x5f, 0x58, 0xab, 0x3f, 0xf0, 0x86, 0xc1, 0x59,
0x48, 0x42, 0xeb, 0xaa, 0xc2, 0x97, 0x4c, 0x60, 0x6d, 0xc3, 0xc1, 0xc8, 0x1b, 0x7b, 0x26, 0x6c, 0x2d, 0x09, 0xad, 0xaa, 0x34, 0xcf, 0x99, 0xc0, 0xda, 0x9a, 0x83, 0x81, 0x37, 0xf4, 0x8c, 0xd9,
0x5d, 0x17, 0x98, 0x9d, 0xb4, 0x20, 0xd8, 0x60, 0x16, 0x13, 0x88, 0x7e, 0x2e, 0x89, 0xba, 0x3e, 0xaa, 0x2e, 0x31, 0x3b, 0x6d, 0x40, 0xb0, 0xc1, 0x2c, 0x26, 0x10, 0xfd, 0xb0, 0x26, 0xea, 0xe6,
0xe3, 0x97, 0x02, 0x21, 0x68, 0x6a, 0x21, 0x7f, 0xb7, 0x54, 0x41, 0x62, 0xcf, 0xe8, 0x10, 0xba, 0x9c, 0xcf, 0x05, 0x42, 0x50, 0xd7, 0x42, 0xfe, 0x62, 0xa9, 0x82, 0xc4, 0xbe, 0xd1, 0x21, 0xb4,
0x6b, 0xa2, 0x15, 0xcd, 0x52, 0x7d, 0x2d, 0x89, 0x2d, 0x14, 0x25, 0xe0, 0x5c, 0xf3, 0x6b, 0x49, 0x57, 0x44, 0x2b, 0x9a, 0xa5, 0xfa, 0x46, 0x12, 0x1b, 0x28, 0x4a, 0xc0, 0xa9, 0xa6, 0x37, 0x92,
0xd0, 0x53, 0x78, 0x54, 0x10, 0xac, 0xb2, 0x55, 0x2a, 0xb1, 0xc2, 0xeb, 0x62, 0xd8, 0xb4, 0x29, 0xa0, 0xa7, 0xf0, 0xa8, 0x20, 0x58, 0x65, 0xcb, 0x54, 0x62, 0x85, 0x57, 0x45, 0xbf, 0x6e, 0x5d,
0x3d, 0xe7, 0xfc, 0x68, 0x7d, 0x71, 0x06, 0xf0, 0x93, 0x60, 0xe5, 0x9a, 0x5b, 0x9e, 0x2f, 0x20, 0x3a, 0x4e, 0xf9, 0xde, 0xea, 0xe2, 0x0c, 0xe0, 0x3b, 0xc1, 0xd6, 0x2b, 0x6e, 0x79, 0x3e, 0x82,
0xbc, 0xa4, 0x84, 0xe5, 0x29, 0xcd, 0x2b, 0xae, 0x8e, 0xb5, 0xcf, 0x72, 0xf4, 0x1a, 0xa2, 0x1c, 0x70, 0x4e, 0x09, 0xcb, 0x53, 0x9a, 0x97, 0x5c, 0x2d, 0x2b, 0x9f, 0xe7, 0xe8, 0x15, 0x44, 0x39,
0x6b, 0xec, 0xc8, 0xcc, 0xa3, 0xfa, 0xd3, 0x27, 0x93, 0x1d, 0xd9, 0x2a, 0xc1, 0xde, 0x62, 0x8d, 0xd6, 0xd8, 0x91, 0x99, 0xa2, 0xba, 0xe3, 0x27, 0xa3, 0x9d, 0xb6, 0x95, 0x0d, 0xfb, 0x1e, 0x6b,
0x0d, 0x7f, 0x12, 0xe6, 0xd5, 0x29, 0xfe, 0xdb, 0x87, 0x28, 0xc1, 0x7c, 0x49, 0xde, 0x7d, 0x92, 0x6c, 0xf8, 0x93, 0x30, 0x2f, 0x5f, 0xf1, 0x1f, 0x3e, 0x44, 0x09, 0xe6, 0x0b, 0xf2, 0xe6, 0x5a,
0x0a, 0xfd, 0x00, 0xdd, 0xcc, 0x52, 0xa6, 0x94, 0x5f, 0x0a, 0xcb, 0xd3, 0xbd, 0x5b, 0xcb, 0xf6, 0x2a, 0xf4, 0x0d, 0xb4, 0x33, 0x4b, 0x99, 0x52, 0x3e, 0x17, 0x96, 0xa7, 0xfd, 0xcf, 0x58, 0x76,
0x66, 0x7b, 0xb1, 0x04, 0xb2, 0xed, 0x25, 0xbf, 0x83, 0x40, 0xc8, 0x62, 0xe8, 0x8f, 0x82, 0x71, 0x36, 0xdb, 0xc4, 0x12, 0xc8, 0xb6, 0x49, 0x7e, 0x05, 0x81, 0x90, 0x45, 0xdf, 0x1f, 0x04, 0xc3,
0x7f, 0xfa, 0x74, 0x0f, 0xae, 0xa6, 0x9a, 0x9c, 0x4b, 0x7b, 0x13, 0x93, 0x8f, 0x5e, 0x41, 0x7b, 0xee, 0xf8, 0xe9, 0x1e, 0x5c, 0x45, 0x35, 0xba, 0x90, 0x36, 0x13, 0xe3, 0x8f, 0x5e, 0x42, 0x73,
0x63, 0x7a, 0x57, 0x0c, 0x83, 0x51, 0x30, 0xee, 0x4e, 0x0f, 0xf7, 0x20, 0x6f, 0xf7, 0x38, 0xa9, 0x63, 0x66, 0x57, 0xf4, 0x83, 0x41, 0x30, 0x6c, 0x8f, 0x0f, 0xf7, 0x20, 0xef, 0xce, 0x38, 0x29,
0xd2, 0x63, 0x0e, 0x6d, 0x57, 0x07, 0x75, 0xa1, 0x73, 0xc6, 0x37, 0x98, 0xd1, 0x7c, 0xd0, 0x40, 0xdd, 0x63, 0x0e, 0x4d, 0x17, 0x07, 0xb5, 0xa1, 0x75, 0xce, 0x37, 0x98, 0xd1, 0xbc, 0x57, 0x43,
0x8f, 0xa1, 0xfb, 0x5e, 0x11, 0xac, 0x89, 0x9a, 0xaf, 0x30, 0x1f, 0x78, 0x68, 0x00, 0xbd, 0xca, 0x8f, 0xa1, 0xfd, 0x56, 0x11, 0xac, 0x89, 0x9a, 0x2e, 0x31, 0xef, 0x79, 0xa8, 0x07, 0x9d, 0x52,
0xf1, 0xee, 0xaa, 0xc4, 0x6c, 0xe0, 0xa3, 0x1e, 0x84, 0x1f, 0x48, 0x51, 0xd8, 0x78, 0x80, 0x1e, 0xf1, 0xe6, 0x6a, 0x8d, 0x59, 0xcf, 0x47, 0x1d, 0x08, 0xdf, 0x91, 0xa2, 0xb0, 0xf6, 0x00, 0x3d,
0x41, 0x64, 0x2c, 0x17, 0x6c, 0xa2, 0x08, 0x5a, 0xee, 0xd8, 0x32, 0x79, 0x33, 0xa1, 0x9d, 0xd5, 0x82, 0xc8, 0x48, 0xce, 0x58, 0x47, 0x11, 0x34, 0xdc, 0xb3, 0x61, 0xfc, 0x26, 0x42, 0x3b, 0xa9,
0x8e, 0xff, 0xf0, 0x20, 0x9c, 0x13, 0xb5, 0xfe, 0x5f, 0xc4, 0xda, 0xbe, 0xda, 0xff, 0x6f, 0xaf, 0x19, 0xff, 0xea, 0x41, 0x38, 0x25, 0x6a, 0xf5, 0xbf, 0x34, 0x6b, 0x5b, 0xb5, 0xff, 0xdf, 0xaa,
0xfe, 0xcb, 0x83, 0xe8, 0x57, 0x8e, 0xd5, 0xb5, 0xbd, 0xc6, 0x0b, 0xf0, 0x85, 0xb4, 0xec, 0xfd, 0xfe, 0xdd, 0x83, 0xe8, 0x27, 0x8e, 0xd5, 0x8d, 0x4d, 0xe3, 0x05, 0xf8, 0x42, 0x5a, 0xf6, 0xee,
0xe9, 0xd7, 0x7b, 0x4a, 0xd4, 0x99, 0xee, 0x74, 0x2e, 0x13, 0x5f, 0x48, 0xf4, 0x0c, 0x5a, 0xd9, 0xf8, 0xd3, 0x3d, 0x21, 0x2a, 0x4f, 0xf7, 0xba, 0x90, 0x89, 0x2f, 0x24, 0x7a, 0x06, 0x8d, 0x6c,
0x8a, 0xb2, 0xdc, 0xce, 0x4b, 0x77, 0xfa, 0xf9, 0x1e, 0xa0, 0xc1, 0x24, 0x2e, 0x2b, 0x3e, 0x84, 0x49, 0x59, 0x6e, 0xf7, 0xa5, 0x3d, 0xfe, 0x70, 0x0f, 0xd0, 0x60, 0x12, 0xe7, 0x15, 0x1f, 0x42,
0x4e, 0x85, 0xde, 0x55, 0xba, 0x03, 0xc1, 0x4c, 0xe8, 0x81, 0x17, 0xbf, 0x05, 0x38, 0xa1, 0x37, 0xab, 0x44, 0xef, 0x76, 0xba, 0x05, 0xc1, 0x44, 0xe8, 0x9e, 0x17, 0xff, 0xe9, 0x01, 0x9c, 0xd2,
0x4c, 0xf1, 0x4b, 0x08, 0x9d, 0x75, 0x37, 0xbf, 0x0f, 0xf0, 0x41, 0x2c, 0x69, 0x86, 0xd9, 0x31, 0x2a, 0xa9, 0xe3, 0x3b, 0x49, 0x7d, 0xb6, 0x27, 0xf6, 0xd6, 0xb5, 0x7c, 0x96, 0x69, 0x7d, 0x01,
0xcf, 0x07, 0x9e, 0x15, 0xde, 0xd9, 0xe7, 0x6a, 0xe0, 0xc7, 0x7f, 0xfa, 0xd0, 0xb4, 0x8f, 0x7a, 0x75, 0x46, 0xe6, 0xfa, 0xdf, 0xb2, 0xb2, 0x4e, 0xa6, 0x06, 0x45, 0x17, 0x4b, 0x6d, 0x3f, 0xd8,
0x03, 0xa0, 0xcc, 0xa8, 0xa4, 0xe4, 0x93, 0x54, 0x95, 0xb4, 0x5f, 0x3d, 0x34, 0x4f, 0xa7, 0x8d, 0x43, 0x35, 0x58, 0xaf, 0xf8, 0x18, 0xc2, 0x5b, 0xae, 0xdd, 0x22, 0xba, 0x00, 0xef, 0xc4, 0x82,
0x24, 0x52, 0xf5, 0x1c, 0xbf, 0x86, 0x48, 0x13, 0xb5, 0x76, 0x68, 0xf7, 0xc2, 0x83, 0x3d, 0xe8, 0x66, 0x98, 0x9d, 0xf0, 0xbc, 0xe7, 0xd9, 0x6d, 0x70, 0xf2, 0x85, 0xea, 0xf9, 0xf1, 0x6f, 0x3e,
0x9b, 0x56, 0x9a, 0x4f, 0xae, 0x6f, 0xda, 0xfa, 0x06, 0xa0, 0x34, 0x57, 0x77, 0xe0, 0xe0, 0x5e, 0xd4, 0x6d, 0x51, 0xaf, 0x01, 0x94, 0xd9, 0xdf, 0x94, 0x5c, 0x4b, 0x55, 0xce, 0xfb, 0x93, 0x87,
0xea, 0x5a, 0x57, 0x43, 0x5d, 0xd6, 0xed, 0xf8, 0x11, 0xba, 0x0b, 0xba, 0xc5, 0x37, 0xef, 0x9d, 0x96, 0xfc, 0xac, 0x96, 0x44, 0xaa, 0xfa, 0x5c, 0xaf, 0x20, 0xd2, 0x44, 0xad, 0x1c, 0xda, 0x15,
0x8a, 0xad, 0x5c, 0xa7, 0x8d, 0x04, 0x16, 0xb5, 0x75, 0xd2, 0x86, 0xa6, 0x81, 0xc6, 0xff, 0x78, 0x78, 0xb0, 0x07, 0x7d, 0xbb, 0x5f, 0xe6, 0xf2, 0xe8, 0xdb, 0x5d, 0x7b, 0x0d, 0xb0, 0x36, 0xa9,
0x00, 0x17, 0x24, 0xd3, 0x42, 0x1d, 0xcf, 0x66, 0xbf, 0xa0, 0x03, 0x88, 0x68, 0x91, 0xba, 0x3c, 0x3b, 0x70, 0x70, 0x2f, 0x75, 0x35, 0x6c, 0x43, 0xbd, 0xae, 0xc6, 0xf1, 0x2d, 0xb4, 0x67, 0x74,
0xb7, 0xd8, 0x92, 0x90, 0x16, 0xae, 0xca, 0xce, 0x76, 0xf0, 0x77, 0xb7, 0xc3, 0x2b, 0x00, 0xa9, 0x8b, 0xaf, 0xdf, 0xbb, 0xaa, 0xdb, 0xb9, 0x9c, 0xd5, 0x12, 0x98, 0x55, 0xd2, 0x69, 0x13, 0xea,
0x48, 0x4e, 0x33, 0xac, 0xed, 0x07, 0x7b, 0xb0, 0xdd, 0xb7, 0x52, 0xd1, 0xf7, 0x00, 0x57, 0x66, 0x06, 0x1a, 0xff, 0xe5, 0x01, 0x5c, 0x92, 0x4c, 0x0b, 0x75, 0x32, 0x99, 0xfc, 0x88, 0x0e, 0x20,
0xcd, 0xb9, 0xf1, 0x6e, 0xde, 0x2b, 0x44, 0xbd, 0x0b, 0x93, 0xe8, 0xaa, 0x5e, 0x8b, 0xdf, 0xc0, 0xa2, 0x45, 0xea, 0xfc, 0xdc, 0xb5, 0x4d, 0x42, 0x5a, 0xb8, 0x28, 0x3b, 0x27, 0xcb, 0xdf, 0x3d,
0x63, 0xc9, 0x70, 0x46, 0x56, 0x82, 0xe5, 0x44, 0xa5, 0x1a, 0x2f, 0x87, 0x2d, 0xbb, 0xe3, 0xfa, 0x59, 0x2f, 0x01, 0xa4, 0x22, 0x39, 0xcd, 0xb0, 0xb6, 0xbf, 0xfe, 0xc1, 0xf9, 0xdd, 0x71, 0x45,
0xb7, 0xdc, 0x73, 0xbc, 0x8c, 0xe7, 0x10, 0x7e, 0x64, 0x98, 0xcf, 0x44, 0x4e, 0x8c, 0x76, 0x1b, 0x5f, 0x03, 0x5c, 0x99, 0xdb, 0xeb, 0xfe, 0x5c, 0xfd, 0xde, 0x46, 0x54, 0x07, 0x3a, 0x89, 0xae,
0xfb, 0xe0, 0x14, 0x73, 0x5e, 0x3c, 0xf0, 0xa3, 0xb6, 0xb2, 0x18, 0xed, 0x1c, 0xe6, 0x98, 0xf3, 0xaa, 0x5b, 0xfd, 0x39, 0x3c, 0x96, 0x0c, 0x67, 0x64, 0x29, 0x58, 0x4e, 0x54, 0xaa, 0xf1, 0xa2,
0xc2, 0x68, 0xc7, 0x45, 0x4e, 0x4e, 0x9e, 0xff, 0xf6, 0xed, 0x92, 0xea, 0x55, 0xb9, 0x98, 0x64, 0xdf, 0xb0, 0x87, 0xb7, 0x7b, 0x47, 0x3d, 0xc5, 0x8b, 0x78, 0x0a, 0xe1, 0x7b, 0x86, 0xf9, 0x44,
0x62, 0x7d, 0xe4, 0x0a, 0x3c, 0xa3, 0xa2, 0x3a, 0x1d, 0x51, 0xae, 0x89, 0xe2, 0x98, 0x1d, 0xd9, 0xe4, 0xc4, 0xf4, 0x6e, 0x63, 0x0b, 0x4e, 0x31, 0xe7, 0xc5, 0x03, 0xdf, 0x7c, 0xdb, 0x16, 0xd3,
0x9a, 0x47, 0xa6, 0xa6, 0x5c, 0x2c, 0xda, 0xd6, 0x7a, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3b, 0x87, 0x39, 0xe1, 0xbc, 0x30, 0xbd, 0xe3, 0x22, 0x27, 0xa7, 0xcf, 0x7f, 0xfe, 0x72, 0x41,
0x33, 0x17, 0x7b, 0x52, 0x7f, 0x06, 0x00, 0x00, 0xf5, 0x72, 0x3d, 0x1b, 0x65, 0x62, 0x75, 0xe4, 0x02, 0x3c, 0xa3, 0xa2, 0x7c, 0x1d, 0x51, 0xae,
0x89, 0xe2, 0x98, 0x1d, 0xd9, 0x98, 0x47, 0x26, 0xa6, 0x9c, 0xcd, 0x9a, 0x56, 0x7a, 0xfe, 0x77,
0x00, 0x00, 0x00, 0xff, 0xff, 0x17, 0x9f, 0xfa, 0x86, 0x14, 0x07, 0x00, 0x00,
} }

View File

@ -1,3 +1,14 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed 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 proxynode package proxynode
import ( import (
@ -11,46 +22,6 @@ import (
"github.com/milvus-io/milvus/internal/util/typeutil" "github.com/milvus-io/milvus/internal/util/typeutil"
) )
//func parseQueryExprNaive(schema *typeutil.SchemaHelper, exprStr string) (*planpb.Expr, error) {
// // TODO: handle more cases
// // TODO: currently just A > 3
//
// tmps := strings.Split(exprStr, ">")
// if len(tmps) != 2 {
// return nil, errors.New("unsupported yet")
// }
// for i, str := range tmps {
// tmps[i] = strings.TrimSpace(str)
// }
// fieldName := tmps[0]
// tmpValue, err := strconv.ParseInt(tmps[1], 10, 64)
// if err != nil {
// return nil, err
// }
// fieldValue := &planpb.GenericValue{
// Val: &planpb.GenericValue_Int64Val{Int64Val: tmpValue},
// }
//
// field, err := schema.GetFieldFromName(fieldName)
// if err != nil {
// return nil, err
// }
//
// expr := &planpb.Expr{
// Expr: &planpb.Expr_RangeExpr{
// RangeExpr: &planpb.RangeExpr{
// ColumnInfo: &planpb.ColumnInfo{
// FieldId: field.FieldID,
// DataType: field.DataType,
// },
// Ops: []planpb.RangeExpr_OpType{planpb.RangeExpr_GreaterThan},
// Values: []*planpb.GenericValue{fieldValue},
// },
// },
// }
// return expr, nil
//}
func parseQueryExpr(schema *typeutil.SchemaHelper, exprStrNullable *string) (*planpb.Expr, error) { func parseQueryExpr(schema *typeutil.SchemaHelper, exprStrNullable *string) (*planpb.Expr, error) {
if exprStrNullable == nil { if exprStrNullable == nil {
return nil, nil return nil, nil
@ -70,7 +41,7 @@ func parseQueryExprAdvanced(schema *typeutil.SchemaHelper, exprStr string) (*pla
} }
context := ParserContext{schema} context := ParserContext{schema}
return context.parseExpr(&ast.Node) return context.handleExpr(&ast.Node)
} }
func (context *ParserContext) createColumnInfo(field *schemapb.FieldSchema) *planpb.ColumnInfo { func (context *ParserContext) createColumnInfo(field *schemapb.FieldSchema) *planpb.ColumnInfo {
@ -80,9 +51,10 @@ func (context *ParserContext) createColumnInfo(field *schemapb.FieldSchema) *pla
} }
} }
func createSingleOps(opStr string, reverse bool) planpb.RangeExpr_OpType { func getCompareOpType(opStr string, reverse bool) planpb.RangeExpr_OpType {
type OpType = planpb.RangeExpr_OpType type OpType = planpb.RangeExpr_OpType
var op planpb.RangeExpr_OpType var op planpb.RangeExpr_OpType
if !reverse { if !reverse {
switch opStr { switch opStr {
case "<": case "<":
@ -121,27 +93,49 @@ func createSingleOps(opStr string, reverse bool) planpb.RangeExpr_OpType {
return op return op
} }
func (context *ParserContext) handleCmpExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) { func getLogicalOpType(opStr string) planpb.BinaryExpr_BinaryOp {
idNode, leftOk := node.Left.(*ant_ast.IdentifierNode) switch opStr {
if !leftOk { case "&&", "and":
return nil, fmt.Errorf("compare require left to be identifier") return planpb.BinaryExpr_LogicalAnd
case "||", "or":
return planpb.BinaryExpr_LogicalOr
default:
return planpb.BinaryExpr_Invalid
} }
}
func (context *ParserContext) handleCmpExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) {
var idNode *ant_ast.IdentifierNode
var isReversed bool
var valueNode *ant_ast.Node
if idNodeLeft, leftOk := node.Left.(*ant_ast.IdentifierNode); leftOk {
idNode = idNodeLeft
isReversed = false
valueNode = &node.Right
} else if idNodeRight, rightOk := node.Right.(*ant_ast.IdentifierNode); rightOk {
idNode = idNodeRight
isReversed = true
valueNode = &node.Left
} else {
return nil, fmt.Errorf("compare expr has no identifier")
}
field, err := context.handleIdentifier(idNode) field, err := context.handleIdentifier(idNode)
if err != nil { if err != nil {
return nil, err return nil, err
} }
val, err := context.handleLeafValue(&node.Right, field.DataType) val, err := context.handleLeafValue(valueNode, field.DataType)
if err != nil { if err != nil {
return nil, err return nil, err
} }
op := createSingleOps(node.Operator, false) op := getCompareOpType(node.Operator, isReversed)
if op == planpb.RangeExpr_Invalid { if op == planpb.RangeExpr_Invalid {
return nil, fmt.Errorf("invalid binary operator %s", node.Operator) return nil, fmt.Errorf("invalid binary operator %s", node.Operator)
} }
final := &planpb.Expr{ expr := &planpb.Expr{
Expr: &planpb.Expr_RangeExpr{ Expr: &planpb.Expr_RangeExpr{
RangeExpr: &planpb.RangeExpr{ RangeExpr: &planpb.RangeExpr{
ColumnInfo: context.createColumnInfo(field), ColumnInfo: context.createColumnInfo(field),
@ -150,15 +144,76 @@ func (context *ParserContext) handleCmpExpr(node *ant_ast.BinaryNode) (*planpb.E
}, },
}, },
} }
return final, nil return expr, nil
} }
func (context *ParserContext) handleLogicalExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) { func (context *ParserContext) handleLogicalExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) {
return nil, fmt.Errorf("unimplemented") op := getLogicalOpType(node.Operator)
if op == planpb.BinaryExpr_Invalid {
return nil, fmt.Errorf("invalid logical op(%s)", node.Operator)
}
leftExpr, err := context.handleExpr(&node.Left)
if err != nil {
return nil, err
}
rightExpr, err := context.handleExpr(&node.Right)
if err != nil {
return nil, err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_BinaryExpr{
BinaryExpr: &planpb.BinaryExpr{
Op: op,
Left: leftExpr,
Right: rightExpr,
},
},
}
return expr, nil
}
func (context *ParserContext) handleArrayExpr(node *ant_ast.Node, dataType schemapb.DataType) ([]*planpb.GenericValue, error) {
arrayNode, ok2 := (*node).(*ant_ast.ArrayNode)
if !ok2 {
return nil, fmt.Errorf("right operand of the InExpr must be array")
}
var arr []*planpb.GenericValue
for _, element := range arrayNode.Nodes {
val, err := context.handleLeafValue(&element, dataType)
if err != nil {
return nil, err
}
arr = append(arr, val)
}
return arr, nil
} }
func (context *ParserContext) handleInExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) { func (context *ParserContext) handleInExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) {
return nil, fmt.Errorf("unimplemented") idNode, ok := node.Left.(*ant_ast.IdentifierNode)
if !ok {
return nil, fmt.Errorf("left operand of the InExpr must be identifier")
}
field, err := context.handleIdentifier(idNode)
if err != nil {
return nil, err
}
arrayData, err := context.handleArrayExpr(&node.Right, field.DataType)
if err != nil {
return nil, err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_TermExpr{
TermExpr: &planpb.TermExpr{
ColumnInfo: context.createColumnInfo(field),
Values: arrayData,
},
},
}
return expr, nil
} }
func (context *ParserContext) handleBinaryExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) { func (context *ParserContext) handleBinaryExpr(node *ant_ast.BinaryNode) (*planpb.Expr, error) {
@ -166,16 +221,24 @@ func (context *ParserContext) handleBinaryExpr(node *ant_ast.BinaryNode) (*planp
switch node.Operator { switch node.Operator {
case "<", "<=", ">", ">=", "==", "!=": case "<", "<=", ">", ">=", "==", "!=":
return context.handleCmpExpr(node) return context.handleCmpExpr(node)
case "and", "or": case "and", "or", "&&", "||":
return context.handleLogicalExpr(node) return context.handleLogicalExpr(node)
case "in", "not in": case "in", "not in":
return context.handleInExpr(node) return context.handleInExpr(node)
} }
return nil, fmt.Errorf("unimplemented") return nil, fmt.Errorf("unsupported binary operator %s", node.Operator)
} }
func (context *ParserContext) handleNotExpr(node *ant_ast.UnaryNode) (*planpb.Expr, error) { func (context *ParserContext) createNotExpr(childExpr *planpb.Expr) (*planpb.Expr, error) {
return nil, fmt.Errorf("unimplemented") expr := &planpb.Expr{
Expr: &planpb.Expr_UnaryExpr{
UnaryExpr: &planpb.UnaryExpr{
Op: planpb.UnaryExpr_Not,
Child: childExpr,
},
},
}
return expr, nil
} }
func (context *ParserContext) handleLeafValue(nodeRaw *ant_ast.Node, dataType schemapb.DataType) (gv *planpb.GenericValue, err error) { func (context *ParserContext) handleLeafValue(nodeRaw *ant_ast.Node, dataType schemapb.DataType) (gv *planpb.GenericValue, err error) {
@ -232,13 +295,17 @@ func (context *ParserContext) handleIdentifier(node *ant_ast.IdentifierNode) (*s
func (context *ParserContext) handleUnaryExpr(node *ant_ast.UnaryNode) (*planpb.Expr, error) { func (context *ParserContext) handleUnaryExpr(node *ant_ast.UnaryNode) (*planpb.Expr, error) {
switch node.Operator { switch node.Operator {
case "!", "not": case "!", "not":
return context.handleNotExpr(node) subExpr, err := context.handleExpr(&node.Node)
if err != nil {
return nil, err
}
return context.createNotExpr(subExpr)
default: default:
return nil, fmt.Errorf("invalid unary operator(%s)", node.Operator) return nil, fmt.Errorf("invalid unary operator(%s)", node.Operator)
} }
} }
func (context *ParserContext) parseExpr(nodeRaw *ant_ast.Node) (*planpb.Expr, error) { func (context *ParserContext) handleExpr(nodeRaw *ant_ast.Node) (*planpb.Expr, error) {
switch node := (*nodeRaw).(type) { switch node := (*nodeRaw).(type) {
case *ant_ast.IdentifierNode, case *ant_ast.IdentifierNode,
*ant_ast.FloatNode, *ant_ast.FloatNode,

View File

@ -1,9 +1,20 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed 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 proxynode package proxynode
import ( import (
"fmt"
"testing" "testing"
ant_ast "github.com/antonmedv/expr/ast"
ant_parser "github.com/antonmedv/expr/parser" ant_parser "github.com/antonmedv/expr/parser"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
@ -15,20 +26,31 @@ import (
) )
func newTestSchema() *schemapb.CollectionSchema { func newTestSchema() *schemapb.CollectionSchema {
fields := []*schemapb.FieldSchema{
{FieldID: 0, Name: "FieldID", IsPrimaryKey: false, Description: "field no.1", DataType: schemapb.DataType_Int64},
}
for name, value := range schemapb.DataType_value {
dataType := schemapb.DataType(value)
if !typeutil.IsIntergerType(dataType) && !typeutil.IsFloatingType(dataType) && !typeutil.IsVectorType(dataType) {
continue
}
newField := &schemapb.FieldSchema{
FieldID: int64(100 + value), Name: name + "Field", IsPrimaryKey: false, Description: "", DataType: dataType,
}
fields = append(fields, newField)
}
return &schemapb.CollectionSchema{ return &schemapb.CollectionSchema{
Name: "test", Name: "test",
Description: "schema for test used", Description: "schema for test used",
AutoID: true, AutoID: true,
Fields: []*schemapb.FieldSchema{ Fields: fields,
{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) { func TestParseQueryExpr_Naive(t *testing.T) {
exprStr := "int64Field > 3" exprStr := "Int64Field > 3"
schemaPb := newTestSchema() schemaPb := newTestSchema()
schema, err := typeutil.CreateSchemaHelper(schemaPb) schema, err := typeutil.CreateSchemaHelper(schemaPb)
assert.Nil(t, err) assert.Nil(t, err)
@ -39,7 +61,16 @@ func TestParseQueryExpr_Naive(t *testing.T) {
} }
func TestParsePlanNode_Naive(t *testing.T) { func TestParsePlanNode_Naive(t *testing.T) {
exprStr := "int64Field > 3" // exprStr := "not (int64Field > 3)"
exprStrs := []string{
"not (Int64Field > 3)",
"not (3 > Int64Field)",
"Int64Field in [1, 2, 3]",
"Int64Field < 3 and (Int64Field > 2 || Int64Field == 1)",
"DoubleField in [1.0, 2, 3]",
"DoubleField in [1.0, 2, 3] && Int64Field < 3 or Int64Field > 2",
}
schema := newTestSchema() schema := newTestSchema()
queryInfo := &planpb.QueryInfo{ queryInfo := &planpb.QueryInfo{
Topk: 10, Topk: 10,
@ -49,20 +80,19 @@ func TestParsePlanNode_Naive(t *testing.T) {
// Note: use pointer to string to represent nullable string // Note: use pointer to string to represent nullable string
// TODO: change it to better solution // TODO: change it to better solution
planProto, err := CreateQueryPlan(schema, &exprStr, "vectorField", queryInfo) for offset, exprStr := range exprStrs {
fmt.Printf("case %d: %s\n", offset, exprStr)
planProto, err := CreateQueryPlan(schema, &exprStr, "FloatVectorField", queryInfo)
assert.Nil(t, err) assert.Nil(t, err)
dbgStr := proto.MarshalTextString(planProto) dbgStr := proto.MarshalTextString(planProto)
println(dbgStr) println(dbgStr)
}
} }
func TestExternalParser(t *testing.T) { 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 ") ast, err := ant_parser.Parse("!(1 < a < 2 or b in [1, 2, 3]) or (c < 3 and b > 5)")
// NOTE: probe ast here via IDE
var node ant_ast.Node = nil
if node == nil {
// TODO
}
assert.Nil(t, err) assert.Nil(t, err)
println(ast.Node.Location().Column) println(ast.Node.Location().Column)