diff --git a/src/context/QueryExpressionContext.h b/src/context/QueryExpressionContext.h index fb7721ddfcf1198a18bccf874fca08a5cdf27ecb..afc062bcb4cb55cbe25f998a6f6338419df648d7 100644 --- a/src/context/QueryExpressionContext.h +++ b/src/context/QueryExpressionContext.h @@ -17,9 +17,8 @@ namespace graph { class QueryExpressionContext final : public ExpressionContext { public: - explicit QueryExpressionContext(ExecutionContext* ectx, Iterator* iter = nullptr) { + explicit QueryExpressionContext(ExecutionContext* ectx = nullptr) { ectx_ = ectx; - iter_ = iter; } // Get the latest version value for the given variable name, such as $a, $b @@ -60,13 +59,17 @@ public: void setVar(const std::string&, Value val) override; - void setIter(Iterator* iter) { + QueryExpressionContext& operator()(Iterator* iter) { iter_ = iter; + return *this; } private: - ExecutionContext* ectx_; - Iterator* iter_; + // ExecutionContext and Iterator are used for getting runtime results, + // and nullptr is acceptable for these two members if the expressions + // could be evaluated as constant value. + ExecutionContext* ectx_{nullptr}; + Iterator* iter_{nullptr}; }; } // namespace graph diff --git a/src/context/test/ExpressionContextTest.cpp b/src/context/test/ExpressionContextTest.cpp index 698f7c98ca49e7f24380f9462973b1400e039c0c..2c1d9fcc2a266c20782327420db4b76e8d6dd3c3 100644 --- a/src/context/test/ExpressionContextTest.cpp +++ b/src/context/test/ExpressionContextTest.cpp @@ -11,20 +11,20 @@ namespace nebula { namespace graph { TEST(ExpressionContextTest, GetVar) { - ExecutionContext qctx; - qctx.setValue("v1", 10); - qctx.setValue("v2", "Hello world"); + ExecutionContext ectx; + ectx.setValue("v1", 10); + ectx.setValue("v2", "Hello world"); - graph::QueryExpressionContext ectx(&qctx, nullptr); - EXPECT_EQ(Value(10), ectx.getVar("v1")); - EXPECT_EQ(Value("Hello world"), ectx.getVar("v2")); + graph::QueryExpressionContext qECtx(&ectx); + EXPECT_EQ(Value(10), qECtx(nullptr).getVar("v1")); + EXPECT_EQ(Value("Hello world"), qECtx(nullptr).getVar("v2")); - qctx.setValue("v1", "Hello world"); - qctx.setValue("v1", 3.14); - qctx.setValue("v1", true); - EXPECT_EQ(Value(true), ectx.getVersionedVar("v1", 0)); - EXPECT_EQ(Value(3.14), ectx.getVersionedVar("v1", -1)); - EXPECT_EQ(Value(10), ectx.getVersionedVar("v1", 1)); + ectx.setValue("v1", "Hello world"); + ectx.setValue("v1", 3.14); + ectx.setValue("v1", true); + EXPECT_EQ(Value(true), qECtx(nullptr).getVersionedVar("v1", 0)); + EXPECT_EQ(Value(3.14), qECtx(nullptr).getVersionedVar("v1", -1)); + EXPECT_EQ(Value(10), qECtx(nullptr).getVersionedVar("v1", 1)); } } // namespace graph } // namespace nebula diff --git a/src/executor/logic/LoopExecutor.cpp b/src/executor/logic/LoopExecutor.cpp index 3d8bdb480274df255de0372e7301e4aedb054f8f..1a9ba532f450976deb987edb651904821caab681 100644 --- a/src/executor/logic/LoopExecutor.cpp +++ b/src/executor/logic/LoopExecutor.cpp @@ -27,7 +27,7 @@ folly::Future<Status> LoopExecutor::execute() { auto *loopNode = asNode<Loop>(node()); Expression *expr = loopNode->condition(); - QueryExpressionContext ctx(ectx_, nullptr); + QueryExpressionContext ctx(ectx_); auto value = expr->eval(ctx); VLOG(1) << "Loop condition: " << value; DCHECK(value.isBool()); diff --git a/src/executor/logic/SelectExecutor.cpp b/src/executor/logic/SelectExecutor.cpp index 522f06130e29f9514f42049ed79949cc7ef8392f..9a3f92887d82d94cd8f7c71b3d62e02bea256191 100644 --- a/src/executor/logic/SelectExecutor.cpp +++ b/src/executor/logic/SelectExecutor.cpp @@ -27,7 +27,7 @@ folly::Future<Status> SelectExecutor::execute() { auto* select = asNode<Select>(node()); auto* expr = select->condition(); - QueryExpressionContext ctx(ectx_, nullptr); + QueryExpressionContext ctx(ectx_); auto value = expr->eval(ctx); DCHECK(value.isBool()); return finish(ResultBuilder().value(std::move(value)).iter(Iterator::Kind::kDefault).finish()); diff --git a/src/executor/mutate/DeleteExecutor.cpp b/src/executor/mutate/DeleteExecutor.cpp index 510c43ba1499d4725cdc4dc3c04eaaf46612011d..9c10bf435f34ed0f128f5c95367b9afc07e7eba1 100644 --- a/src/executor/mutate/DeleteExecutor.cpp +++ b/src/executor/mutate/DeleteExecutor.cpp @@ -38,9 +38,9 @@ folly::Future<Status> DeleteVerticesExecutor::deleteVertices() { auto& inputResult = ectx_->getResult(inputVar); auto iter = inputResult.iter(); vertices.reserve(iter->size()); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); for (; iter->valid(); iter->next()) { - auto val = Expression::eval(vidRef, ctx); + auto val = Expression::eval(vidRef, ctx(iter.get())); if (val.isNull() || val.empty()) { VLOG(3) << "NULL or EMPTY vid"; continue; @@ -90,11 +90,11 @@ folly::Future<Status> DeleteEdgesExecutor::deleteEdges() { return Status::OK(); } edgeKeys.reserve(iter->size()); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); for (; iter->valid(); iter->next()) { for (auto &edgeKeyRef : edgeKeyRefs) { storage::cpp2::EdgeKey edgeKey; - auto srcId = Expression::eval(edgeKeyRef->srcid(), ctx); + auto srcId = Expression::eval(edgeKeyRef->srcid(), ctx(iter.get())); if (srcId.isNull() || srcId.empty()) { VLOG(3) << "NULL or EMPTY vid"; continue; @@ -105,14 +105,14 @@ folly::Future<Status> DeleteEdgesExecutor::deleteEdges() { << "`, value `" << srcId.toString() << "'"; return Status::Error(ss.str()); } - auto dstId = Expression::eval(edgeKeyRef->dstid(), ctx); + auto dstId = Expression::eval(edgeKeyRef->dstid(), ctx(iter.get())); if (!dstId.isStr()) { std::stringstream ss; ss << "Wrong dstId type `" << dstId.type() << "', value `" << dstId.toString() << "'"; return Status::Error(ss.str()); } - auto rank = Expression::eval(edgeKeyRef->rank(), ctx); + auto rank = Expression::eval(edgeKeyRef->rank(), ctx(iter.get())); if (!rank.isInt()) { std::stringstream ss; ss << "Wrong rank type `" << rank.type() @@ -120,7 +120,7 @@ folly::Future<Status> DeleteEdgesExecutor::deleteEdges() { return Status::Error(ss.str()); } DCHECK(edgeKeyRef->type()); - auto type = Expression::eval(edgeKeyRef->type(), ctx); + auto type = Expression::eval(edgeKeyRef->type(), ctx(iter.get())); if (!type.isInt()) { std::stringstream ss; ss << "Wrong edge type `" << type.type() diff --git a/src/executor/query/AggregateExecutor.cpp b/src/executor/query/AggregateExecutor.cpp index 201ab01976ffcd67e5a89d9f1d3e3c91b1ce07ee..d1e8316e0990f0f2c65b6a8ebce7caf37a32d3e9 100644 --- a/src/executor/query/AggregateExecutor.cpp +++ b/src/executor/query/AggregateExecutor.cpp @@ -24,14 +24,13 @@ folly::Future<Status> AggregateExecutor::execute() { auto groupItems = agg->groupItems(); auto iter = ectx_->getResult(agg->inputVar()).iter(); DCHECK(!!iter); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); std::unordered_map<List, std::vector<std::unique_ptr<AggFun>>> result; for (; iter->valid(); iter->next()) { List list; for (auto& key : groupKeys) { - ctx.setIter(iter.get()); - list.values.emplace_back(key->eval(ctx)); + list.values.emplace_back(key->eval(ctx(iter.get()))); } auto it = result.find(list); @@ -39,7 +38,7 @@ folly::Future<Status> AggregateExecutor::execute() { std::vector<std::unique_ptr<AggFun>> funs; for (auto& item : groupItems) { auto fun = AggFun::aggFunMap_[item.func](item.distinct); - auto& v = item.expr->eval(ctx); + auto& v = item.expr->eval(ctx(iter.get())); fun->apply(v); funs.emplace_back(std::move(fun)); } @@ -47,7 +46,7 @@ folly::Future<Status> AggregateExecutor::execute() { } else { DCHECK_EQ(it->second.size(), groupItems.size()); for (size_t i = 0; i < groupItems.size(); ++i) { - auto& v = groupItems[i].expr->eval(ctx); + auto& v = groupItems[i].expr->eval(ctx(iter.get())); it->second[i]->apply(v); } } diff --git a/src/executor/query/DataJoinExecutor.cpp b/src/executor/query/DataJoinExecutor.cpp index 6b68342c205843d3377251a19f368bc8bd022556..873211c277c94062949d5fd5b536109f06543e5f 100644 --- a/src/executor/query/DataJoinExecutor.cpp +++ b/src/executor/query/DataJoinExecutor.cpp @@ -73,12 +73,12 @@ folly::Future<Status> DataJoinExecutor::doInnerJoin() { void DataJoinExecutor::buildHashTable(const std::vector<Expression*>& hashKeys, Iterator* iter) { - QueryExpressionContext ctx(ectx_, iter); + QueryExpressionContext ctx(ectx_); for (; iter->valid(); iter->next()) { List list; list.values.reserve(hashKeys.size()); for (auto& col : hashKeys) { - Value val = col->eval(ctx); + Value val = col->eval(ctx(iter)); list.values.emplace_back(std::move(val)); } @@ -89,12 +89,12 @@ void DataJoinExecutor::buildHashTable(const std::vector<Expression*>& hashKeys, void DataJoinExecutor::probe(const std::vector<Expression*>& probeKeys, Iterator* probeIter, JoinIter* resultIter) { - QueryExpressionContext ctx(ectx_, probeIter); + QueryExpressionContext ctx(ectx_); for (; probeIter->valid(); probeIter->next()) { List list; list.values.reserve(probeKeys.size()); for (auto& col : probeKeys) { - Value val = col->eval(ctx); + Value val = col->eval(ctx(probeIter)); list.values.emplace_back(std::move(val)); } diff --git a/src/executor/query/DedupExecutor.cpp b/src/executor/query/DedupExecutor.cpp index 5251b65e68abfc8f71e4a3b208e644598aeb080b..9952b8357d634deddfb244a7372fdf09b8ecc402 100644 --- a/src/executor/query/DedupExecutor.cpp +++ b/src/executor/query/DedupExecutor.cpp @@ -28,7 +28,6 @@ folly::Future<Status> DedupExecutor::execute() { } ResultBuilder builder; builder.value(iter->valuePtr()); - QueryExpressionContext ctx(ectx_, iter.get()); std::unordered_set<const LogicalRow*> unique; while (iter->valid()) { if (unique.find(iter->row()) != unique.end()) { diff --git a/src/executor/query/FilterExecutor.cpp b/src/executor/query/FilterExecutor.cpp index 8ed9280fbfa5a9a2b8bfe01de769fc26e067ea9c..dfe78a6f19a773f51db557d7126fe23f0ac056de 100644 --- a/src/executor/query/FilterExecutor.cpp +++ b/src/executor/query/FilterExecutor.cpp @@ -25,10 +25,10 @@ folly::Future<Status> FilterExecutor::execute() { } ResultBuilder builder; builder.value(iter->valuePtr()); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); auto condition = filter->condition(); while (iter->valid()) { - auto val = condition->eval(ctx); + auto val = condition->eval(ctx(iter.get())); if (!val.isBool() && !val.isNull()) { return Status::Error("Internal Error: Wrong type result, " "should be NULL type or BOOL type"); diff --git a/src/executor/query/GetEdgesExecutor.cpp b/src/executor/query/GetEdgesExecutor.cpp index 922ba93a55f2809d74a8acdd6404c6e5a4440cad..a8000c5cd653b35a1951e1497a71f8d64852426f 100644 --- a/src/executor/query/GetEdgesExecutor.cpp +++ b/src/executor/query/GetEdgesExecutor.cpp @@ -33,12 +33,12 @@ folly::Future<Status> GetEdgesExecutor::getEdges() { ge->dst() != nullptr) { // Accept Table such as | $a | $b | $c | $d |... which indicate src, ranking or dst auto valueIter = ectx_->getResult(ge->inputVar()).iter(); - auto expCtx = QueryExpressionContext(qctx()->ectx(), valueIter.get()); + auto expCtx = QueryExpressionContext(qctx()->ectx()); for (; valueIter->valid(); valueIter->next()) { - auto src = ge->src()->eval(expCtx); - auto type = ge->type()->eval(expCtx); - auto ranking = ge->ranking()->eval(expCtx); - auto dst = ge->dst()->eval(expCtx); + auto src = ge->src()->eval(expCtx(valueIter.get())); + auto type = ge->type()->eval(expCtx(valueIter.get())); + auto ranking = ge->ranking()->eval(expCtx(valueIter.get())); + auto dst = ge->dst()->eval(expCtx(valueIter.get())); if (!src.isStr() || !type.isInt() || !ranking.isInt() || !dst.isStr()) { LOG(WARNING) << "Mismatched edge key type"; continue; diff --git a/src/executor/query/GetNeighborsExecutor.cpp b/src/executor/query/GetNeighborsExecutor.cpp index f1e595a4dd24a765f9c2a9982db1243eea89b137..e1082e5d6b0bed9e5c688c4c458dd2841cf3bdc0 100644 --- a/src/executor/query/GetNeighborsExecutor.cpp +++ b/src/executor/query/GetNeighborsExecutor.cpp @@ -41,14 +41,14 @@ Status GetNeighborsExecutor::buildRequestDataSet() { VLOG(1) << node()->varName() << " : " << inputVar; auto& inputResult = ectx_->getResult(inputVar); auto iter = inputResult.iter(); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); DataSet input; reqDs_.colNames = {kVid}; reqDs_.rows.reserve(iter->size()); auto* src = gn_->src(); std::unordered_set<Value> uniqueVid; for (; iter->valid(); iter->next()) { - auto val = Expression::eval(src, ctx); + auto val = Expression::eval(src, ctx(iter.get())); if (!val.isStr()) { continue; } diff --git a/src/executor/query/GetVerticesExecutor.cpp b/src/executor/query/GetVerticesExecutor.cpp index 5469d5f81617b58e36dec0759e53761266894fa7..89ef0a3192b0d830de64ea53e22fcf08ca6ac9bd 100644 --- a/src/executor/query/GetVerticesExecutor.cpp +++ b/src/executor/query/GetVerticesExecutor.cpp @@ -31,9 +31,9 @@ folly::Future<Status> GetVerticesExecutor::getVertices() { // Accept Table such as | $a | $b | $c |... as input which one column indicate src auto valueIter = ectx_->getResult(gv->inputVar()).iter(); VLOG(1) << "GV input var: " << gv->inputVar() << " iter kind: " << valueIter->kind(); - auto expCtx = QueryExpressionContext(qctx()->ectx(), valueIter.get()); + auto expCtx = QueryExpressionContext(qctx()->ectx()); for (; valueIter->valid(); valueIter->next()) { - auto src = gv->src()->eval(expCtx); + auto src = gv->src()->eval(expCtx(valueIter.get())); VLOG(1) << "src vid: " << src; if (!src.isStr()) { LOG(WARNING) << "Mismatched vid type: " << src.type(); diff --git a/src/executor/query/LimitExecutor.cpp b/src/executor/query/LimitExecutor.cpp index 880523d3949e84b469d9aee4d43e1d78b8535a1a..04979b2a3ddcbeaec6a3262882338dfca6795bc8 100644 --- a/src/executor/query/LimitExecutor.cpp +++ b/src/executor/query/LimitExecutor.cpp @@ -5,7 +5,6 @@ */ #include "executor/query/LimitExecutor.h" -#include "context/QueryExpressionContext.h" #include "planner/Query.h" #include "util/ScopedTimer.h" @@ -19,7 +18,6 @@ folly::Future<Status> LimitExecutor::execute() { auto iter = ectx_->getResult(limit->inputVar()).iter(); ResultBuilder builder; builder.value(iter->valuePtr()); - QueryExpressionContext ctx(ectx_, iter.get()); auto offset = limit->offset(); auto count = limit->count(); auto size = iter->size(); diff --git a/src/executor/query/ProjectExecutor.cpp b/src/executor/query/ProjectExecutor.cpp index 2cb872d3c92b8f9144204e7c155cad28644bce1a..f68709adfbb34098dc60a7b5b73920579898926f 100644 --- a/src/executor/query/ProjectExecutor.cpp +++ b/src/executor/query/ProjectExecutor.cpp @@ -20,7 +20,7 @@ folly::Future<Status> ProjectExecutor::execute() { auto columns = project->columns()->columns(); auto iter = ectx_->getResult(project->inputVar()).iter(); DCHECK(!!iter); - QueryExpressionContext ctx(ectx_, iter.get()); + QueryExpressionContext ctx(ectx_); VLOG(1) << "input: " << project->inputVar(); DataSet ds; @@ -28,7 +28,7 @@ folly::Future<Status> ProjectExecutor::execute() { for (; iter->valid(); iter->next()) { Row row; for (auto& col : columns) { - Value val = col->expr()->eval(ctx); + Value val = col->expr()->eval(ctx(iter.get())); row.values.emplace_back(std::move(val)); } ds.rows.emplace_back(std::move(row)); diff --git a/src/executor/query/SortExecutor.cpp b/src/executor/query/SortExecutor.cpp index bb58abf10401f133675574cf28fcdcf538407aa5..9fabe9855a37be8cfb991cb10def2738b654152f 100644 --- a/src/executor/query/SortExecutor.cpp +++ b/src/executor/query/SortExecutor.cpp @@ -5,7 +5,6 @@ */ #include "executor/query/SortExecutor.h" -#include "context/QueryExpressionContext.h" #include "planner/Query.h" #include "util/ScopedTimer.h" diff --git a/src/parser/MaintainSentences.h b/src/parser/MaintainSentences.h index b84ea115f87fcc1256c68c52ea6fd06f0b74d4d0..c42d5a6a4172bb52e9502de027414f3c004aeceb 100644 --- a/src/parser/MaintainSentences.h +++ b/src/parser/MaintainSentences.h @@ -53,7 +53,7 @@ public: } Value getDefaultValue() const { - graph::QueryExpressionContext ctx(nullptr, nullptr); + graph::QueryExpressionContext ctx(nullptr); return defaultValue_->eval(ctx); } diff --git a/src/util/SchemaUtil.cpp b/src/util/SchemaUtil.cpp index 768da9044378bb54afa462e3c96c6694f36304af..7099f4d9888a4cd00c27185837f87dbbc79057b3 100644 --- a/src/util/SchemaUtil.cpp +++ b/src/util/SchemaUtil.cpp @@ -188,8 +188,8 @@ Status SchemaUtil::setTTLCol(SchemaPropItem* schemaProp, meta::cpp2::Schema& sch // static StatusOr<VertexID> SchemaUtil::toVertexID(Expression *expr) { - QueryExpressionContext ctx(nullptr, nullptr); - auto vertexId = expr->eval(ctx); + QueryExpressionContext ctx; + auto vertexId = expr->eval(ctx(nullptr)); if (vertexId.type() != Value::Type::STRING) { LOG(ERROR) << "Wrong vertex id type"; return Status::Error("Wrong vertex id type"); @@ -202,9 +202,9 @@ StatusOr<std::vector<Value>> SchemaUtil::toValueVec(std::vector<Expression*> exprs) { std::vector<Value> values; values.reserve(exprs.size()); - QueryExpressionContext ctx(nullptr, nullptr); + QueryExpressionContext ctx; for (auto *expr : exprs) { - auto value = expr->eval(ctx); + auto value = expr->eval(ctx(nullptr)); if (value.isNull() && value.getNull() != NullType::__NULL__) { LOG(ERROR) << "Wrong value type: " << value.type();; return Status::Error("Wrong value type"); diff --git a/src/validator/AdminValidator.cpp b/src/validator/AdminValidator.cpp index e9b02a84e117017aa67ec9ceeb7f26f45bee3787..aeb6ca8b96993a09315a45826249a439fcc01832 100644 --- a/src/validator/AdminValidator.cpp +++ b/src/validator/AdminValidator.cpp @@ -277,7 +277,7 @@ Status SetConfigValidator::validateImpl() { name_ = *item->getName(); module_ = item->getModule(); auto updateItems = item->getUpdateItems(); - QueryExpressionContext ctx(nullptr, nullptr); + QueryExpressionContext ctx; if (updateItems == nullptr) { module_ = item->getModule(); if (item->getName() != nullptr) { @@ -285,7 +285,7 @@ Status SetConfigValidator::validateImpl() { } if (item->getValue() != nullptr) { - value_ = Expression::eval(item->getValue(), ctx); + value_ = Expression::eval(item->getValue(), ctx(nullptr)); } } else { Map configs; @@ -297,7 +297,7 @@ Status SetConfigValidator::validateImpl() { } name = *updateItem->getFieldName(); - value = Expression::eval(const_cast<Expression*>(updateItem->value()), ctx); + value = Expression::eval(const_cast<Expression*>(updateItem->value()), ctx(nullptr)); if (value.isNull() || (!value.isNumeric() && !value.isStr() && !value.isBool())) { return Status::Error("Wrong value: %s", name.c_str()); diff --git a/src/validator/TraversalValidator.cpp b/src/validator/TraversalValidator.cpp index 042faaa74f3bdfe2845a41332c5c12060ff1aafc..f2597e592e2b8184edd851a648890c2be58b8bc6 100644 --- a/src/validator/TraversalValidator.cpp +++ b/src/validator/TraversalValidator.cpp @@ -74,13 +74,13 @@ Status TraversalValidator::validateFrom(const FromClause* from) { } } else { auto vidList = from->vidList(); - QueryExpressionContext ctx(qctx_->ectx(), nullptr); + QueryExpressionContext ctx; for (auto* expr : vidList) { if (!evaluableExpr(expr)) { return Status::Error("`%s' is not an evaluable expression.", expr->toString().c_str()); } - auto vid = expr->eval(ctx); + auto vid = expr->eval(ctx(nullptr)); if (!vid.isStr()) { return Status::Error("Vid should be a string."); } diff --git a/src/validator/Validator.cpp b/src/validator/Validator.cpp index 3122c28980d0158e42287e976a407e2ca1727f8a..b8f40e4e8a93316386bc01c5f13692a8aa94542a 100644 --- a/src/validator/Validator.cpp +++ b/src/validator/Validator.cpp @@ -452,9 +452,9 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { << castExpr->type(); return Status::Error(out.str()); } - QueryExpressionContext ctx(nullptr, nullptr); + QueryExpressionContext ctx; auto* typeCastExpr = const_cast<TypeCastingExpression*>(castExpr); - auto val = typeCastExpr->eval(ctx); + auto val = typeCastExpr->eval(ctx(nullptr)); if (val.isNull()) { return Status::SemanticError("`%s` is not a valid expression ", expr->toString().c_str()); @@ -540,9 +540,9 @@ StatusOr<Value::Type> Validator::deduceExprType(const Expression* expr) const { return Status::SemanticError("LabelExpression can not be instantiated."); } case Expression::Kind::kConstant: { - QueryExpressionContext ctx(nullptr, nullptr); + QueryExpressionContext ctx; auto* mutableExpr = const_cast<Expression*>(expr); - return mutableExpr->eval(ctx).type(); + return mutableExpr->eval(ctx(nullptr)).type(); } case Expression::Kind::kEdgeSrc: { return Value::Type::STRING;