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
refactor and fix error
  • Loading branch information
yixinglu committed May 16, 2023
commit 783cfdabba7b769784c0257be3b71927b12135d9
4 changes: 4 additions & 0 deletions src/graph/executor/logic/ArgumentExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ folly::Future<Status> ArgumentExecutor::execute() {
for (auto &v : val.getList().values) {
addRow(v);
}
} else if (val.isSet()) {
for (auto &v : val.getSet().values) {
addRow(v);
}
} else {
addRow(val);
}
Expand Down
39 changes: 9 additions & 30 deletions src/graph/executor/query/IndexScanExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,42 +38,21 @@ folly::Future<Status> IndexScanExecutor::indexScan() {
}
const auto &colName = static_cast<const LabelExpression *>(relFilter->right())->name();
const auto &result = ectx_->getResult(lookup->inputVar());
auto iter = result.iterRef();
if (iter->empty()) {
return finish(ResultBuilder().value(Value(List())).iter(Iterator::Kind::kProp).build());
}

Set vals;
if (filter->kind() == Expression::Kind::kRelIn) {
if (iter->size() != 1u) {
return Status::Error("IN expression could not support multi-rows index scan.");
}
const auto &val = iter->getColumn(colName);
if (!val.isList() && !val.isSet()) {
return Status::Error("The values is not list or set in expression: %s",
filter->toString().c_str());
}
if (val.isList()) {
const auto &listVals = val.getList().values;
vals.values.insert(listVals.begin(), listVals.end());
} else {
const auto &setVals = val.getSet().values;
vals.values.insert(setVals.begin(), setVals.end());
}
} else {
vals.values.reserve(iter->size());
for (; iter->valid(); iter->next()) {
vals.values.emplace(iter->getColumn(colName));
}
}

std::vector<Expression *> ops;
for (auto &val : vals.values) {
std::unordered_set<Value> unique;
for (auto iter = result.iterRef(); iter->valid(); iter->next()) {
const auto &val = iter->getColumn(colName);
if (!unique.emplace(val).second) continue;
auto constExpr = ConstantExpression::make(objPool, val);
auto leftExpr = relFilter->left()->clone();
auto newRelExpr = RelationalExpression::makeEQ(objPool, leftExpr, constExpr);
ops.push_back(newRelExpr);
}

if (ops.empty()) {
return finish(ResultBuilder().value(Value(List())).iter(Iterator::Kind::kProp).build());
}

if (ops.size() == 1u) {
NG_RETURN_IF_ERROR(OptimizerUtils::createIndexQueryCtx(ops[0], qctx(), lookup, ictxs));
} else {
Expand Down
31 changes: 15 additions & 16 deletions src/graph/planner/match/VariablePropIndexSeek.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,37 +35,31 @@ bool VariablePropIndexSeek::matchNode(NodeContext* nodeCtx) {
if (!whereClause || !whereClause->filter) return false;

auto filter = whereClause->filter;
std::string refVarName, propName;
std::string refVarName;
std::shared_ptr<IndexItem> idxItem;
Expression* indexFilter = nullptr;
if (filter->kind() == Expression::Kind::kLogicalAnd) {
auto logExpr = static_cast<const LogicalExpression*>(filter);
bool found = false;
for (auto op : logExpr->operands()) {
if (getIndexItem(nodeCtx, op, label, nodeInfo.alias, &refVarName, &propName, &idxItem)) {
if (!nodeCtx->aliasesAvailable->count(refVarName)) {
return false;
}
if (getIndexItem(nodeCtx, op, label, nodeInfo.alias, &refVarName, &indexFilter, &idxItem)) {
// TODO(yee): Only select the first index as candidate filter expression and not support
// the combined index
indexFilter = TagPropertyExpression::make(nodeCtx->qctx->objPool(), label, propName);
found = true;
break;
}
}
if (!found) return false;
} else {
if (!getIndexItem(nodeCtx, filter, label, nodeInfo.alias, &refVarName, &propName, &idxItem)) {
if (!getIndexItem(
nodeCtx, filter, label, nodeInfo.alias, &refVarName, &indexFilter, &idxItem)) {
return false;
}

if (!nodeCtx->aliasesAvailable->count(refVarName)) {
return false;
}

indexFilter = TagPropertyExpression::make(nodeCtx->qctx->objPool(), label, propName);
}

if (!nodeCtx->aliasesAvailable->count(refVarName)) {
return false;
}
nodeCtx->refVarName = refVarName;

nodeCtx->scanInfo.filter = DCHECK_NOTNULL(indexFilter);
Expand Down Expand Up @@ -105,7 +99,7 @@ bool VariablePropIndexSeek::getIndexItem(const NodeContext* nodeCtx,
const std::string& label,
const std::string& alias,
std::string* refVarName,
std::string* propName,
Expression** indexFilter,
std::shared_ptr<IndexItem>* idxItem) {
if (filter->kind() != Expression::Kind::kRelEQ && filter->kind() != Expression::Kind::kRelIn) {
return false;
Expand All @@ -117,7 +111,8 @@ bool VariablePropIndexSeek::getIndexItem(const NodeContext* nodeCtx,
return false;
}

if (!MatchSolver::extractTagPropName(relInExpr->left(), alias, label, propName)) {
std::string propName;
if (!MatchSolver::extractTagPropName(relInExpr->left(), alias, label, &propName)) {
return false;
}
// TODO(yee): workaround for index selection
Expand All @@ -129,7 +124,7 @@ bool VariablePropIndexSeek::getIndexItem(const NodeContext* nodeCtx,
auto schemaId = itemPtr->get_schema_id();
if (schemaId.get_tag_id() == nodeCtx->info->tids.back()) {
const auto& fields = itemPtr->get_fields();
if (!fields.empty() && fields.front().get_name() == *propName) {
if (!fields.empty() && fields.front().get_name() == propName) {
idxItemList.push_back(itemPtr);
}
}
Expand All @@ -140,6 +135,10 @@ bool VariablePropIndexSeek::getIndexItem(const NodeContext* nodeCtx,
});
*refVarName = static_cast<const LabelExpression*>(right)->name();
*idxItem = idxItemList.front();
auto objPool = nodeCtx->qctx->objPool();
auto tagPropExpr = TagPropertyExpression::make(objPool, label, propName);
*indexFilter =
RelationalExpression::makeKind(objPool, filter->kind(), tagPropExpr, right->clone());
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/graph/planner/match/VariablePropIndexSeek.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class VariablePropIndexSeek final : public StartVidFinder {
const std::string& label,
const std::string& alias,
std::string* refVarName,
std::string* propName,
Expression** indexFilter,
std::shared_ptr<meta::cpp2::IndexItem>* idxItem);
};

Expand Down