Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support variable when seeking by property index in match clause #5553

Merged
merged 10 commits into from
May 18, 2023
Prev Previous commit
Next Next commit
Move the index query context construction outside of OptRule
  • Loading branch information
yixinglu committed May 16, 2023
commit 5bae72a4ae69ea9d7391e8c43f135ce5b4edc9de
499 changes: 499 additions & 0 deletions src/graph/optimizer/OptimizerUtils.cpp

Large diffs are not rendered by default.

125 changes: 114 additions & 11 deletions src/graph/optimizer/OptimizerUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ class OptimizerUtils {
OptimizerUtils() = delete;

// Compare `a` and `b`, if `a`>`b` then swap a and b.That means `b`>=`a` after call this function.
static Status compareAndSwapBound(std::pair<Value, bool>& a, std::pair<Value, bool>& b);
static Status compareAndSwapBound(std::pair<Value, bool> &a, std::pair<Value, bool> &b);
static void eraseInvalidIndexItems(
int32_t schemaId, std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>>* indexItems);
int32_t schemaId, std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>> *indexItems);

// Find optimal index according to filter expression and all valid indexes.
//
Expand Down Expand Up @@ -64,18 +64,121 @@ class OptimizerUtils {
// different `IndexQueryContext' for each operand of filter condition, nebula
// storage will union all results of multiple index contexts
static bool findOptimalIndex(
const Expression* condition,
const std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>>& indexItems,
bool* isPrefixScan,
nebula::storage::cpp2::IndexQueryContext* ictx);
const Expression *condition,
const std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>> &indexItems,
bool *isPrefixScan,
nebula::storage::cpp2::IndexQueryContext *ictx);

static bool relExprHasIndex(
const Expression* expr,
const std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>>& indexItems);
const Expression *expr,
const std::vector<std::shared_ptr<nebula::meta::cpp2::IndexItem>> &indexItems);

static void copyIndexScanData(const nebula::graph::IndexScan* from,
nebula::graph::IndexScan* to,
QueryContext* qctx);
static void copyIndexScanData(const nebula::graph::IndexScan *from,
nebula::graph::IndexScan *to,
QueryContext *qctx);

//---------------------------------------------------------------

using IndexItemPtr = std::shared_ptr<meta::cpp2::IndexItem>;
using IndexQueryContextList = std::vector<storage::cpp2::IndexQueryContext>;

struct ScanKind {
enum class Kind {
kUnknown = 0,
kMultipleScan,
kSingleScan,
};

private:
Kind kind_;

public:
ScanKind() {
kind_ = Kind::kUnknown;
}
void setKind(Kind k) {
kind_ = k;
}
Kind getKind() {
return kind_;
}
bool isSingleScan() {
return kind_ == Kind::kSingleScan;
}
};

// col_ : index column name
// relOP_ : Relational operator , for example c1 > 1 , the relOP_ == kRelGT
// 1 > c1 , the relOP_ == kRelLT
// value_ : Constant value. from ConstantExpression.
struct FilterItem {
std::string col_;
Expression::Kind relOP_;
Value value_;

FilterItem(const std::string &col, RelationalExpression::Kind relOP, const Value &value)
: col_(col), relOP_(relOP), value_(value) {}
};

static Status createIndexQueryCtx(Expression *filter,
QueryContext *qctx,
const IndexScan *node,
IndexQueryContextList &iqctx);

static Status createIndexQueryCtx(IndexQueryContextList &iqctx,
QueryContext *qctx,
const IndexScan *node);

static Status createIndexQueryCtx(IndexQueryContextList &iqctx,
ScanKind kind,
const std::vector<FilterItem> &items,
graph::QueryContext *qctx,
const IndexScan *node);
static IndexItemPtr findLightestIndex(graph::QueryContext *qctx, const IndexScan *node);

static Status createMultipleIQC(IndexQueryContextList &iqctx,
const std::vector<FilterItem> &items,
graph::QueryContext *qctx,
const IndexScan *node);
static Status createSingleIQC(IndexQueryContextList &iqctx,
const std::vector<FilterItem> &items,
graph::QueryContext *qctx,
const IndexScan *node);
static Status appendIQCtx(const IndexItemPtr &index,
const std::vector<FilterItem> &items,
IndexQueryContextList &iqctx,
const Expression *filter = nullptr);
static Status appendIQCtx(const IndexItemPtr &index, IndexQueryContextList &iqctx);
static Status appendColHint(std::vector<storage::cpp2::IndexColumnHint> &hints,
const std::vector<FilterItem> &items,
const meta::cpp2::ColumnDef &col);
static bool verifyType(const Value &val);
static size_t hintCount(const std::vector<FilterItem> &items);
static IndexItemPtr findOptimalIndex(graph::QueryContext *qctx,
const IndexScan *node,
const std::vector<FilterItem> &items);
static std::vector<IndexItemPtr> findIndexForRangeScan(const std::vector<IndexItemPtr> &indexes,
const std::vector<FilterItem> &items);
static std::vector<IndexItemPtr> findIndexForEqualScan(const std::vector<IndexItemPtr> &indexes,
const std::vector<FilterItem> &items);
static std::vector<IndexItemPtr> findValidIndex(graph::QueryContext *qctx,
const IndexScan *node,
const std::vector<FilterItem> &items);
static std::vector<IndexItemPtr> allIndexesBySchema(graph::QueryContext *qctx,
const IndexScan *node);
static Status analyzeExpression(Expression *expr,
std::vector<FilterItem> *items,
ScanKind *kind,
bool isEdge,
QueryContext *qctx);

template <typename E,
typename = std::enable_if_t<std::is_same<E, EdgePropertyExpression>::value ||
std::is_same<E, LabelTagPropertyExpression>::value ||
std::is_same<E, TagPropertyExpression>::value>>
static Status addFilterItem(RelationalExpression *expr,
std::vector<FilterItem> *items,
QueryContext *qctx);
};

} // namespace graph
Expand Down
Loading