diff --git a/src/executor/AlterEdgeExecutor.cpp b/src/executor/AlterEdgeExecutor.cpp deleted file mode 100644 index 5c005a787fc46cf3aab63449577d8bd5b30c4adb..0000000000000000000000000000000000000000 --- a/src/executor/AlterEdgeExecutor.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/AlterEdgeExecutor.h" -#include "graph/SchemaHelper.h" - -namespace nebula { -namespace graph { - -AlterEdgeExecutor::AlterEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<AlterEdgeSentence*>(sentence); -} - - -Status AlterEdgeExecutor::prepare() { - return Status::OK(); -} - - -Status AlterEdgeExecutor::getSchema() { - auto status = checkIfGraphSpaceChosen(); - - if (!status.ok()) { - return status; - } - - const auto& schemaOpts = sentence_->getSchemaOpts(); - const auto& schemaProps = sentence_->getSchemaProps(); - - return SchemaHelper::alterSchema(schemaOpts, schemaProps, options_, schemaProp_); -} - - -void AlterEdgeExecutor::execute() { - auto status = getSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - auto future = mc->alterEdgeSchema(spaceId, *name, std::move(options_), std::move(schemaProp_)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(resp.status()); - return; - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/AlterEdgeExecutor.h b/src/executor/AlterEdgeExecutor.h deleted file mode 100644 index bd67f5de7d1da09393f65b90a01ca890ea8fb4c5..0000000000000000000000000000000000000000 --- a/src/executor/AlterEdgeExecutor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_ALTEREDGEEXECUTOR_H_ -#define GRAPH_ALTEREDGEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class AlterEdgeExecutor final : public Executor { -public: - AlterEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "AlterEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status getSchema(); - -private: - AlterEdgeSentence *sentence_{nullptr}; - std::vector<nebula::meta::cpp2::AlterSchemaItem> options_; - nebula::cpp2::SchemaProp schemaProp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_ALTEREDGEEXECUTOR_H_ diff --git a/src/executor/AlterTagExecutor.cpp b/src/executor/AlterTagExecutor.cpp deleted file mode 100644 index bdd659ef29d9b450c3a4cab09bc081f4a26c0bbd..0000000000000000000000000000000000000000 --- a/src/executor/AlterTagExecutor.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/AlterTagExecutor.h" -#include "graph/SchemaHelper.h" - -namespace nebula { -namespace graph { - -AlterTagExecutor::AlterTagExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<AlterTagSentence*>(sentence); -} - - -Status AlterTagExecutor::prepare() { - return Status::OK(); -} - - -Status AlterTagExecutor::getSchema() { - auto status = checkIfGraphSpaceChosen(); - - if (!status.ok()) { - return status; - } - - const auto& schemaOpts = sentence_->getSchemaOpts(); - const auto& schemaProps = sentence_->getSchemaProps(); - - return SchemaHelper::alterSchema(schemaOpts, schemaProps, options_, schemaProp_); -} - - -void AlterTagExecutor::execute() { - auto status = getSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - auto future = mc->alterTagSchema(spaceId, *name, std::move(options_), std::move(schemaProp_)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(resp.status()); - return; - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/AlterTagExecutor.h b/src/executor/AlterTagExecutor.h deleted file mode 100644 index 7826cb756ae2a27ebb04bd0ce2f98a2f76ef8a2d..0000000000000000000000000000000000000000 --- a/src/executor/AlterTagExecutor.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_ALTERTAGEXECUTOR_H_ -#define GRAPH_ALTERTAGEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class AlterTagExecutor final : public Executor { -public: - AlterTagExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "AlterTagExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status getSchema(); - -private: - AlterTagSentence *sentence_{nullptr}; - std::vector<nebula::meta::cpp2::AlterSchemaItem> options_; - nebula::cpp2::SchemaProp schemaProp_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_ALTERTAGEXECUTOR_H_ diff --git a/src/executor/AssignmentExecutor.cpp b/src/executor/AssignmentExecutor.cpp deleted file mode 100644 index 38ca0372d00f9ac975667a8ef6c6189df1768620..0000000000000000000000000000000000000000 --- a/src/executor/AssignmentExecutor.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/AssignmentExecutor.h" -#include "graph/TraverseExecutor.h" - - -namespace nebula { -namespace graph { - - -AssignmentExecutor::AssignmentExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<AssignmentSentence*>(sentence); -} - - -Status AssignmentExecutor::prepare() { - var_ = sentence_->var(); - executor_ = TraverseExecutor::makeTraverseExecutor(sentence_->sentence(), ectx()); - - auto onError = [this] (Status s) { - DCHECK(onError_); - onError_(std::move(s)); - }; - auto onFinish = [this] (Executor::ProcessControl ctr) { - DCHECK(onFinish_); - onFinish_(ctr); - }; - auto onResult = [this] (std::unique_ptr<InterimResult> result) { - ectx()->variableHolder()->add(*var_, std::move(result)); - }; - executor_->setOnError(onError); - executor_->setOnFinish(onFinish); - executor_->setOnResult(onResult); - - auto status = executor_->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - executor_->name(), status.toString().c_str()); - return status; - } - - return Status::OK(); -} - - -void AssignmentExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - executor_->execute(); -} - - -} // namespace graph -} // namespace nebula diff --git a/src/executor/AssignmentExecutor.h b/src/executor/AssignmentExecutor.h deleted file mode 100644 index 171240c9fed90511703e41fd792db4585d3a4c96..0000000000000000000000000000000000000000 --- a/src/executor/AssignmentExecutor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_ASSIGNMENTEXECUTOR_H_ -#define GRAPH_ASSIGNMENTEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class TraverseExecutor; -class AssignmentExecutor final : public Executor { -public: - AssignmentExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "AssignmentExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - AssignmentSentence *sentence_{nullptr}; - std::unique_ptr<TraverseExecutor> executor_; - const std::string *var_{nullptr}; -}; - - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_ASSIGNMENTEXECUTOR_H_ diff --git a/src/executor/BalanceExecutor.cpp b/src/executor/BalanceExecutor.cpp deleted file mode 100644 index 13fd67aecf5e549b67759d693e6c26c2fe9fabc7..0000000000000000000000000000000000000000 --- a/src/executor/BalanceExecutor.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/BalanceExecutor.h" - -namespace nebula { -namespace graph { - -BalanceExecutor::BalanceExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<BalanceSentence*>(sentence); -} - -Status BalanceExecutor::prepare() { - return Status::OK(); -} - -void BalanceExecutor::execute() { - auto showType = sentence_->subType(); - switch (showType) { - case BalanceSentence::SubType::kLeader: - balanceLeader(); - break; - case BalanceSentence::SubType::kData: - balanceData(); - break; - case BalanceSentence::SubType::kDataStop: - balanceData(true); - break; - case BalanceSentence::SubType::kShowBalancePlan: - showBalancePlan(); - break; - case BalanceSentence::SubType::kUnknown: - onError_(Status::Error("Type unknown")); - break; - } -} - -void BalanceExecutor::balanceLeader() { - auto future = ectx()->getMetaClient()->balanceLeader(); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto ret = std::move(resp).value(); - if (!ret) { - DCHECK(onError_); - onError_(Status::Error("Balance leader failed")); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void BalanceExecutor::balanceData(bool isStop) { - std::vector<HostAddr> hostDelList; - auto hostDel = sentence_->hostDel(); - if (hostDel != nullptr) { - hostDelList = hostDel->hosts(); - } - auto future = ectx()->getMetaClient()->balance(std::move(hostDelList), - isStop); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto balanceId = std::move(resp).value(); - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"ID"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - std::vector<cpp2::ColumnValue> row; - row.resize(1); - row[0].set_integer(balanceId); - rows.emplace_back(); - - rows.back().set_columns(std::move(row)); - - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void BalanceExecutor::showBalancePlan() { - auto id = sentence_->balanceId(); - auto future = ectx()->getMetaClient()->showBalance(id); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto tasks = std::move(resp).value(); - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"balanceId, spaceId:partId, src->dst", "status"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - rows.reserve(tasks.size()); - int32_t succeeded = 0; - int32_t failed = 0; - int32_t inProgress = 0; - int32_t invalid = 0; - for (auto& task : tasks) { - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str(std::move(task.get_id())); - switch (task.get_result()) { - case meta::cpp2::TaskResult::SUCCEEDED: - row[1].set_str("succeeded"); - succeeded++; - break; - case meta::cpp2::TaskResult::FAILED: - row[1].set_str("failed"); - failed++; - break; - case meta::cpp2::TaskResult::IN_PROGRESS: - row[1].set_str("in progress"); - inProgress++; - break; - case meta::cpp2::TaskResult::INVALID: - row[1].set_str("invalid"); - invalid++; - break; - } - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - int32_t total = static_cast<int32_t>(rows.size()); - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str( - folly::stringPrintf("Total:%d, Succeeded:%d, Failed:%d, In Progress:%d, Invalid:%d", - total, succeeded, failed, inProgress, invalid)); - row[1].set_str(folly::stringPrintf("%f%%", - total == 0 ? 100 : (100 - static_cast<float>(inProgress) / total * 100))); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void BalanceExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_) { - resp = std::move(*resp_); - } else { - Executor::setupResponse(resp); - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/BalanceExecutor.h b/src/executor/BalanceExecutor.h deleted file mode 100644 index 27c345b986ed04c862fd752fed31a5d72f01e206..0000000000000000000000000000000000000000 --- a/src/executor/BalanceExecutor.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_BALANCEEXECUTOR_H_ -#define GRAPH_BALANCEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class BalanceExecutor final : public Executor { -public: - BalanceExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "BalanceExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void balanceLeader(); - - void balanceData(bool isStop = false); - - void stopBalanceData(); - - void showBalancePlan(); - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - BalanceSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_BALANCEEXECUTOR_H_ diff --git a/src/executor/CMakeLists.txt b/src/executor/CMakeLists.txt deleted file mode 100644 index 238f47942ea5eade9c43b97c370ab02859b108f3..0000000000000000000000000000000000000000 --- a/src/executor/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2020 vesoft inc. All rights reserved. -# -# This source code is licensed under Apache 2.0 License, -# attached with Common Clause Condition 1.0, found in the LICENSES directory. - -nebula_add_library( - graph_obj OBJECT - GraphFlags.cpp - GraphService.cpp - ClientSession.cpp - SessionManager.cpp - ExecutionEngine.cpp - ExecutionContext.cpp - ExecutionPlan.cpp - Executor.cpp - TraverseExecutor.cpp - SequentialExecutor.cpp - UseExecutor.cpp - GoExecutor.cpp - PipeExecutor.cpp - CreateEdgeExecutor.cpp - CreateTagExecutor.cpp - AlterEdgeExecutor.cpp - AlterTagExecutor.cpp - DropTagExecutor.cpp - DropEdgeExecutor.cpp - DescribeTagExecutor.cpp - DescribeEdgeExecutor.cpp - InsertVertexExecutor.cpp - UpdateVertexExecutor.cpp - InsertEdgeExecutor.cpp - UpdateEdgeExecutor.cpp - AssignmentExecutor.cpp - InterimResult.cpp - VariableHolder.cpp - CreateSpaceExecutor.cpp - DropSpaceExecutor.cpp - DescribeSpaceExecutor.cpp - ShowExecutor.cpp - YieldExecutor.cpp - DownloadExecutor.cpp - OrderByExecutor.cpp - IngestExecutor.cpp - ConfigExecutor.cpp - BalanceExecutor.cpp - SchemaHelper.cpp - FetchVerticesExecutor.cpp - FetchEdgesExecutor.cpp - FetchExecutor.cpp - SetExecutor.cpp - FindExecutor.cpp - MatchExecutor.cpp - DeleteVertexExecutor.cpp - DeleteEdgesExecutor.cpp - FindPathExecutor.cpp - LimitExecutor.cpp - GroupByExecutor.cpp - ReturnExecutor.cpp - CreateSnapshotExecutor.cpp - DropSnapshotExecutor.cpp -) - -nebula_add_library( - graph_http_handler OBJECT - GraphHttpHandler.cpp -) - -nebula_add_subdirectory(test) diff --git a/src/executor/ConfigExecutor.cpp b/src/executor/ConfigExecutor.cpp deleted file mode 100644 index ba84e5a076784ff747a2e57c7ee57fbde5195fdd..0000000000000000000000000000000000000000 --- a/src/executor/ConfigExecutor.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/ConfigExecutor.h" -#include "base/Configuration.h" - -namespace nebula { -namespace graph { - -const std::string kConfigUnknown = "UNKNOWN"; // NOLINT - -ConfigExecutor::ConfigExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<ConfigSentence*>(sentence); -} - -Status ConfigExecutor::prepare() { - configItem_ = sentence_->configItem(); - return Status::OK(); -} - -void ConfigExecutor::execute() { - auto showType = sentence_->subType(); - switch (showType) { - case ConfigSentence::SubType::kShow: - showVariables(); - break; - case ConfigSentence::SubType::kSet: - setVariables(); - break; - case ConfigSentence::SubType::kGet: - getVariables(); - break; - case ConfigSentence::SubType::kUnknown: - onError_(Status::Error("Type unknown")); - break; - } -} - -void ConfigExecutor::showVariables() { - meta::cpp2::ConfigModule module = meta::cpp2::ConfigModule::ALL; - if (configItem_ != nullptr) { - if (configItem_->getModule() != nullptr) { - module = toThriftConfigModule(*configItem_->getModule()); - } - } - - if (module == meta::cpp2::ConfigModule::UNKNOWN) { - DCHECK(onError_); - onError_(Status::Error("Parse config module error")); - return; - } - - auto future = ectx()->gflagsManager()->listConfigs(module); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp.status())); - return; - } - - std::vector<std::string> header{"module", "name", "type", "mode", "value"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - - auto configs = std::move(resp.value()); - std::vector<cpp2::RowValue> rows; - for (const auto &item : configs) { - auto row = genRow(item); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void ConfigExecutor::setVariables() { - meta::cpp2::ConfigModule module = meta::cpp2::ConfigModule::UNKNOWN; - std::string name; - VariantType value; - meta::cpp2::ConfigType type; - if (configItem_ != nullptr) { - if (configItem_->getModule() != nullptr) { - module = toThriftConfigModule(*configItem_->getModule()); - } - if (configItem_->getName() != nullptr) { - name = *configItem_->getName(); - } - if (configItem_->getValue() != nullptr) { - auto v = configItem_->getValue()->eval(); - if (!v.ok()) { - DCHECK(onError_); - onError_(v.status()); - return; - } - value = v.value(); - switch (value.which()) { - case VAR_INT64: - type = meta::cpp2::ConfigType::INT64; - break; - case VAR_DOUBLE: - type = meta::cpp2::ConfigType::DOUBLE; - break; - case VAR_BOOL: - type = meta::cpp2::ConfigType::BOOL; - break; - case VAR_STR: - type = meta::cpp2::ConfigType::STRING; - break; - default: - DCHECK(onError_); - onError_(Status::Error("Parse value type error")); - return; - } - } else if (configItem_->getUpdateItems() != nullptr) { - auto status = configItem_->getUpdateItems()->toEvaledString(); - if (!status.ok()) { - DCHECK(onError_); - onError_(status.status()); - return; - } - value = status.value(); - // all nested options are regarded as string - type = meta::cpp2::ConfigType::NESTED; - } - } - - if (module == meta::cpp2::ConfigModule::UNKNOWN) { - DCHECK(onError_); - onError_(Status::Error("Parse config module error")); - return; - } - - bool isForce = sentence_->isForce(); - auto future = ectx()->gflagsManager()->setConfig(module, name, type, value, isForce); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto && resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp.status())); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void ConfigExecutor::getVariables() { - meta::cpp2::ConfigModule module = meta::cpp2::ConfigModule::UNKNOWN; - std::string name; - if (configItem_ != nullptr) { - if (configItem_->getModule() != nullptr) { - module = toThriftConfigModule(*configItem_->getModule()); - } - if (configItem_->getName() != nullptr) { - name = *configItem_->getName(); - } - } - - if (module == meta::cpp2::ConfigModule::UNKNOWN) { - DCHECK(onError_); - onError_(Status::Error("Parse config module error")); - return; - } - - auto future = ectx()->gflagsManager()->getConfig(module, name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto && resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp.status())); - return; - } - - std::vector<std::string> header{"module", "name", "type", "mode", "value"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - - auto configs = std::move(resp.value()); - std::vector<cpp2::RowValue> rows; - for (const auto &item : configs) { - auto row = genRow(item); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -std::vector<cpp2::ColumnValue> ConfigExecutor::genRow(const meta::cpp2::ConfigItem& item) { - std::vector<cpp2::ColumnValue> row; - row.resize(5); - row[0].set_str(ConfigModuleToString(item.get_module())); - row[1].set_str(item.get_name()); - row[2].set_str(ConfigTypeToString(item.get_type())); - row[3].set_str(ConfigModeToString(item.get_mode())); - // TODO: Console must have same type of the same column over different lines, - // so we transform all kinds of value to string for now. - VariantType value; - switch (item.get_type()) { - case meta::cpp2::ConfigType::INT64: - value = *reinterpret_cast<const int64_t*>(item.get_value().data()); - row[4].set_str(std::to_string(boost::get<int64_t>(value))); - break; - case meta::cpp2::ConfigType::DOUBLE: - value = *reinterpret_cast<const double*>(item.get_value().data()); - row[4].set_str(std::to_string(boost::get<double>(value))); - break; - case meta::cpp2::ConfigType::BOOL: - value = *reinterpret_cast<const bool*>(item.get_value().data()); - row[4].set_str(boost::get<bool>(value) ? "True" : "False"); - break; - case meta::cpp2::ConfigType::STRING: - value = item.get_value(); - row[4].set_str(boost::get<std::string>(value)); - break; - case meta::cpp2::ConfigType::NESTED: - value = item.get_value(); - Configuration conf; - auto status = conf.parseFromString(boost::get<std::string>(value)); - if (!status.ok()) { - row[4].set_str(boost::get<std::string>(value)); - } else { - row[4].set_str(conf.dumpToPrettyString()); - } - break; - } - return row; -} - -void ConfigExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -meta::cpp2::ConfigModule toThriftConfigModule(const nebula::ConfigModule& mode) { - switch (mode) { - case nebula::ConfigModule::ALL: - return meta::cpp2::ConfigModule::ALL; - case nebula::ConfigModule::GRAPH: - return meta::cpp2::ConfigModule::GRAPH; - case nebula::ConfigModule::META: - return meta::cpp2::ConfigModule::META; - case nebula::ConfigModule::STORAGE: - return meta::cpp2::ConfigModule::STORAGE; - default: - return meta::cpp2::ConfigModule::UNKNOWN; - } -} - -std::string ConfigModuleToString(const meta::cpp2::ConfigModule& module) { - auto it = meta::cpp2::_ConfigModule_VALUES_TO_NAMES.find(module); - if (it == meta::cpp2::_ConfigModule_VALUES_TO_NAMES.end()) { - return kConfigUnknown; - } else { - return it->second; - } -} - -std::string ConfigModeToString(const meta::cpp2::ConfigMode& mode) { - auto it = meta::cpp2::_ConfigMode_VALUES_TO_NAMES.find(mode); - if (it == meta::cpp2::_ConfigMode_VALUES_TO_NAMES.end()) { - return kConfigUnknown; - } else { - return it->second; - } -} - -std::string ConfigTypeToString(const meta::cpp2::ConfigType& type) { - auto it = meta::cpp2::_ConfigType_VALUES_TO_NAMES.find(type); - if (it == meta::cpp2::_ConfigType_VALUES_TO_NAMES.end()) { - return kConfigUnknown; - } else { - return it->second; - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/ConfigExecutor.h b/src/executor/ConfigExecutor.h deleted file mode 100644 index b4d82ca337e62ad5458ce00758f51da224aedbb8..0000000000000000000000000000000000000000 --- a/src/executor/ConfigExecutor.h +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_CONFIGEXECUTOR_H_ -#define GRAPH_CONFIGEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" -#include "meta/ClientBasedGflagsManager.h" - -namespace nebula { -namespace graph { - -class ConfigExecutor final : public Executor { -public: - ConfigExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "ConfigExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - - void showVariables(); - void setVariables(); - void getVariables(); - -private: - std::vector<cpp2::ColumnValue> genRow(const meta::cpp2::ConfigItem& item); - - ConfigSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - ConfigRowItem *configItem_{nullptr}; -}; - -meta::cpp2::ConfigModule toThriftConfigModule(const nebula::ConfigModule& mode); -std::string ConfigModuleToString(const meta::cpp2::ConfigModule& module); -std::string ConfigModeToString(const meta::cpp2::ConfigMode& mode); -std::string ConfigTypeToString(const meta::cpp2::ConfigType& type); - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_CONFIGEXECUTOR_H_ diff --git a/src/executor/CreateEdgeExecutor.cpp b/src/executor/CreateEdgeExecutor.cpp deleted file mode 100644 index e1141f9d815379bc50ae4a2d2b47c57a5e71fb91..0000000000000000000000000000000000000000 --- a/src/executor/CreateEdgeExecutor.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/CreateEdgeExecutor.h" -#include "dataman/ResultSchemaProvider.h" -#include "graph/SchemaHelper.h" - -namespace nebula { -namespace graph { - -CreateEdgeExecutor::CreateEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<CreateEdgeSentence*>(sentence); -} - - -Status CreateEdgeExecutor::prepare() { - return Status::OK(); -} - - -Status CreateEdgeExecutor::getSchema() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - return status; - } - - const auto& specs = sentence_->columnSpecs(); - const auto& schemaProps = sentence_->getSchemaProps(); - - return SchemaHelper::createSchema(specs, schemaProps, schema_); -} - - -void CreateEdgeExecutor::execute() { - auto status = getSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - auto future = mc->createEdgeSchema(spaceId, *name, schema_, sentence_->isIfNotExist()); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(resp.status()); - return; - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/CreateEdgeExecutor.h b/src/executor/CreateEdgeExecutor.h deleted file mode 100644 index 32d934c2b0ff2ef2fadd648d7876a394888937b7..0000000000000000000000000000000000000000 --- a/src/executor/CreateEdgeExecutor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_CREATEEDGEEXECUTOR_H_ -#define GRAPH_CREATEEDGEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class CreateEdgeExecutor final : public Executor { -public: - CreateEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "CreateEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status getSchema(); - -private: - CreateEdgeSentence *sentence_{nullptr}; - nebula::cpp2::Schema schema_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DEFINEEDGEEXECUTOR_H_ diff --git a/src/executor/CreateSnapshotExecutor.cpp b/src/executor/CreateSnapshotExecutor.cpp deleted file mode 100644 index d4e4c98fb371486febfb76739ce7d09c2e347905..0000000000000000000000000000000000000000 --- a/src/executor/CreateSnapshotExecutor.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/CreateSnapshotExecutor.h" - -namespace nebula { -namespace graph { - -CreateSnapshotExecutor::CreateSnapshotExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<CreateSnapshotSentence*>(sentence); -} - -Status CreateSnapshotExecutor::prepare() { - return Status::OK(); -} - -void CreateSnapshotExecutor::execute() { - auto future = ectx()->getMetaClient()->createSnapshot(); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto ret = std::move(resp).value(); - if (!ret) { - DCHECK(onError_); - onError_(Status::Error("Balance leader failed")); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/CreateSnapshotExecutor.h b/src/executor/CreateSnapshotExecutor.h deleted file mode 100644 index af8f01209a73dbbc0d546db984da9b5c6c732574..0000000000000000000000000000000000000000 --- a/src/executor/CreateSnapshotExecutor.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_CREATESNAPSHOT_H_ -#define GRAPH_CREATESNAPSHOT_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class CreateSnapshotExecutor final : public Executor { -public: - CreateSnapshotExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "CreateSnapshotExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - CreateSnapshotSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_CREATESNAPSHOT_H_ - diff --git a/src/executor/CreateSpaceExecutor.cpp b/src/executor/CreateSpaceExecutor.cpp deleted file mode 100644 index 666f370c1ef6685b8ffc9fb69aebc5111cc20983..0000000000000000000000000000000000000000 --- a/src/executor/CreateSpaceExecutor.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/CreateSpaceExecutor.h" - -namespace nebula { -namespace graph { - -CreateSpaceExecutor::CreateSpaceExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<CreateSpaceSentence*>(sentence); -} - - -Status CreateSpaceExecutor::prepare() { - spaceName_ = sentence_->name(); - for (auto &item : sentence_->getOpts()) { - switch (item->getOptType()) { - case SpaceOptItem::PARTITION_NUM: - partNum_ = item->get_partition_num(); - if (partNum_ <= 0) { - return Status::Error("Partition_num value should be greater than zero"); - } - break; - case SpaceOptItem::REPLICA_FACTOR: - replicaFactor_ = item->get_replica_factor(); - if (replicaFactor_ <= 0) { - return Status::Error("Replica_factor value should be greater than zero"); - } - break; - } - } - return Status::OK(); -} - - -void CreateSpaceExecutor::execute() { - auto future = ectx()->getMetaClient()->createSpace( - *spaceName_, partNum_, replicaFactor_, sentence_->isIfNotExist()); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto spaceId = std::move(resp).value(); - if (spaceId <= 0) { - DCHECK(onError_); - onError_(Status::Error("Create space failed")); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/CreateSpaceExecutor.h b/src/executor/CreateSpaceExecutor.h deleted file mode 100644 index 8847c865562372557a0c2683fc806391cffcd972..0000000000000000000000000000000000000000 --- a/src/executor/CreateSpaceExecutor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_CREATESPACEEXECUTOR_H_ -#define GRAPH_CREATESPACEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class CreateSpaceExecutor final : public Executor { -public: - CreateSpaceExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "CreateSpaceExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - CreateSpaceSentence *sentence_{nullptr}; - const std::string *spaceName_{nullptr}; - // TODO Due to the currently design of the createSpace interface, - // it's impossible to express *not specified*, so we use 0 to indicate this. - int32_t partNum_{0}; - int32_t replicaFactor_{0}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_CREATESPACEEXECUTOR_H_ diff --git a/src/executor/CreateTagExecutor.cpp b/src/executor/CreateTagExecutor.cpp deleted file mode 100644 index 6f4bdf0b347bd7971da7403a074bfc51b744a41b..0000000000000000000000000000000000000000 --- a/src/executor/CreateTagExecutor.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/CreateTagExecutor.h" -#include "dataman/ResultSchemaProvider.h" -#include "graph/SchemaHelper.h" - -namespace nebula { -namespace graph { - -CreateTagExecutor::CreateTagExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<CreateTagSentence*>(sentence); -} - - -Status CreateTagExecutor::prepare() { - return Status::OK(); -} - - -Status CreateTagExecutor::getSchema() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - return status; - } - - const auto& specs = sentence_->columnSpecs(); - const auto& schemaProps = sentence_->getSchemaProps(); - - return SchemaHelper::createSchema(specs, schemaProps, schema_); -} - - -void CreateTagExecutor::execute() { - auto status = getSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - auto future = mc->createTagSchema(spaceId, *name, schema_, sentence_->isIfNotExist()); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(resp.status()); - return; - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/CreateTagExecutor.h b/src/executor/CreateTagExecutor.h deleted file mode 100644 index 84cf86c906f19cb833857386fcaeff6162eab01f..0000000000000000000000000000000000000000 --- a/src/executor/CreateTagExecutor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_CREATETAGEXECUTOR_H_ -#define GRAPH_CREATETAGEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class CreateTagExecutor final : public Executor { -public: - CreateTagExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "CreateTagExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status getSchema(); - -private: - CreateTagSentence *sentence_{nullptr}; - nebula::cpp2::Schema schema_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_DEFINETAGEXECUTOR_H_ diff --git a/src/executor/DeleteEdgesExecutor.cpp b/src/executor/DeleteEdgesExecutor.cpp deleted file mode 100644 index aacc8d9783e7aaf483a4c51193c58e33e06af379..0000000000000000000000000000000000000000 --- a/src/executor/DeleteEdgesExecutor.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/DeleteEdgesExecutor.h" -#include "meta/SchemaManager.h" -#include "filter/Expressions.h" -#include "storage/client/StorageClient.h" - -namespace nebula { -namespace graph { - -DeleteEdgesExecutor::DeleteEdgesExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DeleteEdgesSentence*>(sentence); -} - -Status DeleteEdgesExecutor::prepare() { - Status status; - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - spaceId_ = ectx()->rctx()->session()->space(); - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setSpace(spaceId_); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId_, *sentence_->edge()); - if (!edgeStatus.ok()) { - status = edgeStatus.status(); - break; - } - edgeType_ = edgeStatus.value(); - auto schema = ectx()->schemaManager()->getEdgeSchema(spaceId_, edgeType_); - if (schema == nullptr) { - status = Status::Error("No schema found for '%s'", sentence_->edge()->c_str()); - break; - } - } while (false); - return status; -} - -void DeleteEdgesExecutor::execute() { - auto status = setupEdgeKeys(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - // TODO Need to consider distributed transaction because in-edges/out-edges - // may be in different partitions - auto future = ectx()->getStorageClient()->deleteEdges(spaceId_, std::move(edgeKeys_)); - - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - auto completeness = resp.completeness(); - if (completeness != 100) { - // TODO Need to consider atomic issues - DCHECK(onError_); - onError_(Status::Error("Internal Error")); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -Status DeleteEdgesExecutor::setupEdgeKeys() { - auto status = Status::OK(); - auto edgeKeysExpr = sentence_->keys()->keys(); - for (auto *keyExpr : edgeKeysExpr) { - auto *srcExpr = keyExpr->srcid(); - srcExpr->setContext(expCtx_.get()); - - auto *dstExpr = keyExpr->dstid(); - dstExpr->setContext(expCtx_.get()); - - auto rank = keyExpr->rank(); - status = srcExpr->prepare(); - if (!status.ok()) { - break; - } - status = dstExpr->prepare(); - if (!status.ok()) { - break; - } - auto value = srcExpr->eval(); - if (!value.ok()) { - return value.status(); - } - auto srcid = value.value(); - value = dstExpr->eval(); - if (!value.ok()) { - return value.status(); - } - auto dstid = value.value(); - if (!Expression::isInt(srcid) || !Expression::isInt(dstid)) { - status = Status::Error("ID should be of type integer."); - break; - } - storage::cpp2::EdgeKey outkey; - outkey.set_src(Expression::asInt(srcid)); - outkey.set_edge_type(edgeType_); - outkey.set_dst(Expression::asInt(dstid)); - outkey.set_ranking(rank); - - storage::cpp2::EdgeKey inkey; - inkey.set_src(Expression::asInt(dstid)); - inkey.set_edge_type(-edgeType_); - inkey.set_dst(Expression::asInt(srcid)); - inkey.set_ranking(rank); - - edgeKeys_.emplace_back(std::move(outkey)); - edgeKeys_.emplace_back(std::move(inkey)); - } - return status; -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DeleteEdgesExecutor.h b/src/executor/DeleteEdgesExecutor.h deleted file mode 100644 index eef6e4c636c46110d3deea23701b5709c083d718..0000000000000000000000000000000000000000 --- a/src/executor/DeleteEdgesExecutor.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DELETEEDGESEXECUTOR_H_ -#define GRAPH_DELETEEDGESEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DeleteEdgesExecutor final : public Executor { -public: - DeleteEdgesExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DeleteEdgesExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status setupEdgeKeys(); - -private: - DeleteEdgesSentence *sentence_{nullptr}; - std::vector<storage::cpp2::EdgeKey> edgeKeys_; - GraphSpaceID spaceId_{-1}; - EdgeType edgeType_{0}; - std::unique_ptr<ExpressionContext> expCtx_; -}; - -} // namespace graph -} // namespace nebula - - #endif // GRAPH_DELETEEDGESEXECUTOR_H_ diff --git a/src/executor/DeleteVertexExecutor.cpp b/src/executor/DeleteVertexExecutor.cpp deleted file mode 100644 index 98893d1ad43a1dca6bfe0eb9c2e7b67c5012c7df..0000000000000000000000000000000000000000 --- a/src/executor/DeleteVertexExecutor.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/DeleteVertexExecutor.h" -#include "storage/client/StorageClient.h" - -namespace nebula { -namespace graph { - -DeleteVertexExecutor::DeleteVertexExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DeleteVertexSentence*>(sentence); -} - -Status DeleteVertexExecutor::prepare() { - spaceId_ = ectx()->rctx()->session()->space(); - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setSpace(spaceId_); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - auto vid = sentence_->vid(); - vid->setContext(expCtx_.get()); - auto ovalue = vid->eval(); - auto v = ovalue.value(); - if (!Expression::isInt(v)) { - return Status::Error("Vertex ID should be of type integer"); - } - vid_ = Expression::asInt(v); - return Status::OK(); -} - -void DeleteVertexExecutor::execute() { - // TODO(zlcook) Get edgeKeys of a vertex by Go - auto future = ectx()->getStorageClient()->getEdgeKeys(spaceId_, vid_); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - } - auto rpcResp = std::move(resp).value(); - std::vector<storage::cpp2::EdgeKey> allEdges; - for (auto& edge : *rpcResp.get_edge_keys()) { - storage::cpp2::EdgeKey reverseEdge; - reverseEdge.set_src(edge.get_dst()); - reverseEdge.set_edge_type(-(edge.get_edge_type())); - reverseEdge.set_ranking(edge.get_ranking()); - reverseEdge.set_dst(edge.get_src()); - allEdges.emplace_back(std::move(edge)); - allEdges.emplace_back(std::move(reverseEdge)); - } - if (allEdges.size() > 0) { - deleteEdges(&allEdges); - } else { - deleteVertex(); - } - return; - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void DeleteVertexExecutor::deleteEdges(std::vector<storage::cpp2::EdgeKey>* edges) { - auto future = ectx()->getStorageClient()->deleteEdges(spaceId_, *edges); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - auto completeness = resp.completeness(); - if (completeness != 100) { - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - } - deleteVertex(); - return; - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void DeleteVertexExecutor::deleteVertex() { - auto future = ectx()->getStorageClient()->deleteVertex(spaceId_, vid_); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - } - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getDeleteVertexStats()); - return; - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getDeleteVertexStats()); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/DeleteVertexExecutor.h b/src/executor/DeleteVertexExecutor.h deleted file mode 100644 index d6dd85492863d4cbf7cd74c8f234d3fc20d8169b..0000000000000000000000000000000000000000 --- a/src/executor/DeleteVertexExecutor.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DELETEVERTEXEXECUTOR_H_ -#define GRAPH_DELETEVERTEXEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DeleteVertexExecutor final : public Executor { -public: - DeleteVertexExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DeleteVertexExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - void deleteEdges(std::vector<storage::cpp2::EdgeKey>* edges); - void deleteVertex(); - -private: - DeleteVertexSentence *sentence_{nullptr}; - std::unique_ptr<ExpressionContext> expCtx_; - VertexID vid_; - GraphSpaceID spaceId_{-1}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DELETEVERTEXEXECUTOR_H_ diff --git a/src/executor/DescribeEdgeExecutor.cpp b/src/executor/DescribeEdgeExecutor.cpp deleted file mode 100644 index 0dc2d48f606a17b533c3affb73fd98148e5fdb90..0000000000000000000000000000000000000000 --- a/src/executor/DescribeEdgeExecutor.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/DescribeEdgeExecutor.h" - -namespace nebula { -namespace graph { - -DescribeEdgeExecutor::DescribeEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DescribeEdgeSentence*>(sentence); -} - - -Status DescribeEdgeExecutor::prepare() { - return Status::OK(); -} - - -void DescribeEdgeExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - // Get the lastest ver - auto future = ectx()->getMetaClient()->getEdgeSchema(spaceId, *name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(Status::Error("Schema not found for edge '%s'", sentence_->name()->c_str())); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"Field", "Type"}; - resp_->set_column_names(std::move(header)); - std::vector<cpp2::RowValue> rows; - for (auto& item : resp.value().columns) { - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str(item.name); - row[1].set_str(valueTypeToString(item.type)); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void DescribeEdgeExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DescribeEdgeExecutor.h b/src/executor/DescribeEdgeExecutor.h deleted file mode 100644 index b56b32ef431121175bdf0c369397ff6b161b5e4b..0000000000000000000000000000000000000000 --- a/src/executor/DescribeEdgeExecutor.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DESCRIBEEDGEEXECUTOR_H_ -#define GRAPH_DESCRIBEEDGEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DescribeEdgeExecutor final : public Executor { -public: - DescribeEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DescribeEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - DescribeEdgeSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DESCRIBEEDGEEXECUTOR_H_ diff --git a/src/executor/DescribeSpaceExecutor.cpp b/src/executor/DescribeSpaceExecutor.cpp deleted file mode 100644 index c676baf5a9c91eb1dbfc2b6eb92cefabfbf0422c..0000000000000000000000000000000000000000 --- a/src/executor/DescribeSpaceExecutor.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/DescribeSpaceExecutor.h" - -namespace nebula { -namespace graph { - -DescribeSpaceExecutor::DescribeSpaceExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DescribeSpaceSentence*>(sentence); -} - -Status DescribeSpaceExecutor::prepare() { - return Status::OK(); -} - -void DescribeSpaceExecutor::execute() { - auto *name = sentence_->name(); - auto future = ectx()->getMetaClient()->getSpace(*name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - onError_(Status::Error("Space not found")); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"ID", "Name", "Partition number", "Replica Factor"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - std::vector<cpp2::ColumnValue> row; - row.resize(4); - row[0].set_integer(resp.value().get_space_id()); - - auto properties = resp.value().get_properties(); - row[1].set_str(properties.get_space_name()); - row[2].set_integer(properties.get_partition_num()); - row[3].set_integer(properties.get_replica_factor()); - - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void DescribeSpaceExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DescribeSpaceExecutor.h b/src/executor/DescribeSpaceExecutor.h deleted file mode 100644 index 31e8a37b14f6455b52a08c0cc4bfef9bc037b2f3..0000000000000000000000000000000000000000 --- a/src/executor/DescribeSpaceExecutor.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DESCRIBESPACEEXECUTOR_H_ -#define GRAPH_DESCRIBESPACEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DescribeSpaceExecutor final : public Executor { -public: - DescribeSpaceExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DescribeSpaceExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - DescribeSpaceSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DESCRIBESPACEEXECUTOR_H_ diff --git a/src/executor/DescribeTagExecutor.cpp b/src/executor/DescribeTagExecutor.cpp deleted file mode 100644 index 6d2f75713effaf5855c70f0adb29bef55f37e958..0000000000000000000000000000000000000000 --- a/src/executor/DescribeTagExecutor.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/DescribeTagExecutor.h" - -namespace nebula { -namespace graph { - -DescribeTagExecutor::DescribeTagExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DescribeTagSentence*>(sentence); -} - - -Status DescribeTagExecutor::prepare() { - return Status::OK(); -} - - -void DescribeTagExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - - // Get the lastest ver - auto future = ectx()->getMetaClient()->getTagSchema(spaceId, *name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(Status::Error("Schema not found for tag '%s'", sentence_->name()->c_str())); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"Field", "Type"}; - resp_->set_column_names(std::move(header)); - std::vector<cpp2::RowValue> rows; - for (auto& item : resp.value().columns) { - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str(item.name); - row[1].set_str(valueTypeToString(item.type)); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void DescribeTagExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DescribeTagExecutor.h b/src/executor/DescribeTagExecutor.h deleted file mode 100644 index 473333aa08f14bde3a31bace42bae81bbea1e71c..0000000000000000000000000000000000000000 --- a/src/executor/DescribeTagExecutor.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DESCRIBETAGEXECUTOR_H_ -#define GRAPH_DESCRIBETAGEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DescribeTagExecutor final : public Executor { -public: - DescribeTagExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DescribeTagExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - DescribeTagSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DESCRIBETAGEXECUTOR_H_ diff --git a/src/executor/DownloadExecutor.cpp b/src/executor/DownloadExecutor.cpp deleted file mode 100644 index 7ea5eb03deb485b7224658d8e4984af8a5bb5a24..0000000000000000000000000000000000000000 --- a/src/executor/DownloadExecutor.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/StatusOr.h" -#include "http/HttpClient.h" -#include "graph/DownloadExecutor.h" -#include "process/ProcessUtils.h" -#include "webservice/Common.h" - -#include <folly/executors/Async.h> -#include <folly/futures/Future.h> -#include <folly/executors/ThreadedExecutor.h> - -namespace nebula { -namespace graph { - -DownloadExecutor::DownloadExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DownloadSentence*>(sentence); -} - -Status DownloadExecutor::prepare() { - return Status::OK(); -} - -void DownloadExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - auto *mc = ectx()->getMetaClient(); - auto addresses = mc->getAddresses(); - auto metaHost = network::NetworkUtils::intToIPv4(addresses[0].first); - auto spaceId = ectx()->rctx()->session()->space(); - auto *hdfsHost = sentence_->host(); - auto hdfsPort = sentence_->port(); - auto *hdfsPath = sentence_->path(); - if (hdfsHost == nullptr || hdfsPort == 0 || hdfsPath == nullptr) { - LOG(ERROR) << "URL Parse Failed"; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - onError_(Status::Error("URL Parse Failed")); - return; - } - - auto func = [metaHost, hdfsHost, hdfsPort, hdfsPath, spaceId]() { - static const char *tmp = "http://%s:%d/%s?host=%s&port=%d&path=%s&space=%d"; - auto url = folly::stringPrintf(tmp, metaHost.c_str(), FLAGS_ws_meta_http_port, - "download-dispatch", hdfsHost->c_str(), - hdfsPort, hdfsPath->c_str(), spaceId); - auto result = http::HttpClient::get(url); - if (result.ok() && result.value() == "SSTFile dispatch successfully") { - LOG(INFO) << "Download Successfully"; - return true; - } else { - LOG(ERROR) << "Download Failed "; - return false; - } - }; - auto future = folly::async(func); - - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp) { - DCHECK(onError_); - onError_(Status::Error("Download Failed")); - return; - } - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void DownloadExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/DownloadExecutor.h b/src/executor/DownloadExecutor.h deleted file mode 100644 index f90428744ea880be71ad93205eea126213437591..0000000000000000000000000000000000000000 --- a/src/executor/DownloadExecutor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DOWNLOADEXECUTOR_H -#define GRAPH_DOWNLOADEXECUTOR_H - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DownloadExecutor final : public Executor { -public: - DownloadExecutor(Sentence *sentence, ExecutionContext *context); - - const char* name() const override { - return "DownloadExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - DownloadSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DOWNLOADEXECUTOR_H - diff --git a/src/executor/DropEdgeExecutor.cpp b/src/executor/DropEdgeExecutor.cpp deleted file mode 100644 index e8aab635b80bf3672e61d9891f24cdc373e1f92e..0000000000000000000000000000000000000000 --- a/src/executor/DropEdgeExecutor.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/DropEdgeExecutor.h" - -namespace nebula { -namespace graph { - -DropEdgeExecutor::DropEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DropEdgeSentence*>(sentence); -} - -Status DropEdgeExecutor::prepare() { - return Status::OK(); -} - -void DropEdgeExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - auto future = mc->dropEdgeSchema(spaceId, *name); - - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/DropEdgeExecutor.h b/src/executor/DropEdgeExecutor.h deleted file mode 100644 index 973feef1adaed3714b4e877cf9f3ed975dd2b26e..0000000000000000000000000000000000000000 --- a/src/executor/DropEdgeExecutor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DROPEDGEEXECUTOR_H -#define GRAPH_DROPEDGEEXECUTOR_H - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DropEdgeExecutor final : public Executor { -public: - DropEdgeExecutor(Sentence *sentence, ExecutionContext *context); - - const char* name() const override { - return "DropEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - DropEdgeSentence *sentence_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DROPEDGEEXECUTOR_H diff --git a/src/executor/DropSnapshotExecutor.cpp b/src/executor/DropSnapshotExecutor.cpp deleted file mode 100644 index 6bceb285bb0164aec27a7232e7dd3f739595c0cb..0000000000000000000000000000000000000000 --- a/src/executor/DropSnapshotExecutor.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/DropSnapshotExecutor.h" - -namespace nebula { -namespace graph { - -DropSnapshotExecutor::DropSnapshotExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DropSnapshotSentence*>(sentence); -} - -Status DropSnapshotExecutor::prepare() { - return Status::OK(); -} - -void DropSnapshotExecutor::execute() { - auto *name = sentence_->getName(); - auto future = ectx()->getMetaClient()->dropSnapshot(*name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::forward<decltype(resp)>(resp).status()); - return; - } - auto ret = std::forward<decltype(resp)>(resp).value(); - if (!ret) { - DCHECK(onError_); - onError_(Status::Error("Balance leader failed")); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DropSnapshotExecutor.h b/src/executor/DropSnapshotExecutor.h deleted file mode 100644 index 1cb31efe6ef72e6a89fe2c85cf679cbc63aa7d56..0000000000000000000000000000000000000000 --- a/src/executor/DropSnapshotExecutor.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DROPSNAPSHOT_H_ -#define GRAPH_DROPSNAPSHOT_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DropSnapshotExecutor final : public Executor { -public: - DropSnapshotExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DropSnapshotExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - DropSnapshotSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DROPSNAPSHOT_H_ - diff --git a/src/executor/DropSpaceExecutor.cpp b/src/executor/DropSpaceExecutor.cpp deleted file mode 100644 index 4584766779e2b340aac11fe662cf71e1f8917229..0000000000000000000000000000000000000000 --- a/src/executor/DropSpaceExecutor.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/DropSpaceExecutor.h" - -namespace nebula { -namespace graph { - -DropSpaceExecutor::DropSpaceExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DropSpaceSentence*>(sentence); -} - - -Status DropSpaceExecutor::prepare() { - spaceName_ = sentence_->name(); - return Status::OK(); -} - - -void DropSpaceExecutor::execute() { - auto future = ectx()->getMetaClient()->dropSpace(*spaceName_); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - auto ret = std::move(resp).value(); - if (!ret) { - DCHECK(onError_); - onError_(Status::Error("Drop space failed")); - return; - } - - if (*spaceName_ == ectx()->rctx()->session()->spaceName()) { - ectx()->rctx()->session()->setSpace("", -1); - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/DropSpaceExecutor.h b/src/executor/DropSpaceExecutor.h deleted file mode 100644 index ed7f25a66884078b845bed06e1fd157ba7d06c46..0000000000000000000000000000000000000000 --- a/src/executor/DropSpaceExecutor.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DROPSPACEEXECUTOR_H_ -#define GRAPH_DROPSPACEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DropSpaceExecutor final : public Executor { -public: - DropSpaceExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "DropSpaceExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - DropSpaceSentence *sentence_{nullptr}; - const std::string *spaceName_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DROPSPACEEXECUTOR_H_ diff --git a/src/executor/DropTagExecutor.cpp b/src/executor/DropTagExecutor.cpp deleted file mode 100644 index a956cc55d59676bceb0d02e8cd2a45cf4b5b5861..0000000000000000000000000000000000000000 --- a/src/executor/DropTagExecutor.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/DropTagExecutor.h" - -namespace nebula { -namespace graph { - -DropTagExecutor::DropTagExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<DropTagSentence*>(sentence); -} - -Status DropTagExecutor::prepare() { - return Status::OK(); -} - -void DropTagExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *mc = ectx()->getMetaClient(); - auto *name = sentence_->name(); - auto spaceId = ectx()->rctx()->session()->space(); - auto future = mc->dropTagSchema(spaceId, *name); - - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/DropTagExecutor.h b/src/executor/DropTagExecutor.h deleted file mode 100644 index 0962bb8599093fdbe3b33fbe08fc948b29a14b37..0000000000000000000000000000000000000000 --- a/src/executor/DropTagExecutor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_DROPTAGEXECUTOR_H -#define GRAPH_DROPTAGEXECUTOR_H - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class DropTagExecutor final : public Executor { -public: - DropTagExecutor(Sentence *sentence, ExecutionContext *context); - - const char* name() const override { - return "DropTagExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - DropTagSentence *sentence_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_DROPTAGEXECUTOR_H diff --git a/src/executor/Executor.cpp b/src/executor/Executor.cpp deleted file mode 100644 index 51727da97635684a0450ba51357ba51d56052d90..0000000000000000000000000000000000000000 --- a/src/executor/Executor.cpp +++ /dev/null @@ -1,405 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/Executor.h" -#include "parser/TraverseSentences.h" -#include "parser/MutateSentences.h" -#include "parser/MaintainSentences.h" -#include "parser/AdminSentences.h" -#include "graph/GoExecutor.h" -#include "graph/UseExecutor.h" -#include "graph/PipeExecutor.h" -#include "graph/CreateTagExecutor.h" -#include "graph/CreateEdgeExecutor.h" -#include "graph/AlterTagExecutor.h" -#include "graph/AlterEdgeExecutor.h" -#include "graph/DropTagExecutor.h" -#include "graph/DropEdgeExecutor.h" -#include "graph/DescribeTagExecutor.h" -#include "graph/DescribeEdgeExecutor.h" -#include "graph/InsertVertexExecutor.h" -#include "graph/InsertEdgeExecutor.h" -#include "graph/AssignmentExecutor.h" -#include "graph/ShowExecutor.h" -#include "graph/CreateSpaceExecutor.h" -#include "graph/DescribeSpaceExecutor.h" -#include "graph/DropSpaceExecutor.h" -#include "graph/YieldExecutor.h" -#include "graph/DownloadExecutor.h" -#include "graph/OrderByExecutor.h" -#include "graph/IngestExecutor.h" -#include "graph/ConfigExecutor.h" -#include "graph/FetchVerticesExecutor.h" -#include "graph/FetchEdgesExecutor.h" -#include "graph/ConfigExecutor.h" -#include "graph/SetExecutor.h" -#include "graph/FindExecutor.h" -#include "graph/MatchExecutor.h" -#include "graph/BalanceExecutor.h" -#include "graph/DeleteVertexExecutor.h" -#include "graph/DeleteEdgesExecutor.h" -#include "graph/UpdateVertexExecutor.h" -#include "graph/UpdateEdgeExecutor.h" -#include "graph/FindPathExecutor.h" -#include "graph/LimitExecutor.h" -#include "graph/GroupByExecutor.h" -#include "graph/ReturnExecutor.h" -#include "graph/CreateSnapshotExecutor.h" -#include "graph/DropSnapshotExecutor.h" - -namespace nebula { -namespace graph { - -std::unique_ptr<Executor> Executor::makeExecutor(Sentence *sentence) { - auto kind = sentence->kind(); - std::unique_ptr<Executor> executor; - switch (kind) { - case Sentence::Kind::kGo: - executor = std::make_unique<GoExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kUse: - executor = std::make_unique<UseExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kPipe: - executor = std::make_unique<PipeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kCreateTag: - executor = std::make_unique<CreateTagExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kCreateEdge: - executor = std::make_unique<CreateEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kAlterTag: - executor = std::make_unique<AlterTagExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kAlterEdge: - executor = std::make_unique<AlterEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDescribeTag: - executor = std::make_unique<DescribeTagExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDescribeEdge: - executor = std::make_unique<DescribeEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDropTag: - executor = std::make_unique<DropTagExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDropEdge: - executor = std::make_unique<DropEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kInsertVertex: - executor = std::make_unique<InsertVertexExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kInsertEdge: - executor = std::make_unique<InsertEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kShow: - executor = std::make_unique<ShowExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kAssignment: - executor = std::make_unique<AssignmentExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kCreateSpace: - executor = std::make_unique<CreateSpaceExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDropSpace: - executor = std::make_unique<DropSpaceExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDescribeSpace: - executor = std::make_unique<DescribeSpaceExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kYield: - executor = std::make_unique<YieldExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDownload: - executor = std::make_unique<DownloadExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kOrderBy: - executor = std::make_unique<OrderByExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kIngest: - executor = std::make_unique<IngestExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kConfig: - executor = std::make_unique<ConfigExecutor>(sentence, ectx()); - break; - case Sentence::Kind::KGroupBy: - executor = std::make_unique<GroupByExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kFetchVertices: - executor = std::make_unique<FetchVerticesExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kFetchEdges: - executor = std::make_unique<FetchEdgesExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kSet: - executor = std::make_unique<SetExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kMatch: - executor = std::make_unique<MatchExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kFind: - executor = std::make_unique<FindExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kBalance: - executor = std::make_unique<BalanceExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDeleteVertices: - executor = std::make_unique<DeleteVertexExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDeleteEdges: - executor = std::make_unique<DeleteEdgesExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kUpdateVertex: - executor = std::make_unique<UpdateVertexExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kUpdateEdge: - executor = std::make_unique<UpdateEdgeExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kFindPath: - executor = std::make_unique<FindPathExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kLimit: - executor = std::make_unique<LimitExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kReturn: - executor = std::make_unique<ReturnExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kCreateSnapshot: - executor = std::make_unique<CreateSnapshotExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kDropSnapshot: - executor = std::make_unique<DropSnapshotExecutor>(sentence, ectx()); - break; - case Sentence::Kind::kUnknown: - LOG(ERROR) << "Sentence kind unknown"; - return nullptr; - default: - LOG(ERROR) << "Sentence kind illegal: " << kind; - return nullptr; - } - return executor; -} - -std::string Executor::valueTypeToString(nebula::cpp2::ValueType type) { - switch (type.type) { - case nebula::cpp2::SupportedType::BOOL: - return "bool"; - case nebula::cpp2::SupportedType::INT: - return "int"; - case nebula::cpp2::SupportedType::DOUBLE: - return "double"; - case nebula::cpp2::SupportedType::STRING: - return "string"; - case nebula::cpp2::SupportedType::TIMESTAMP: - return "timestamp"; - default: - return "unknown"; - } -} - -void Executor::writeVariantType(RowWriter &writer, const VariantType &value) { - switch (value.which()) { - case VAR_INT64: - writer << boost::get<int64_t>(value); - break; - case VAR_DOUBLE: - writer << boost::get<double>(value); - break; - case VAR_BOOL: - writer << boost::get<bool>(value); - break; - case VAR_STR: - writer << boost::get<std::string>(value); - break; - default: - LOG(FATAL) << "Unknown value type: " << static_cast<uint32_t>(value.which()); - } -} - -bool Executor::checkValueType(const nebula::cpp2::ValueType &type, const VariantType &value) { - switch (value.which()) { - case VAR_INT64: - return nebula::cpp2::SupportedType::INT == type.type || - nebula::cpp2::SupportedType::TIMESTAMP == type.type; - case VAR_DOUBLE: - return nebula::cpp2::SupportedType::DOUBLE == type.type; - case VAR_BOOL: - return nebula::cpp2::SupportedType::BOOL == type.type; - case VAR_STR: - return nebula::cpp2::SupportedType::STRING == type.type || - nebula::cpp2::SupportedType::TIMESTAMP == type.type; - // TODO: Other type - } - - return false; -} - -StatusOr<int64_t> Executor::toTimestamp(const VariantType &value) { - if (value.which() != VAR_INT64 && value.which() != VAR_STR) { - return Status::Error("Invalid value type"); - } - - int64_t timestamp; - if (value.which() == VAR_STR) { - static const std::regex reg("^([1-9]\\d{3})-" - "(0[1-9]|1[0-2]|\\d)-" - "(0[1-9]|[1-2][0-9]|3[0-1]|\\d)\\s+" - "(20|21|22|23|[0-1]\\d|\\d):" - "([0-5]\\d|\\d):" - "([0-5]\\d|\\d)$"); - std::smatch result; - if (!std::regex_match(boost::get<std::string>(value), result, reg)) { - return Status::Error("Invalid timestamp type"); - } - struct tm time; - memset(&time, 0, sizeof(time)); - time.tm_year = atoi(result[1].str().c_str()) - 1900; - time.tm_mon = atoi(result[2].str().c_str()) - 1; - time.tm_mday = atoi(result[3].str().c_str()); - time.tm_hour = atoi(result[4].str().c_str()); - time.tm_min = atoi(result[5].str().c_str()); - time.tm_sec = atoi(result[6].str().c_str()); - timestamp = mktime(&time); - } else { - timestamp = boost::get<int64_t>(value); - } - - // The mainstream Linux kernel's implementation constrains this - static const int64_t maxTimestamp = std::numeric_limits<int64_t>::max() / 1000000000; - if (timestamp < 0 || (timestamp > maxTimestamp)) { - return Status::Error("Invalid timestamp type"); - } - return timestamp; -} - -StatusOr<cpp2::ColumnValue> Executor::toColumnValue(const VariantType& value, - cpp2::ColumnValue::Type type) const { - cpp2::ColumnValue colVal; - try { - if (type == cpp2::ColumnValue::Type::__EMPTY__) { - switch (value.which()) { - case VAR_INT64: - colVal.set_integer(boost::get<int64_t>(value)); - break; - case VAR_DOUBLE: - colVal.set_double_precision(boost::get<double>(value)); - break; - case VAR_BOOL: - colVal.set_bool_val(boost::get<bool>(value)); - break; - case VAR_STR: - colVal.set_str(boost::get<std::string>(value)); - break; - default: - LOG(ERROR) << "Wrong Type: " << value.which(); - return Status::Error("Wrong Type: %d", value.which()); - } - return colVal; - } - switch (type) { - case cpp2::ColumnValue::Type::id: - colVal.set_id(boost::get<int64_t>(value)); - break; - case cpp2::ColumnValue::Type::integer: - colVal.set_integer(boost::get<int64_t>(value)); - break; - case cpp2::ColumnValue::Type::timestamp: - colVal.set_timestamp(boost::get<int64_t>(value)); - break; - case cpp2::ColumnValue::Type::double_precision: - colVal.set_double_precision(boost::get<double>(value)); - break; - case cpp2::ColumnValue::Type::bool_val: - colVal.set_bool_val(boost::get<bool>(value)); - break; - case cpp2::ColumnValue::Type::str: - colVal.set_str(boost::get<std::string>(value)); - break; - default: - LOG(ERROR) << "Wrong Type: " << static_cast<int32_t>(type); - return Status::Error("Wrong Type: %d", static_cast<int32_t>(type)); - } - } catch (const std::exception& e) { - LOG(ERROR) << "Exception caught: " << e.what(); - return Status::Error("Wrong Type: %d", static_cast<int32_t>(type)); - } - return colVal; -} - -OptVariantType Executor::toVariantType(const cpp2::ColumnValue& value) const { - switch (value.getType()) { - case cpp2::ColumnValue::Type::id: - return value.get_id(); - case cpp2::ColumnValue::Type::integer: - return value.get_integer(); - case cpp2::ColumnValue::Type::bool_val: - return value.get_bool_val(); - case cpp2::ColumnValue::Type::double_precision: - return value.get_double_precision(); - case cpp2::ColumnValue::Type::str: - return value.get_str(); - case cpp2::ColumnValue::Type::timestamp: - return value.get_timestamp(); - default: - break; - } - - LOG(ERROR) << "Unknown ColumnType: " << static_cast<int32_t>(value.getType()); - return Status::Error("Unknown ColumnType: %d", static_cast<int32_t>(value.getType())); -} - -StatusOr<VariantType> Executor::transformDefaultValue(nebula::cpp2::SupportedType type, - std::string& originalValue) { - switch (type) { - case nebula::cpp2::SupportedType::BOOL: - try { - return folly::to<bool>(originalValue); - } catch (const std::exception& ex) { - LOG(ERROR) << "Conversion to bool failed: " << originalValue; - return Status::Error("Type Conversion Failed"); - } - break; - case nebula::cpp2::SupportedType::INT: - try { - return folly::to<int64_t>(originalValue); - } catch (const std::exception& ex) { - LOG(ERROR) << "Conversion to int64_t failed: " << originalValue; - return Status::Error("Type Conversion Failed"); - } - break; - case nebula::cpp2::SupportedType::DOUBLE: - try { - return folly::to<double>(originalValue); - } catch (const std::exception& ex) { - LOG(ERROR) << "Conversion to double failed: " << originalValue; - return Status::Error("Type Conversion Failed"); - } - break; - case nebula::cpp2::SupportedType::STRING: - return originalValue; - break; - default: - LOG(ERROR) << "Unknow type"; - return Status::Error("Unknow type"); - } - return Status::OK(); -} - -void Executor::doError(Status status, const stats::Stats* stats, uint32_t count) const { - stats::Stats::addStatsValue(stats, false, duration().elapsedInUSec(), count); - DCHECK(onError_); - onError_(std::move(status)); -} - -void Executor::doFinish(ProcessControl pro, const stats::Stats* stats, uint32_t count) const { - stats::Stats::addStatsValue(stats, true, duration().elapsedInUSec(), count); - DCHECK(onFinish_); - onFinish_(pro); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/Executor.h b/src/executor/Executor.h deleted file mode 100644 index 11b7389ebd06b4b9e67d6063164a1d379f6e54fa..0000000000000000000000000000000000000000 --- a/src/executor/Executor.h +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_EXECUTOR_H_ -#define GRAPH_EXECUTOR_H_ - -#include "base/Base.h" -#include "base/Status.h" -#include "cpp/helpers.h" -#include "graph/ExecutionContext.h" -#include "gen-cpp2/common_types.h" -#include "gen-cpp2/storage_types.h" -#include "dataman/RowWriter.h" -#include "meta/SchemaManager.h" -#include "time/Duration.h" -#include "stats/Stats.h" - - -/** - * Executor is the interface of kinds of specific executors that do the actual execution. - */ - -namespace nebula { -namespace graph { - -class Executor : public cpp::NonCopyable, public cpp::NonMovable { -public: - explicit Executor(ExecutionContext *ectx) { - ectx_ = ectx; - } - - virtual ~Executor() {} - - /** - * Do some preparatory works, such as sanitize checking, dependency setup, etc. - * - * `prepare' succeeds only if all its sub-executors are prepared. - * `prepare' works in a synchronous way, once the executor is prepared, it will - * be executed. - */ - virtual Status MUST_USE_RESULT prepare() = 0; - - virtual void execute() = 0; - - virtual const char* name() const = 0; - - enum ProcessControl : uint8_t { - kNext = 0, - kReturn, - }; - - /** - * Set callback to be invoked when this executor is finished(normally). - */ - void setOnFinish(std::function<void(ProcessControl)> onFinish) { - onFinish_ = onFinish; - } - /** - * When some error happens during an executor's execution, it should invoke its - * `onError_' with a Status that indicates the reason. - * - * An executor terminates its execution via invoking either `onFinish_' or `onError_', - * but should never call them both. - */ - void setOnError(std::function<void(Status)> onError) { - onError_ = onError; - } - /** - * Upon finished successfully, `setupResponse' would be invoked on the last executor. - * Any Executor implementation, which wants to send its meaningful result to the client, - * should override this method. - */ - virtual void setupResponse(cpp2::ExecutionResponse &resp) { - resp.set_error_code(cpp2::ErrorCode::SUCCEEDED); - } - - ExecutionContext* ectx() const { - return ectx_; - } - - const time::Duration& duration() const { - return duration_; - } - -protected: - std::unique_ptr<Executor> makeExecutor(Sentence *sentence); - - std::string valueTypeToString(nebula::cpp2::ValueType type); - - void writeVariantType(RowWriter &writer, const VariantType &value); - - bool checkValueType(const nebula::cpp2::ValueType &type, const VariantType &value); - - StatusOr<int64_t> toTimestamp(const VariantType &value); - - StatusOr<cpp2::ColumnValue> toColumnValue(const VariantType& value, - cpp2::ColumnValue::Type type) const; - - OptVariantType toVariantType(const cpp2::ColumnValue& value) const; - - Status checkIfGraphSpaceChosen() const { - if (ectx()->rctx()->session()->space() == -1) { - return Status::Error("Please choose a graph space with `USE spaceName' firstly"); - } - return Status::OK(); - } - - StatusOr<VariantType> transformDefaultValue(nebula::cpp2::SupportedType type, - std::string& originalValue); - void doError(Status status, const stats::Stats* stats = nullptr, uint32_t count = 1) const; - void doFinish(ProcessControl pro, - const stats::Stats* stats = nullptr, - uint32_t count = 1) const; - -protected: - ExecutionContext *ectx_; - std::function<void(ProcessControl)> onFinish_; - std::function<void(Status)> onError_; - time::Duration duration_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_EXECUTOR_H_ diff --git a/src/executor/FetchEdgesExecutor.cpp b/src/executor/FetchEdgesExecutor.cpp deleted file mode 100644 index 9c5b9a2f931d37e3feff3afc231a2ec5ad1a24e1..0000000000000000000000000000000000000000 --- a/src/executor/FetchEdgesExecutor.cpp +++ /dev/null @@ -1,385 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/FetchEdgesExecutor.h" - -namespace nebula { -namespace graph { -FetchEdgesExecutor::FetchEdgesExecutor(Sentence *sentence, ExecutionContext *ectx) - : FetchExecutor(ectx) { - sentence_ = static_cast<FetchEdgesSentence*>(sentence); -} - -Status FetchEdgesExecutor::prepare() { - return Status::OK(); -} - -Status FetchEdgesExecutor::prepareClauses() { - Status status = Status::OK(); - - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - spaceId_ = ectx()->rctx()->session()->space(); - yieldClause_ = DCHECK_NOTNULL(sentence_)->yieldClause(); - labelName_ = sentence_->edge(); - auto result = ectx()->schemaManager()->toEdgeType(spaceId_, *labelName_); - if (!result.ok()) { - status = result.status(); - break; - } - edgeType_ = result.value(); - labelSchema_ = ectx()->schemaManager()->getEdgeSchema(spaceId_, edgeType_); - if (labelSchema_ == nullptr) { - LOG(ERROR) << *labelName_ << " edge schema not exist."; - status = Status::Error("%s edge schema not exist.", labelName_->c_str()); - break; - } - - status = prepareEdgeKeys(); - if (!status.ok()) { - break; - } - status = prepareYield(); - if (!status.ok()) { - break; - } - } while (false); - return status; -} - -Status FetchEdgesExecutor::prepareEdgeKeys() { - Status status = Status::OK(); - do { - if (sentence_->isRef()) { - auto *edgeKeyRef = sentence_->ref(); - - srcid_ = edgeKeyRef->srcid(); - if (srcid_ == nullptr) { - status = Status::Error("Internal error."); - LOG(ERROR) << "Get src nullptr."; - break; - } - - dstid_ = edgeKeyRef->dstid(); - if (dstid_ == nullptr) { - status = Status::Error("Internal error."); - LOG(ERROR) << "Get dst nullptr."; - break; - } - - rank_ = edgeKeyRef->rank(); - - if ((*srcid_ == "*") - || (*dstid_ == "*") - || (rank_ != nullptr && *rank_ == "*")) { - status = Status::Error("Can not use `*' to reference a vertex id column."); - break; - } - - auto ret = edgeKeyRef->varname(); - if (!ret.ok()) { - status = std::move(ret).status(); - break; - } - varname_ = std::move(ret).value(); - } - } while (false); - - return status; -} - -void FetchEdgesExecutor::execute() { - FLOG_INFO("Executing FetchEdges: %s", sentence_->toString().c_str()); - auto status = prepareClauses(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - status = setupEdgeKeys(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - - if (edgeKeys_.empty()) { - onEmptyInputs(); - return; - } - - fetchEdges(); -} - -Status FetchEdgesExecutor::setupEdgeKeys() { - Status status = Status::OK(); - hash_ = [] (const storage::cpp2::EdgeKey &key) -> size_t { - return std::hash<VertexID>()(key.src) - ^ std::hash<VertexID>()(key.dst) - ^ std::hash<EdgeRanking>()(key.ranking); - }; - if (sentence_->isRef()) { - status = setupEdgeKeysFromRef(); - } else { - status = setupEdgeKeysFromExpr(); - } - - VLOG(3) << "EdgeKey length: " << edgeKeys_.size(); - - return status; -} - -Status FetchEdgesExecutor::setupEdgeKeysFromRef() { - const InterimResult *inputs; - if (sentence_->ref()->isInputExpr()) { - inputs = inputs_.get(); - } else { - bool existing = false; - inputs = ectx()->variableHolder()->get(varname_, &existing); - if (!existing) { - return Status::Error("Variable `%s' not defined", varname_.c_str()); - } - } - if (inputs == nullptr || !inputs->hasData()) { - // we have empty imputs from pipe. - return Status::OK(); - } - - auto ret = inputs->getVIDs(*srcid_); - if (!ret.ok()) { - return ret.status(); - } - auto srcVids = std::move(ret).value(); - ret = inputs->getVIDs(*dstid_); - if (!ret.ok()) { - return ret.status(); - } - auto dstVids = std::move(ret).value(); - - std::vector<EdgeRanking> ranks; - if (rank_ != nullptr) { - ret = inputs->getVIDs(*rank_); - if (!ret.ok()) { - return ret.status(); - } - ranks = std::move(ret).value(); - } - - std::unique_ptr<EdgeKeyHashSet> uniq; - if (distinct_) { - uniq = std::make_unique<EdgeKeyHashSet>(256, hash_); - } - for (decltype(srcVids.size()) index = 0u; index < srcVids.size(); ++index) { - storage::cpp2::EdgeKey key; - key.set_src(srcVids[index]); - key.set_edge_type(edgeType_); - key.set_dst(dstVids[index]); - key.set_ranking(rank_ == nullptr ? 0 : ranks[index]); - - if (distinct_) { - auto result = uniq->emplace(key); - if (result.second) { - edgeKeys_.emplace_back(std::move(key)); - } - } else { - edgeKeys_.emplace_back(std::move(key)); - } - } - - return Status::OK(); -} - -Status FetchEdgesExecutor::setupEdgeKeysFromExpr() { - Status status = Status::OK(); - std::unique_ptr<EdgeKeyHashSet> uniq; - if (distinct_) { - uniq = std::make_unique<EdgeKeyHashSet>(256, hash_); - } - - auto edgeKeyExprs = sentence_->keys()->keys(); - expCtx_->setSpace(spaceId_); - - for (auto *keyExpr : edgeKeyExprs) { - auto *srcExpr = keyExpr->srcid(); - srcExpr->setContext(expCtx_.get()); - - auto *dstExpr = keyExpr->dstid(); - dstExpr->setContext(expCtx_.get()); - - auto rank = keyExpr->rank(); - status = srcExpr->prepare(); - if (!status.ok()) { - break; - } - status = dstExpr->prepare(); - if (!status.ok()) { - break; - } - auto value = srcExpr->eval(); - if (!value.ok()) { - return value.status(); - } - auto srcid = value.value(); - value = dstExpr->eval(); - if (!value.ok()) { - return value.status(); - } - auto dstid = value.value(); - if (!Expression::isInt(srcid) || !Expression::isInt(dstid)) { - status = Status::Error("ID should be of type integer."); - break; - } - storage::cpp2::EdgeKey key; - key.set_src(Expression::asInt(srcid)); - key.set_edge_type(edgeType_); - key.set_dst(Expression::asInt(dstid)); - key.set_ranking(rank); - - if (distinct_) { - auto ret = uniq->emplace(key); - if (ret.second) { - edgeKeys_.emplace_back(std::move(key)); - } - } else { - edgeKeys_.emplace_back(std::move(key)); - } - } - - return status; -} - -void FetchEdgesExecutor::fetchEdges() { - std::vector<storage::cpp2::PropDef> props; - auto status = getPropNames(props); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - - if (props.empty()) { - doError(Status::Error("No props declared."), - ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - - auto future = ectx()->getStorageClient()->getEdgeProps(spaceId_, edgeKeys_, std::move(props)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (RpcResponse &&result) mutable { - auto completeness = result.completeness(); - if (completeness == 0) { - doError(Status::Error("Get props failed"), - ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } else if (completeness != 100) { - LOG(INFO) << "Get edges partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - processResult(std::move(result)); - return; - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error"), - ectx()->getGraphStats()->getFetchEdgesStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -Status FetchEdgesExecutor::getPropNames(std::vector<storage::cpp2::PropDef> &props) { - for (auto &prop : expCtx_->aliasProps()) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::EDGE; - pd.name = prop.second; - auto status = ectx()->schemaManager()->toEdgeType(spaceId_, prop.first); - if (!status.ok()) { - return Status::Error("No schema found for '%s'", prop.first.c_str()); - } - auto edgeType = status.value(); - pd.id.set_edge_type(edgeType); - props.emplace_back(std::move(pd)); - } - - return Status::OK(); -} - -void FetchEdgesExecutor::processResult(RpcResponse &&result) { - auto all = result.responses(); - std::shared_ptr<SchemaWriter> outputSchema; - std::unique_ptr<RowSetWriter> rsWriter; - auto uniqResult = std::make_unique<std::unordered_set<std::string>>(); - for (auto &resp : all) { - if (!resp.__isset.schema || !resp.__isset.data - || resp.get_schema() == nullptr || resp.get_data() == nullptr - || resp.data.empty()) { - continue; - } - - auto eschema = std::make_shared<ResultSchemaProvider>(*(resp.get_schema())); - RowSetReader rsReader(eschema, *(resp.get_data())); - auto iter = rsReader.begin(); - if (outputSchema == nullptr) { - outputSchema = std::make_shared<SchemaWriter>(); - auto status = getOutputSchema(eschema.get(), &*iter, outputSchema.get()); - if (!status.ok()) { - LOG(ERROR) << "Get getOutputSchema failed: " << status; - doError(Status::Error("Internal error."), - ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - rsWriter = std::make_unique<RowSetWriter>(outputSchema); - } - while (iter) { - auto writer = std::make_unique<RowWriter>(outputSchema); - - auto &getters = expCtx_->getters(); - getters.getAliasProp = - [&iter, &eschema] (const std::string&, - const std::string &prop) -> OptVariantType { - return Collector::getProp(eschema.get(), prop, &*iter); - }; - for (auto *column : yields_) { - auto *expr = column->expr(); - auto value = expr->eval(); - if (!value.ok()) { - doError(std::move(value).status(), - ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - auto status = Collector::collect(value.value(), writer.get()); - if (!status.ok()) { - LOG(ERROR) << "Collect prop error: " << status; - doError(std::move(status), ectx()->getGraphStats()->getFetchEdgesStats()); - return; - } - } - - // TODO Consider float/double, and need to reduce mem copy. - std::string encode = writer->encode(); - if (distinct_) { - auto ret = uniqResult->emplace(encode); - if (ret.second) { - rsWriter->addRow(std::move(encode)); - } - } else { - rsWriter->addRow(std::move(encode)); - } - ++iter; - } // while `iter' - } // for `resp' - - finishExecution(std::move(rsWriter)); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/FetchEdgesExecutor.h b/src/executor/FetchEdgesExecutor.h deleted file mode 100644 index 43b23bfd06a9689f02153eb99d43afe9eb5cc209..0000000000000000000000000000000000000000 --- a/src/executor/FetchEdgesExecutor.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_FETCHEDGESEXECUTOR_H_ -#define GRAPH_FETCHEDGESEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/FetchExecutor.h" -#include "storage/client/StorageClient.h" -#include "meta/SchemaProviderIf.h" -#include "dataman/SchemaWriter.h" - -namespace nebula { -namespace graph { -class FetchEdgesExecutor final : public FetchExecutor { -public: - FetchEdgesExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "FetchEdgesExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status prepareClauses(); - - Status prepareEdgeKeys(); - - Status setupEdgeKeys(); - - Status setupEdgeKeysFromExpr(); - - Status setupEdgeKeysFromRef(); - - Status getPropNames(std::vector<storage::cpp2::PropDef> &props); - - void fetchEdges(); - - using RpcResponse = storage::StorageRpcResponse<storage::cpp2::EdgePropResponse>; - void processResult(RpcResponse &&result); - - using EdgeKeyHashSet = std::unordered_set< - storage::cpp2::EdgeKey, - std::function<size_t(const storage::cpp2::EdgeKey& key)>>; - -private: - FetchEdgesSentence *sentence_{nullptr}; - std::vector<storage::cpp2::EdgeKey> edgeKeys_; - EdgeType edgeType_{INT_MIN}; - std::string *srcid_{nullptr}; - std::string *dstid_{nullptr}; - std::string *rank_{nullptr}; - std::string varname_; - std::function<size_t(const storage::cpp2::EdgeKey)> hash_; -}; -} // namespace graph -} // namespace nebula -#endif diff --git a/src/executor/FetchExecutor.cpp b/src/executor/FetchExecutor.cpp deleted file mode 100644 index 7bc273d99293cc91c68c497ef69071e04eb330a1..0000000000000000000000000000000000000000 --- a/src/executor/FetchExecutor.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "FetchExecutor.h" -#include "SchemaHelper.h" - -namespace nebula { -namespace graph { - -Status FetchExecutor::prepareYield() { - if (yieldClause_ == nullptr) { - setupColumns(); - } else { - yields_ = yieldClause_->columns(); - // TODO 'distinct' could always pushdown in fetch. - distinct_ = yieldClause_->isDistinct(); - } - - for (auto *col : yields_) { - col->expr()->setContext(expCtx_.get()); - Status status = col->expr()->prepare(); - if (!status.ok()) { - return status; - } - if (col->alias() == nullptr) { - resultColNames_.emplace_back(col->expr()->toString()); - } else { - resultColNames_.emplace_back(*col->alias()); - } - - // such as YIELD 1+1, it has not type in schema, the type from the eval() - colTypes_.emplace_back(nebula::cpp2::SupportedType::UNKNOWN); - if (col->expr()->isAliasExpression()) { - auto prop = *static_cast<AliasPropertyExpression*>(col->expr())->prop(); - auto type = labelSchema_->getFieldType(prop); - if (type != CommonConstants::kInvalidValueType()) { - colTypes_.back() = type.get_type(); - } - } else if (col->expr()->isTypeCastingExpression()) { - // type cast - auto exprPtr = dynamic_cast<TypeCastingExpression*>(col->expr()); - colTypes_.back() = SchemaHelper::columnTypeToSupportedType(exprPtr->getType()); - } - } - - if (expCtx_->hasSrcTagProp() || expCtx_->hasDstTagProp()) { - return Status::SyntaxError( - "tag.prop and edgetype.prop are supported in fetch sentence."); - } - - if (expCtx_->hasInputProp() || expCtx_->hasVariableProp()) { - // TODO: support yield input and variable props - return Status::SyntaxError( - "`$-' and `$variable' not supported in fetch yet."); - } - - auto aliasProps = expCtx_->aliasProps(); - for (auto pair : aliasProps) { - if (pair.first != *labelName_) { - return Status::SyntaxError( - "Near [%s.%s], tag or edge should be declared in statement first.", - pair.first.c_str(), pair.second.c_str()); - } - } - - return Status::OK(); -} - -void FetchExecutor::setupColumns() { - auto iter = DCHECK_NOTNULL(labelSchema_)->begin(); - if (yieldColsHolder_ == nullptr) { - yieldColsHolder_ = std::make_unique<YieldColumns>(); - } - while (iter) { - auto *ref = new std::string(""); - auto *alias = new std::string(*labelName_); - auto *prop = iter->getName(); - Expression *expr = - new AliasPropertyExpression(ref, alias, new std::string(prop)); - YieldColumn *column = new YieldColumn(expr); - yieldColsHolder_->addColumn(column); - yields_.emplace_back(column); - ++iter; - } -} - -void FetchExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(resultColNames_)); - } - resp = std::move(*resp_); -} - -void FetchExecutor::onEmptyInputs() { - if (onResult_) { - auto outputs = std::make_unique<InterimResult>(std::move(resultColNames_)); - onResult_(std::move(outputs)); - } else if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(resultColNames_)); - } - doFinish(Executor::ProcessControl::kNext, getStats()); -} - -Status FetchExecutor::getOutputSchema( - meta::SchemaProviderIf *schema, - const RowReader *reader, - SchemaWriter *outputSchema) const { - if (expCtx_ == nullptr || resultColNames_.empty()) { - return Status::Error("Input is empty."); - } - auto &getters = expCtx_->getters(); - getters.getAliasProp = [schema, reader] (const std::string&, const std::string &prop) { - return Collector::getProp(schema, prop, reader); - }; - std::vector<VariantType> record; - for (auto *column : yields_) { - auto *expr = column->expr(); - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - record.emplace_back(std::move(value.value())); - } - - return Collector::getSchema(record, resultColNames_, colTypes_, outputSchema); -} - -void FetchExecutor::finishExecution(std::unique_ptr<RowSetWriter> rsWriter) { - auto outputs = std::make_unique<InterimResult>(std::move(resultColNames_)); - if (rsWriter != nullptr) { - outputs->setInterim(std::move(rsWriter)); - } - - if (onResult_) { - onResult_(std::move(outputs)); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - auto colNames = outputs->getColNames(); - resp_->set_column_names(std::move(colNames)); - if (outputs->hasData()) { - auto ret = outputs->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - doError(std::move(ret).status(), getStats()); - return; - } - resp_->set_rows(std::move(ret).value()); - } - } - doFinish(Executor::ProcessControl::kNext, getStats()); -} - -stats::Stats* FetchExecutor::getStats() const { - if (0 == strcmp(name(), "FetchVerticesExecutor")) { - return ectx()->getGraphStats()->getFetchVerticesStats(); - } else { - return ectx()->getGraphStats()->getFetchEdgesStats(); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/FetchExecutor.h b/src/executor/FetchExecutor.h deleted file mode 100644 index 56666b72d24f690c931c3817b76071bc368ea82e..0000000000000000000000000000000000000000 --- a/src/executor/FetchExecutor.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_FETCHEXECUTOR_H_ -#define GRAPH_FETCHEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "storage/client/StorageClient.h" - -namespace nebula { -namespace graph { -class FetchExecutor : public TraverseExecutor { -public: - explicit FetchExecutor(ExecutionContext *ectx) : TraverseExecutor(ectx) {} - - void feedResult(std::unique_ptr<InterimResult> result) override { - inputs_ = std::move(result); - } - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -protected: - Status prepareYield(); - - void setupColumns(); - - void onEmptyInputs(); - - Status getOutputSchema( - meta::SchemaProviderIf *schema, - const RowReader *reader, - SchemaWriter *outputSchema) const; - - void finishExecution(std::unique_ptr<RowSetWriter> rsWriter); - - stats::Stats* getStats() const; - -protected: - GraphSpaceID spaceId_{INT_MIN}; - std::unique_ptr<ExpressionContext> expCtx_; - std::string *labelName_{nullptr}; - std::shared_ptr<const meta::SchemaProviderIf> labelSchema_; - YieldClause *yieldClause_{nullptr}; - std::vector<YieldColumn*> yields_; - std::unique_ptr<YieldColumns> yieldColsHolder_; - bool distinct_{false}; - std::unique_ptr<InterimResult> inputs_; - std::vector<std::string> resultColNames_; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - std::vector<nebula::cpp2::SupportedType> colTypes_; -}; -} // namespace graph -} // namespace nebula -#endif diff --git a/src/executor/FetchVerticesExecutor.cpp b/src/executor/FetchVerticesExecutor.cpp deleted file mode 100644 index 0b7cd06c3ace719e51a7c578683e8a3aa8ce8efd..0000000000000000000000000000000000000000 --- a/src/executor/FetchVerticesExecutor.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/FetchVerticesExecutor.h" -#include "meta/SchemaProviderIf.h" -#include "dataman/SchemaWriter.h" - -namespace nebula { -namespace graph { -FetchVerticesExecutor::FetchVerticesExecutor(Sentence *sentence, ExecutionContext *ectx) - : FetchExecutor(ectx) { - sentence_ = static_cast<FetchVerticesSentence*>(sentence); -} - -Status FetchVerticesExecutor::prepare() { - return Status::OK(); -} - -Status FetchVerticesExecutor::prepareClauses() { - Status status = Status::OK(); - - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - spaceId_ = ectx()->rctx()->session()->space(); - yieldClause_ = DCHECK_NOTNULL(sentence_)->yieldClause(); - labelName_ = sentence_->tag(); - auto result = ectx()->schemaManager()->toTagID(spaceId_, *labelName_); - if (!result.ok()) { - status = result.status(); - break; - } - tagID_ = result.value(); - labelSchema_ = ectx()->schemaManager()->getTagSchema(spaceId_, tagID_); - if (labelSchema_ == nullptr) { - LOG(ERROR) << *labelName_ << " tag schema not exist."; - status = Status::Error("%s tag schema not exist.", labelName_->c_str()); - break; - } - - status = prepareVids(); - if (!status.ok()) { - break; - } - status = prepareYield(); - if (!status.ok()) { - break; - } - } while (false); - return status; -} - -Status FetchVerticesExecutor::prepareVids() { - if (sentence_->isRef()) { - auto *expr = sentence_->ref(); - if (expr->isInputExpression()) { - auto *iexpr = static_cast<InputPropertyExpression*>(expr); - colname_ = iexpr->prop(); - } else if (expr->isVariableExpression()) { - auto *vexpr = static_cast<VariablePropertyExpression*>(expr); - varname_ = vexpr->alias(); - colname_ = vexpr->prop(); - } else { - // should never come to here. - // only support input and variable yet. - LOG(FATAL) << "Unknown kind of expression."; - } - if (colname_ != nullptr && *colname_ == "*") { - return Status::Error("Cant not use `*' to reference a vertex id column."); - } - } - return Status::OK(); -} - -void FetchVerticesExecutor::execute() { - FLOG_INFO("Executing FetchVertices: %s", sentence_->toString().c_str()); - auto status = prepareClauses(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - - status = setupVids(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - if (vids_.empty()) { - onEmptyInputs(); - return; - } - - fetchVertices(); -} - -void FetchVerticesExecutor::fetchVertices() { - auto props = getPropNames(); - if (props.empty()) { - doError(Status::Error("No props declared."), - ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - - auto future = ectx()->getStorageClient()->getVertexProps(spaceId_, vids_, std::move(props)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (RpcResponse &&result) mutable { - auto completeness = result.completeness(); - if (completeness == 0) { - doError(Status::Error("Get props failed"), - ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } else if (completeness != 100) { - LOG(INFO) << "Get vertices partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - processResult(std::move(result)); - return; - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error"), ectx()->getGraphStats()->getFetchVerticesStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -std::vector<storage::cpp2::PropDef> FetchVerticesExecutor::getPropNames() { - std::vector<storage::cpp2::PropDef> props; - for (auto &prop : expCtx_->aliasProps()) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::SOURCE; - pd.name = prop.second; - pd.id.set_tag_id(tagID_); - props.emplace_back(std::move(pd)); - } - - return props; -} - -void FetchVerticesExecutor::processResult(RpcResponse &&result) { - auto all = result.responses(); - std::shared_ptr<SchemaWriter> outputSchema; - std::unique_ptr<RowSetWriter> rsWriter; - auto uniqResult = std::make_unique<std::unordered_set<std::string>>(); - for (auto &resp : all) { - if (!resp.__isset.vertices) { - continue; - } - - auto *schema = resp.get_vertex_schema(); - if (schema == nullptr) { - continue; - } - - std::unordered_map<TagID, std::shared_ptr<ResultSchemaProvider>> tagSchema; - std::transform(schema->cbegin(), schema->cend(), - std::inserter(tagSchema, tagSchema.begin()), [](auto &s) { - return std::make_pair( - s.first, std::make_shared<ResultSchemaProvider>(s.second)); - }); - - for (auto &vdata : resp.vertices) { - std::unique_ptr<RowReader> vreader; - if (!vdata.__isset.tag_data || vdata.tag_data.empty()) { - continue; - } - - auto vschema = tagSchema[vdata.tag_data[0].tag_id]; - vreader = RowReader::getRowReader(vdata.tag_data[0].data, vschema); - if (outputSchema == nullptr) { - outputSchema = std::make_shared<SchemaWriter>(); - auto status = getOutputSchema(vschema.get(), vreader.get(), outputSchema.get()); - if (!status.ok()) { - LOG(ERROR) << "Get getOutputSchema failed: " << status; - doError(Status::Error("Internal error."), - ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - rsWriter = std::make_unique<RowSetWriter>(outputSchema); - } - - auto writer = std::make_unique<RowWriter>(outputSchema); - auto &getters = expCtx_->getters(); - getters.getAliasProp = - [&vreader, &vschema] (const std::string&, - const std::string &prop) -> OptVariantType { - return Collector::getProp(vschema.get(), prop, vreader.get()); - }; - for (auto *column : yields_) { - auto *expr = column->expr(); - auto value = expr->eval(); - if (!value.ok()) { - doError(std::move(value).status(), - ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - auto status = Collector::collect(value.value(), writer.get()); - if (!status.ok()) { - LOG(ERROR) << "Collect prop error: " << status; - doError(std::move(status), ectx()->getGraphStats()->getFetchVerticesStats()); - return; - } - } - // TODO Consider float/double, and need to reduce mem copy. - std::string encode = writer->encode(); - if (distinct_) { - auto ret = uniqResult->emplace(encode); - if (ret.second) { - rsWriter->addRow(std::move(encode)); - } - } else { - rsWriter->addRow(std::move(encode)); - } - } // for `vdata' - } // for `resp' - - finishExecution(std::move(rsWriter)); -} - -Status FetchVerticesExecutor::setupVids() { - Status status = Status::OK(); - if (sentence_->isRef()) { - status = setupVidsFromRef(); - } else { - status = setupVidsFromExpr(); - } - - return status; -} - -Status FetchVerticesExecutor::setupVidsFromExpr() { - Status status = Status::OK(); - std::unique_ptr<std::unordered_set<VertexID>> uniqID; - if (distinct_) { - uniqID = std::make_unique<std::unordered_set<VertexID>>(); - } - - expCtx_->setSpace(spaceId_); - auto vidList = sentence_->vidList(); - for (auto *expr : vidList) { - expr->setContext(expCtx_.get()); - status = expr->prepare(); - if (!status.ok()) { - break; - } - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - auto v = value.value(); - if (!Expression::isInt(v)) { - status = Status::Error("Vertex ID should be of type integer"); - break; - } - - auto valInt = Expression::asInt(v); - if (distinct_) { - auto result = uniqID->emplace(valInt); - if (result.second) { - vids_.emplace_back(valInt); - } - } else { - vids_.emplace_back(valInt); - } - } - - return status; -} - -Status FetchVerticesExecutor::setupVidsFromRef() { - const InterimResult *inputs; - if (varname_ == nullptr) { - inputs = inputs_.get(); - } else { - bool existing = false; - inputs = ectx()->variableHolder()->get(*varname_, &existing); - if (!existing) { - return Status::Error("Variable `%s' not defined", varname_->c_str()); - } - } - if (inputs == nullptr || !inputs->hasData()) { - return Status::OK(); - } - - StatusOr<std::vector<VertexID>> result; - if (distinct_) { - result = inputs->getDistinctVIDs(*colname_); - } else { - result = inputs->getVIDs(*colname_); - } - if (!result.ok()) { - return std::move(result).status(); - } - vids_ = std::move(result).value(); - return Status::OK(); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/FetchVerticesExecutor.h b/src/executor/FetchVerticesExecutor.h deleted file mode 100644 index 1940e2a252d677075dbe5ddc1ef60baebd75bcac..0000000000000000000000000000000000000000 --- a/src/executor/FetchVerticesExecutor.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_FETCHVERTICESEXECUTOR_H_ -#define GRAPH_FETCHVERTICESEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/FetchExecutor.h" -#include "storage/client/StorageClient.h" -#include "meta/SchemaProviderIf.h" -#include "dataman/SchemaWriter.h" - -namespace nebula { -namespace graph { -class FetchVerticesExecutor final : public FetchExecutor { -public: - FetchVerticesExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "FetchVerticesExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status prepareClauses(); - - Status prepareVids(); - - Status setupVids(); - - Status setupVidsFromRef(); - - Status setupVidsFromExpr(); - - std::vector<storage::cpp2::PropDef> getPropNames(); - - void fetchVertices(); - - using RpcResponse = storage::StorageRpcResponse<storage::cpp2::QueryResponse>; - void processResult(RpcResponse &&result); - -private: - FetchVerticesSentence *sentence_{nullptr}; - std::vector<VertexID> vids_; - TagID tagID_{INT_MIN}; - std::string *varname_{nullptr}; - std::string *colname_{nullptr}; -}; -} // namespace graph -} // namespace nebula -#endif // GRAPH_FETCHVERTICESEXECUTOR_H_ diff --git a/src/executor/FindExecutor.cpp b/src/executor/FindExecutor.cpp deleted file mode 100644 index ea4cc86541e158ed005c1f424db2970544adee20..0000000000000000000000000000000000000000 --- a/src/executor/FindExecutor.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/FindExecutor.h" - -namespace nebula { -namespace graph { - -FindExecutor::FindExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<FindSentence*>(sentence); -} - - -Status FindExecutor::prepare() { - return Status::Error("Does not support"); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/FindExecutor.h b/src/executor/FindExecutor.h deleted file mode 100644 index 4064b9b6debe26126f6d4fc8b4b45ffdb08feae3..0000000000000000000000000000000000000000 --- a/src/executor/FindExecutor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_FINDEXECUTOR_H_ -#define GRAPH_FINDEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class FindExecutor final : public TraverseExecutor { -public: - FindExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "FindExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void feedResult(std::unique_ptr<InterimResult> result) override { - UNUSED(result); - } - - void execute() override {} - -private: - FindSentence *sentence_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_FINDEXECUTOR_H_ diff --git a/src/executor/FindPathExecutor.cpp b/src/executor/FindPathExecutor.cpp deleted file mode 100644 index 8bdcd4b93ed5a223301997a2669d80476dcd64b6..0000000000000000000000000000000000000000 --- a/src/executor/FindPathExecutor.cpp +++ /dev/null @@ -1,714 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "FindPathExecutor.h" - -namespace nebula { -namespace graph { - -FindPathExecutor::FindPathExecutor(Sentence *sentence, ExecutionContext *exct) - : TraverseExecutor(exct) { - sentence_ = static_cast<FindPathSentence*>(sentence); -} - -Status FindPathExecutor::prepare() { - Status status; - expCtx_ = std::make_unique<ExpressionContext>(); - do { - if (sentence_->from() != nullptr) { - status = sentence_->from()->prepare(from_); - if (!status.ok()) { - break; - } - } - if (sentence_->to() != nullptr) { - status = sentence_->to()->prepare(to_); - if (!status.ok()) { - break; - } - } - if (sentence_->over() != nullptr) { - status = sentence_->over()->prepare(over_); - if (!status.ok()) { - break; - } - } - if (sentence_->step() != nullptr) { - status = sentence_->step()->prepare(step_); - if (!status.ok()) { - break; - } - } - if (sentence_->where() != nullptr) { - status = sentence_->where()->prepare(where_); - if (!status.ok()) { - break; - } - } - shortest_ = sentence_->isShortest(); - } while (false); - - if (!status.ok()) { - stats::Stats::addStatsValue(ectx()->getGraphStats()->getFindPathStats(), - false, duration().elapsedInUSec()); - } - return status; -} - -Status FindPathExecutor::beforeExecute() { - Status status; - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break;; - } - spaceId_ = ectx()->rctx()->session()->space(); - - status = prepareOver(); - if (!status.ok()) { - break; - } - - status = setupVids(); - if (!status.ok()) { - break; - } - } while (false); - return status; -} - -Status FindPathExecutor::prepareOverAll() { - auto edgeAllStatus = ectx()->schemaManager()->getAllEdge(spaceId_); - - if (!edgeAllStatus.ok()) { - return edgeAllStatus.status(); - } - - auto allEdge = edgeAllStatus.value(); - for (auto &e : allEdge) { - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId_, e); - if (!edgeStatus.ok()) { - return edgeStatus.status(); - } - - auto v = edgeStatus.value(); - over_.edgeTypes_.emplace_back(v); - over_.oppositeTypes_.emplace_back(-v); - - if (!expCtx_->addEdge(e, v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", e)); - } - edgeTypeNameMap_.emplace(v, e); - } - - return Status::OK(); -} - -Status FindPathExecutor::prepareOver() { - Status status = Status::OK(); - - for (auto e : over_.edges_) { - if (e->isOverAll()) { - expCtx_->setOverAllEdge(); - return prepareOverAll(); - } - - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId_, *e->edge()); - if (!edgeStatus.ok()) { - return edgeStatus.status(); - } - - auto v = edgeStatus.value(); - over_.edgeTypes_.emplace_back(v); - over_.oppositeTypes_.emplace_back(-v); - - if (e->alias() != nullptr) { - if (!expCtx_->addEdge(*e->alias(), v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", *e->alias())); - } - } else { - if (!expCtx_->addEdge(*e->edge(), v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", *e->edge())); - } - } - - edgeTypeNameMap_.emplace(v, *e->edge()); - } - - return status; -} - -void FindPathExecutor::execute() { - auto status = beforeExecute(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getFindPathStats()); - return; - } - - steps_ = step_.steps_ / 2 + step_.steps_ % 2; - fromVids_ = from_.vids_; - toVids_ = to_.vids_; - visitedFrom_.insert(fromVids_.begin(), fromVids_.end()); - visitedTo_.insert(toVids_.begin(), toVids_.end()); - targetNotFound_.insert(toVids_.begin(), toVids_.end()); - for (auto &v : fromVids_) { - Path path; - pathFrom_.emplace(v, std::move(path)); - } - for (auto &v : toVids_) { - Path path; - pathTo_.emplace(v, std::move(path)); - } - - getNeighborsAndFindPath(); -} - -void FindPathExecutor::getNeighborsAndFindPath() { - // We meet the dead end. - if (fromVids_.empty() || toVids_.empty()) { - onFinish_(Executor::ProcessControl::kNext); - return; - } - - fPro_ = std::make_unique<folly::Promise<folly::Unit>>(); - tPro_ = std::make_unique<folly::Promise<folly::Unit>>(); - std::vector<folly::Future<folly::Unit>> futures; - futures.emplace_back(fPro_->getFuture()); - futures.emplace_back(tPro_->getFuture()); - - auto props = getStepOutProps(false); - if (!props.ok()) { - doError(std::move(props).status(), ectx()->getGraphStats()->getFindPathStats()); - return; - } - getFromFrontiers(std::move(props).value()); - - props = getStepOutProps(true); - if (!props.ok()) { - doError(std::move(props).status(), ectx()->getGraphStats()->getFindPathStats()); - return; - } - getToFrontiers(std::move(props).value()); - - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&result) { - UNUSED(result); - if (!fStatus_.ok() || !tStatus_.ok()) { - std::string msg = fStatus_.toString() + " " + tStatus_.toString(); - doError(Status::Error(std::move(msg)), ectx()->getGraphStats()->getFindPathStats()); - return; - } - - findPath(); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error."), ectx()->getGraphStats()->getFindPathStats()); - }; - folly::collectAll(futures).via(runner).thenValue(cb).thenError(error); -} - -void FindPathExecutor::findPath() { - VLOG(2) << "Find Path."; - visitedFrom_.clear(); - std::multimap<VertexID, Path> pathF; - VLOG(2) << "Get froms: " << fromFrontiers_.second.size(); - VLOG(2) << "Get tos: " << toFrontiers_.second.size(); - for (auto &frontier : fromFrontiers_.second) { - // Notice: we treat edges with different ranking - // between two vertices as different path - for (auto &neighbor : frontier.second) { - auto dstId = std::get<0>(neighbor); - VLOG(2) << "src vertex:" << frontier.first; - VLOG(2) << "dst vertex:" << dstId; - // if frontiers of F are neighbors of visitedByT, - // we found an odd path - if (visitedTo_.count(dstId) == 1) { - meetOddPath(frontier.first, dstId, neighbor); - } - - // update the path to frontiers - updatePath(frontier.first, pathFrom_, neighbor, pathF, VisitedBy::FROM); - visitedFrom_.emplace(dstId); - } // for `neighbor' - } // for `frontier' - pathFrom_ = std::move(pathF); - fromVids_.clear(); - fromVids_.reserve(visitedFrom_.size()); - std::copy(visitedFrom_.begin(), - visitedFrom_.end(), std::back_inserter(fromVids_)); - - visitedTo_.clear(); - std::multimap<VertexID, Path> pathT; - for (auto &frontier : toFrontiers_.second) { - for (auto &neighbor : frontier.second) { - auto dstId = std::get<0>(neighbor); - // update the path to frontiers - updatePath(frontier.first, pathTo_, neighbor, pathT, VisitedBy::TO); - visitedTo_.emplace(dstId); - } // for `neighbor' - } // for `frontier' - pathTo_ = std::move(pathT); - toVids_.clear(); - toVids_.reserve(visitedTo_.size()); - std::copy(visitedTo_.begin(), - visitedTo_.end(), std::back_inserter(toVids_)); - - std::sort(fromVids_.begin(), fromVids_.end()); - std::sort(toVids_.begin(), toVids_.end()); - std::set<VertexID> intersect; - std::set_intersection(fromVids_.begin(), fromVids_.end(), - toVids_.begin(), toVids_.end(), - std::inserter(intersect, intersect.end())); - // if frontiersF meets frontiersT, we found an even path - if (!intersect.empty()) { - if (shortest_ && targetNotFound_.empty()) { - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getFindPathStats()); - return; - } - for (auto intersectId : intersect) { - meetEvenPath(intersectId); - } // `intersectId' - } - - if (isFinalStep() || - (shortest_ && targetNotFound_.empty())) { - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getFindPathStats()); - return; - } else { - VLOG(2) << "Current step:" << currentStep_; - ++currentStep_; - } - getNeighborsAndFindPath(); -} - -inline void FindPathExecutor::meetOddPath(VertexID src, VertexID dst, Neighbor &neighbor) { - VLOG(2) << "Meet Odd Path."; - auto rangeF = pathFrom_.equal_range(src); - for (auto i = rangeF.first; i != rangeF.second; ++i) { - auto rangeT = pathTo_.equal_range(dst); - for (auto j = rangeT.first; j != rangeT.second; ++j) { - if (j->second.size() + i->second.size() > step_.steps_) { - continue; - } - // Build path: - // i->second + (src,type,ranking) + (dst, -type, ranking) + j->second - Path path = i->second; - auto s0 = std::make_unique<StepOut>(neighbor); - std::get<0>(*s0) = src; - path.emplace_back(s0.get()); - stepOutHolder_.emplace(std::move(s0)); - VLOG(2) << "PathF: " << buildPathString(path); - - auto s1 = std::make_unique<StepOut>(neighbor); - std::get<1>(*s1) = - std::get<1>(neighbor); - path.emplace_back(s1.get()); - stepOutHolder_.emplace(std::move(s1)); - path.insert(path.end(), j->second.begin(), j->second.end()); - VLOG(2) << "PathT: " << buildPathString(j->second); - - auto target = std::get<0>(*(path.back())); - if (shortest_) { - targetNotFound_.erase(target); - if (finalPath_.count(target) > 0) { - // already found a shorter path - continue; - } else { - VLOG(2) << "Found path: " << buildPathString(path); - finalPath_.emplace(target, std::move(path)); - } - } else { - VLOG(2) << "Found path: " << buildPathString(path); - finalPath_.emplace(target, std::move(path)); - } - } // for `j' - } // for `i' -} - -inline void FindPathExecutor::meetEvenPath(VertexID intersectId) { - VLOG(2) << "Meet Even Path."; - auto rangeF = pathFrom_.equal_range(intersectId); - auto rangeT = pathTo_.equal_range(intersectId); - for (auto i = rangeF.first; i != rangeF.second; ++i) { - for (auto j = rangeT.first; j != rangeT.second; ++j) { - if (j->second.size() + i->second.size() > step_.steps_) { - continue; - } - // Build path: - // i->second + (src,type,ranking) + j->second - Path path = i->second; - VLOG(2) << "PathF: " << buildPathString(path); - if (j->second.size() > 0) { - StepOut *s = j->second.front(); - auto s0 = std::make_unique<StepOut>(*s); - std::get<0>(*s0) = intersectId; - std::get<1>(*s0) = - std::get<1>(*s0); - path.emplace_back(s0.get()); - stepOutHolder_.emplace(std::move(s0)); - VLOG(2) << "Joiner: " << buildPathString(path); - } else if (i->second.size() > 0) { - StepOut *s = i->second.back(); - auto s0 = std::make_unique<StepOut>(*s); - std::get<0>(*s0) = intersectId; - path.emplace_back(s0.get()); - stepOutHolder_.emplace(std::move(s0)); - VLOG(2) << "Joiner: " << buildPathString(path); - } - VLOG(2) << "PathT: " << buildPathString(j->second); - path.insert(path.end(), j->second.begin(), j->second.end()); - auto target = std::get<0>(*(path.back())); - if (shortest_) { - if (finalPath_.count(target) > 0) { - // already found a shorter path - continue; - } else { - targetNotFound_.erase(target); - VLOG(2) << "Found path: " << buildPathString(path); - finalPath_.emplace(target, std::move(path)); - } - } else { - VLOG(2) << "Found path: " << buildPathString(path); - finalPath_.emplace(target, std::move(path)); - } - } - } -} - -inline void FindPathExecutor::updatePath( - VertexID &src, - std::multimap<VertexID, Path> &pathToSrc, - Neighbor &neighbor, - std::multimap<VertexID, Path> &pathToNeighbor, - VisitedBy visitedBy) { - VLOG(2) << "Update Path."; - auto range = pathToSrc.equal_range(src); - for (auto i = range.first; i != range.second; ++i) { - // Build path: - // i->second + (src,type,ranking) - Path path = i->second; - VLOG(2) << "Interim path before :" << buildPathString(path); - VLOG(2) << "Interim path length before:" << path.size(); - auto s = std::make_unique<StepOut>(neighbor); - std::get<0>(*s) = src; - if (visitedBy == VisitedBy::FROM) { - path.emplace_back(s.get()); - } else { - path.emplace(path.begin(), s.get()); - } - VLOG(2) << "Neighbor: " << std::get<0>(neighbor); - VLOG(2) << "Interim path:" << buildPathString(path); - VLOG(2) << "Interim path length:" << path.size(); - stepOutHolder_.emplace(std::move(s)); - pathToNeighbor.emplace(std::get<0>(neighbor), std::move(path)); - } // for `i' -} - -Status FindPathExecutor::setupVids() { - Status status = Status::OK(); - do { - if (sentence_->from()->isRef()) { - status = setupVidsFromRef(from_); - if (!status.ok()) { - break; - } - } - - if (sentence_->to()->isRef()) { - status = setupVidsFromRef(to_); - if (!status.ok()) { - break; - } - } - } while (false); - - return status; -} - -Status FindPathExecutor::setupVidsFromRef(Clause::Vertices &vertices) { - const InterimResult *inputs; - if (vertices.varname_ == nullptr) { - inputs = inputs_.get(); - if (inputs == nullptr) { - return Status::OK(); - } - } else { - inputs = ectx()->variableHolder()->get(*(vertices.varname_)); - if (inputs == nullptr) { - return Status::Error("Variable `%s' not defined", vertices.varname_->c_str()); - } - } - - auto result = inputs->getDistinctVIDs(*(vertices.colname_)); - if (!result.ok()) { - return std::move(result).status(); - } - vertices.vids_ = std::move(result).value(); - return Status::OK(); -} - -void FindPathExecutor::getFromFrontiers( - std::vector<storage::cpp2::PropDef> props) { - auto future = ectx()->getStorageClient()->getNeighbors(spaceId_, - std::move(fromVids_), - over_.edgeTypes_, - "", - std::move(props)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&result) { - Frontiers frontiers; - auto completeness = result.completeness(); - if (completeness == 0) { - fStatus_ = Status::Error("Get neighbors failed."); - fPro_->setValue(); - return; - } else if (completeness != 100) { - LOG(INFO) << "Get neighbors partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - auto status = doFilter(std::move(result), where_.filter_, true, frontiers); - if (!status.ok()) { - fStatus_ = std::move(status); - fPro_->setValue(); - return; - } - fromFrontiers_ = std::make_pair(VisitedBy::FROM, std::move(frontiers)); - fPro_->setValue(); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - fStatus_ = Status::Error("Get neighbors failed."); - }; - std::move(future).via(runner, folly::Executor::HI_PRI).thenValue(cb).thenError(error); -} - -void FindPathExecutor::getToFrontiers( - std::vector<storage::cpp2::PropDef> props) { - auto future = ectx()->getStorageClient()->getNeighbors(spaceId_, - std::move(toVids_), - over_.oppositeTypes_, - "", - std::move(props)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&result) { - Frontiers frontiers; - auto completeness = result.completeness(); - if (completeness == 0) { - tStatus_ = Status::Error("Get neighbors failed."); - tPro_->setValue(); - return; - } else if (completeness != 100) { - LOG(INFO) << "Get neighbors partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - auto status = doFilter(std::move(result), where_.filter_, false, frontiers); - if (!status.ok()) { - tStatus_ = std::move(status); - tPro_->setValue(); - return; - } - toFrontiers_ = std::make_pair(VisitedBy::TO, std::move(frontiers)); - tPro_->setValue(); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - tStatus_ = Status::Error("Get neighbors failed."); - }; - std::move(future).via(runner, folly::Executor::HI_PRI).thenValue(cb).thenError(error); -} - -Status FindPathExecutor::doFilter( - storage::StorageRpcResponse<storage::cpp2::QueryResponse> &&result, - Expression *filter, - bool isOutBound, - Frontiers &frontiers) { - UNUSED(filter); - UNUSED(isOutBound); - - auto &resps = result.responses(); - for (auto &resp : resps) { - if (resp.get_vertices() == nullptr) { - continue; - } - - std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> edgeSchema; - auto *eschema = resp.get_edge_schema(); - if (eschema != nullptr) { - std::transform(eschema->cbegin(), eschema->cend(), - std::inserter(edgeSchema, edgeSchema.begin()), [](auto &schema) { - return std::make_pair( - schema.first, - std::make_shared<ResultSchemaProvider>(schema.second)); - }); - } - - if (edgeSchema.empty()) { - continue; - } - - for (auto &vdata : resp.vertices) { - DCHECK(vdata.__isset.edge_data); - for (auto &edata : vdata.edge_data) { - auto edgeType = edata.type; - auto it = edgeSchema.find(edgeType); - DCHECK(it != edgeSchema.end()); - RowSetReader rsReader(it->second, edata.data); - auto iter = rsReader.begin(); - Neighbors neighbors; - while (iter) { - std::vector<VariantType> temps; - for (auto &prop : kReserveProps_) { - auto res = RowReader::getPropByName(&*iter, prop); - if (ok(res)) { - temps.emplace_back(std::move(value(res))); - } else { - return Status::Error("get edge prop failed %s", prop.c_str()); - } - } - Neighbor neighbor( - boost::get<int64_t>(temps[0]), - boost::get<int64_t>(temps[1]), - boost::get<int64_t>(temps[2])); - neighbors.emplace_back(std::move(neighbor)); - ++iter; - } // while `iter' - auto frontier = std::make_pair(vdata.get_vertex_id(), std::move(neighbors)); - frontiers.emplace_back(std::move(frontier)); - } // `edata' - } // for `vdata' - } // for `resp' - return Status::OK(); -} - -StatusOr<std::vector<storage::cpp2::PropDef>> -FindPathExecutor::getStepOutProps(bool reversely) { - auto *edges = &over_.edgeTypes_; - if (reversely) { - edges = &over_.oppositeTypes_; - } - std::vector<storage::cpp2::PropDef> props; - for (auto &e : *edges) { - for (auto &prop : kReserveProps_) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::EDGE; - pd.name = prop; - pd.id.set_edge_type(e); - props.emplace_back(std::move(pd)); - } - } - - return props; -} - -std::string FindPathExecutor::buildPathString(const Path &path) { - std::string pathStr; - auto iter = path.begin(); - for (; iter != path.end(); ++iter) { - auto *step = *iter; - auto id = std::get<0>(*step); - auto type = std::get<1>(*step); - auto ranking = std::get<2>(*step); - if (type < 0) { - pathStr += folly::to<std::string>(id); - ++iter; - break; - } - - pathStr += folly::stringPrintf("%ld<%d,%ld>", id, type, ranking); - } - - for (; iter != path.end(); ++iter) { - auto *step = *iter; - auto id = std::get<0>(*step); - auto type = std::get<1>(*step); - auto ranking = std::get<2>(*step); - - pathStr += folly::stringPrintf("<%d,%ld>%ld", -type, ranking, id); - } - - return pathStr; -} - -cpp2::RowValue FindPathExecutor::buildPathRow(const Path &path) { - cpp2::RowValue rowValue; - std::vector<cpp2::ColumnValue> row; - cpp2::Path pathValue; - auto entryList = pathValue.get_entry_list(); - auto iter = path.begin(); - for (; iter != path.end(); ++iter) { - auto *step = *iter; - auto id = std::get<0>(*step); - auto type = std::get<1>(*step); - auto ranking = std::get<2>(*step); - if (type < 0) { - entryList.emplace_back(); - cpp2::Vertex vertex; - vertex.set_id(id); - entryList.back().set_vertex(std::move(vertex)); - ++iter; - break; - } - entryList.emplace_back(); - cpp2::Vertex vertex; - vertex.set_id(id); - entryList.back().set_vertex(std::move(vertex)); - - entryList.emplace_back(); - cpp2::Edge edge; - auto typeName = edgeTypeNameMap_.find(type); - DCHECK(typeName != edgeTypeNameMap_.end()) << type; - edge.set_type(typeName->second); - edge.set_ranking(ranking); - entryList.back().set_edge(std::move(edge)); - } - - for (; iter != path.end(); ++iter) { - auto *step = *iter; - auto id = std::get<0>(*step); - auto type = std::get<1>(*step); - auto ranking = std::get<2>(*step); - - entryList.emplace_back(); - cpp2::Edge edge; - auto typeName = edgeTypeNameMap_.find(-type); - DCHECK(typeName != edgeTypeNameMap_.end()) << type; - edge.set_type(typeName->second); - edge.set_ranking(ranking); - entryList.back().set_edge(std::move(edge)); - - entryList.emplace_back(); - cpp2::Vertex vertex; - vertex.set_id(id); - entryList.back().set_vertex(std::move(vertex)); - } - - row.emplace_back(); - pathValue.set_entry_list(std::move(entryList)); - row.back().set_path(std::move(pathValue)); - rowValue.set_columns(std::move(row)); - return rowValue; -} - -void FindPathExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - std::vector<cpp2::RowValue> rows; - for (auto &path : finalPath_) { - auto row = buildPathRow(path.second); - rows.emplace_back(std::move(row)); - VLOG(1) << "Path: " << buildPathString(path.second); - } - - std::vector<std::string> colNames = {"_path_"}; - resp.set_column_names(std::move(colNames)); - resp.set_rows(std::move(rows)); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/FindPathExecutor.h b/src/executor/FindPathExecutor.h deleted file mode 100644 index 87aa250ec3a85ced1e5bfbcd894176dfa0929e1c..0000000000000000000000000000000000000000 --- a/src/executor/FindPathExecutor.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_FINDPATHEXECUTOR_H_ -#define GRAPH_FINDPATHEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "storage/client/StorageClient.h" -#include "common/concurrent/Barrier.h" - -namespace nebula { -namespace graph { - -using SchemaProps = std::unordered_map<std::string, std::vector<std::string>>; -const std::vector<std::string> kReserveProps_ = {"_dst", "_type", "_rank"}; -using Neighbor = std::tuple<VertexID, EdgeType, EdgeRanking>; /* dst, type, rank*/ -using Neighbors = std::vector<Neighbor>; -using Frontiers = - std::vector< - std::pair< - VertexID, /* start */ - Neighbors /* frontiers of vertex*/ - > - >; - -using StepOut = std::tuple<VertexID, EdgeType, EdgeRanking>; /* src, type, rank*/ -using Path = std::list<StepOut*>; -enum class VisitedBy : char { - FROM, - TO, -}; - -class FindPathExecutor final : public TraverseExecutor { -public: - FindPathExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "FindPathExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override { - inputs_ = std::move(result); - } - - void setupResponse(cpp2::ExecutionResponse &resp) override; - - static std::string buildPathString(const Path &path); - - cpp2::RowValue buildPathRow(const Path &path); - -private: - // Do some prepare work that can not do in prepare() - Status beforeExecute(); - - Status prepareOver(); - - Status prepareOverAll(); - - void getNeighborsAndFindPath(); - - bool isFinalStep() { - return currentStep_ == steps_; - } - - void getFromFrontiers(std::vector<storage::cpp2::PropDef> props); - - void getToFrontiers(std::vector<storage::cpp2::PropDef> props); - - void findPath(); - - inline void meetOddPath(VertexID src, VertexID dst, Neighbor &neighbor); - - inline void meetEvenPath(VertexID intersectId); - - inline void updatePath( - VertexID &src, - std::multimap<VertexID, Path> &pathToSrc, - Neighbor &neighbor, - std::multimap<VertexID, Path> &pathToNeighbor, - VisitedBy visitedBy); - - Status setupVids(); - - Status setupVidsFromRef(Clause::Vertices &vertices); - - Status doFilter( - storage::StorageRpcResponse<storage::cpp2::QueryResponse> &&result, - Expression *filter, - bool isOutBound, - Frontiers &frontiers); - - StatusOr<std::vector<storage::cpp2::PropDef>> getStepOutProps(bool reversely); - - StatusOr<std::vector<storage::cpp2::PropDef>> getDstProps(); - -private: - FindPathSentence *sentence_{nullptr}; - std::unique_ptr<ExpressionContext> expCtx_; - GraphSpaceID spaceId_{INT_MIN}; - Clause::Vertices from_; - Clause::Vertices to_; - Clause::Over over_; - Clause::Step step_; - Clause::Where where_; - bool shortest_{false}; - std::unique_ptr<InterimResult> inputs_; - using SchemaPropIndex = std::unordered_map<std::pair<std::string, std::string>, int64_t>; - SchemaPropIndex srcTagProps_; - SchemaPropIndex dstTagProps_; - std::unordered_map<EdgeType, std::string> edgeTypeNameMap_; - std::unique_ptr<folly::Promise<folly::Unit>> fPro_; - std::unique_ptr<folly::Promise<folly::Unit>> tPro_; - Status fStatus_; - Status tStatus_; - std::unordered_set<VertexID> targetNotFound_; - using StepOutHolder = std::unordered_set<std::unique_ptr<StepOut>>; - StepOutHolder stepOutHolder_; - // next step starting vertices - std::unordered_set<VertexID> visitedFrom_; - std::unordered_set<VertexID> visitedTo_; - // next step starting vertices - std::vector<VertexID> fromVids_; - std::vector<VertexID> toVids_; - // frontiers of vertices - std::pair<VisitedBy, Frontiers> fromFrontiers_; - std::pair<VisitedBy, Frontiers> toFrontiers_; - // interim path - std::multimap<VertexID, Path> pathFrom_; - std::multimap<VertexID, Path> pathTo_; - // final path(shortest or all) - std::multimap<VertexID, Path> finalPath_; - uint64_t currentStep_{1}; - uint64_t steps_{0}; -}; -} // namespace graph -} // namespace nebula -#endif diff --git a/src/executor/GoExecutor.cpp b/src/executor/GoExecutor.cpp deleted file mode 100644 index 28722e8746770fe4502d3315b14e39d1bd66b5bd..0000000000000000000000000000000000000000 --- a/src/executor/GoExecutor.cpp +++ /dev/null @@ -1,1367 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/GoExecutor.h" -#include "graph/SchemaHelper.h" -#include "dataman/RowReader.h" -#include "dataman/RowSetReader.h" -#include "dataman/ResultSchemaProvider.h" - - -namespace nebula { -namespace graph { - -using SchemaProps = std::unordered_map<std::string, std::vector<std::string>>; -using nebula::cpp2::SupportedType; - -GoExecutor::GoExecutor(Sentence *sentence, ExecutionContext *ectx) : TraverseExecutor(ectx) { - // The RTTI is guaranteed by Sentence::Kind, - // so we use `static_cast' instead of `dynamic_cast' for the sake of efficiency. - sentence_ = static_cast<GoSentence*>(sentence); -} - - -Status GoExecutor::prepare() { - return Status::OK(); -} - - -Status GoExecutor::prepareClauses() { - DCHECK(sentence_ != nullptr); - Status status; - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - status = prepareStep(); - if (!status.ok()) { - break; - } - status = prepareFrom(); - if (!status.ok()) { - break; - } - status = prepareOver(); - if (!status.ok()) { - break; - } - status = prepareWhere(); - if (!status.ok()) { - break; - } - status = prepareYield(); - if (!status.ok()) { - break; - } - status = prepareNeededProps(); - if (!status.ok()) { - break; - } - status = prepareDistinct(); - if (!status.ok()) { - break; - } - } while (false); - - if (!status.ok()) { - LOG(ERROR) << "Preparing failed: " << status; - return status; - } - - return status; -} - - -void GoExecutor::execute() { - FLOG_INFO("Executing Go: %s", sentence_->toString().c_str()); - auto status = prepareClauses(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getGoStats()); - return; - } - - status = setupStarts(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getGoStats()); - return; - } - if (starts_.empty()) { - onEmptyInputs(); - return; - } - if (distinct_) { - std::unordered_set<VertexID> uniqID; - for (auto id : starts_) { - uniqID.emplace(id); - } - starts_ = std::vector<VertexID>(uniqID.begin(), uniqID.end()); - } - stepOut(); -} - - -void GoExecutor::feedResult(std::unique_ptr<InterimResult> result) { - inputs_ = std::move(result); -} - - -Status GoExecutor::prepareStep() { - auto *clause = sentence_->stepClause(); - if (clause != nullptr) { - steps_ = clause->steps(); - upto_ = clause->isUpto(); - } - - if (isUpto()) { - return Status::Error("`UPTO' not supported yet"); - } - - if (steps_ != 1) { - backTracker_ = std::make_unique<VertexBackTracker>(); - } - - return Status::OK(); -} - - -Status GoExecutor::prepareFrom() { - Status status = Status::OK(); - auto *clause = sentence_->fromClause(); - do { - if (clause == nullptr) { - LOG(FATAL) << "From clause shall never be null"; - } - - if (clause->isRef()) { - auto *expr = clause->ref(); - if (expr->isInputExpression()) { - fromType_ = kPipe; - auto *iexpr = static_cast<InputPropertyExpression*>(expr); - colname_ = iexpr->prop(); - } else if (expr->isVariableExpression()) { - fromType_ = kVariable; - auto *vexpr = static_cast<VariablePropertyExpression*>(expr); - varname_ = vexpr->alias(); - colname_ = vexpr->prop(); - } else { - // No way to happen except memory corruption - LOG(FATAL) << "Unknown kind of expression"; - } - - if (colname_ != nullptr && *colname_ == "*") { - status = Status::Error("Can not use `*' to reference a vertex id column."); - break; - } - break; - } - - auto space = ectx()->rctx()->session()->space(); - expCtx_->setSpace(space); - auto vidList = clause->vidList(); - for (auto *expr : vidList) { - expr->setContext(expCtx_.get()); - - status = expr->prepare(); - if (!status.ok()) { - break; - } - auto value = expr->eval(); - if (!value.ok()) { - status = Status::Error(); - break; - } - if (expr->isFunCallExpression()) { - auto *funcExpr = static_cast<FunctionCallExpression*>(expr); - if (*(funcExpr->name()) == "near") { - auto v = Expression::asString(value.value()); - std::vector<VertexID> result; - folly::split(",", v, result, true); - starts_.insert(starts_.end(), - std::make_move_iterator(result.begin()), - std::make_move_iterator(result.end())); - continue; - } - } - auto v = value.value(); - if (!Expression::isInt(v)) { - status = Status::Error("Vertex ID should be of type integer"); - break; - } - starts_.push_back(Expression::asInt(v)); - } - fromType_ = kInstantExpr; - if (!status.ok()) { - break; - } - } while (false); - return status; -} - -Status GoExecutor::prepareOverAll() { - auto spaceId = ectx()->rctx()->session()->space(); - auto edgeAllStatus = ectx()->schemaManager()->getAllEdge(spaceId); - - if (!edgeAllStatus.ok()) { - return edgeAllStatus.status(); - } - - auto allEdge = edgeAllStatus.value(); - for (auto &e : allEdge) { - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId, e); - if (!edgeStatus.ok()) { - return edgeStatus.status(); - } - - auto v = edgeStatus.value(); - edgeTypes_.push_back(v); - - if (!expCtx_->addEdge(e, v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", e)); - } - } - - return Status::OK(); -} - -Status GoExecutor::prepareOver() { - Status status = Status::OK(); - auto *clause = sentence_->overClause(); - if (clause == nullptr) { - LOG(FATAL) << "Over clause shall never be null"; - } - - isReversely_ = clause->isReversely(); - - if (isReversely()) { - edgeHolder_ = std::make_unique<EdgeHolder>(); - } - - auto edges = clause->edges(); - for (auto e : edges) { - if (e->isOverAll()) { - expCtx_->setOverAllEdge(); - return prepareOverAll(); - } - - auto spaceId = ectx()->rctx()->session()->space(); - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId, *e->edge()); - if (!edgeStatus.ok()) { - return edgeStatus.status(); - } - - auto v = edgeStatus.value(); - if (isReversely()) { - v = -v; - } - edgeTypes_.push_back(v); - - if (e->alias() != nullptr) { - if (!expCtx_->addEdge(*e->alias(), v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", *e->alias())); - } - } else { - if (!expCtx_->addEdge(*e->edge(), v)) { - return Status::Error(folly::sformat("edge alias({}) was dup", *e->edge())); - } - } - } - - return status; -} - - -Status GoExecutor::prepareWhere() { - auto *clause = sentence_->whereClause(); - if (clause != nullptr) { - filter_ = clause->filter(); - } - return Status::OK(); -} - - -Status GoExecutor::prepareYield() { - auto *clause = sentence_->yieldClause(); - // this preparation depends on interim result, - // it can only be called after getting results of the previous executor, - // but if we can do the semantic analysis before execution, - // then we can do the preparation before execution - // TODO: make it possible that this preparation not depends on interim result - if (clause != nullptr) { - yieldClauseWrapper_ = std::make_unique<YieldClauseWrapper>(clause); - auto *varHolder = ectx()->variableHolder(); - auto status = yieldClauseWrapper_->prepare(inputs_.get(), varHolder, yields_); - if (!status.ok()) { - return status; - } - for (auto *col : yields_) { - if (!col->getFunName().empty()) { - return Status::SyntaxError("Do not support in aggregated query without group by"); - } - } - } - return Status::OK(); -} - - -Status GoExecutor::prepareNeededProps() { - auto status = Status::OK(); - do { - if (filter_ != nullptr) { - filter_->setContext(expCtx_.get()); - status = filter_->prepare(); - if (!status.ok()) { - break; - } - } - - for (auto *col : yields_) { - col->expr()->setContext(expCtx_.get()); - status = col->expr()->prepare(); - if (!status.ok()) { - break; - } - } - if (!status.ok()) { - break; - } - - if (expCtx_->hasVariableProp()) { - if (fromType_ != kVariable) { - status = Status::Error("A variable must be referred in FROM " - "before used in WHERE or YIELD"); - break; - } - auto &variables = expCtx_->variables(); - if (variables.size() > 1) { - status = Status::Error("Only one variable allowed to use"); - break; - } - auto &var = *variables.begin(); - if (var != *varname_) { - status = Status::Error("Variable name not match: `%s' vs. `%s'", - var.c_str(), varname_->c_str()); - break; - } - } - - if (expCtx_->hasInputProp()) { - if (fromType_ != kPipe) { - status = Status::Error("`$-' must be referred in FROM " - "before used in WHERE or YIELD"); - break; - } - } - - auto &tagMap = expCtx_->getTagMap(); - auto spaceId = ectx()->rctx()->session()->space(); - for (auto &entry : tagMap) { - auto tagId = ectx()->schemaManager()->toTagID(spaceId, entry.first); - if (!tagId.ok()) { - status == Status::Error("Tag `%s' not found.", entry.first.c_str()); - break; - } - entry.second = tagId.value(); - } - } while (false); - - return status; -} - - -Status GoExecutor::prepareDistinct() { - auto *clause = sentence_->yieldClause(); - if (clause != nullptr) { - distinct_ = clause->isDistinct(); - // TODO Consider distinct pushdown later, depends on filter and some other clause pushdown. - distinctPushDown_ = - !((expCtx_->hasSrcTagProp() || expCtx_->hasEdgeProp()) && expCtx_->hasDstTagProp()); - } - return Status::OK(); -} - - -Status GoExecutor::setupStarts() { - // Literal vertex ids - if (!starts_.empty()) { - return Status::OK(); - } - const auto *inputs = inputs_.get(); - // Take one column from a variable - if (varname_ != nullptr) { - bool existing = false; - auto *varInputs = ectx()->variableHolder()->get(*varname_, &existing); - if (varInputs == nullptr && !existing) { - return Status::Error("Variable `%s' not defined", varname_->c_str()); - } - DCHECK(inputs == nullptr); - inputs = varInputs; - } - // No error happened, but we are having empty inputs - if (inputs == nullptr || !inputs->hasData()) { - return Status::OK(); - } - - auto result = inputs->getVIDs(*colname_); - if (!result.ok()) { - LOG(ERROR) << "Get vid fail: " << *colname_; - return std::move(result).status(); - } - starts_ = std::move(result).value(); - - auto indexResult = inputs->buildIndex(*colname_); - if (!indexResult.ok()) { - return std::move(indexResult).status(); - } - index_ = std::move(indexResult).value(); - return Status::OK(); -} - - -void GoExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - } - resp = std::move(*resp_); -} - - -void GoExecutor::stepOut() { - auto spaceId = ectx()->rctx()->session()->space(); - auto status = getStepOutProps(); - if (!status.ok()) { - doError(Status::Error("Get step out props failed"), - ectx()->getGraphStats()->getGoStats()); - return; - } - auto returns = status.value(); - auto future = ectx()->getStorageClient()->getNeighbors(spaceId, - starts_, - edgeTypes_, - "", - std::move(returns)); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&result) { - auto completeness = result.completeness(); - if (completeness == 0) { - doError(Status::Error("Get neighbors failed"), ectx()->getGraphStats()->getGoStats()); - return; - } else if (completeness != 100) { - // TODO(dutor) We ought to let the user know that the execution was partially - // performed, even in the case that this happened in the intermediate process. - // Or, make this case configurable at runtime. - // For now, we just do some logging and keep going. - LOG(INFO) << "Get neighbors partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - onStepOutResponse(std::move(result)); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Exeception when handle out-bounds/in-bounds."), - ectx()->getGraphStats()->getGoStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void GoExecutor::onStepOutResponse(RpcResponse &&rpcResp) { - if (isFinalStep()) { - maybeFinishExecution(std::move(rpcResp)); - return; - } else { - starts_ = getDstIdsFromResp(rpcResp); - if (starts_.empty()) { - onEmptyInputs(); - return; - } - curStep_++; - stepOut(); - } -} - - -void GoExecutor::maybeFinishExecution(RpcResponse &&rpcResp) { - auto requireDstProps = expCtx_->hasDstTagProp(); - auto requireEdgeProps = !expCtx_->aliasProps().empty(); - - // Non-reversely traversal, no properties required on destination nodes - // Or, Reversely traversal but no properties on edge and destination nodes required. - // Note that the `dest` which used in reversely traversal means the `src` in foword edge. - if ((!requireDstProps && !isReversely()) || - (isReversely() && !requireDstProps && !requireEdgeProps)) { - finishExecution(std::move(rpcResp)); - return; - } - - auto dstids = getDstIdsFromResp(rpcResp); - - // Reaching the dead end - if (dstids.empty()) { - onEmptyInputs(); - return; - } - - // Only properties on destination nodes required - if (!isReversely() || (requireDstProps && !requireEdgeProps)) { - fetchVertexProps(std::move(dstids), std::move(rpcResp)); - return; - } - - // Reversely traversal - DCHECK(isReversely()); - - std::unordered_map<EdgeType, std::vector<storage::cpp2::EdgeKey>> edgeKeysMapping; - std::unordered_map<EdgeType, std::vector<storage::cpp2::PropDef>> edgePropsMapping; - - // TODO: There would be no need to fetch edges' props here, - // if we implemnet the feature that keep all the props in the reverse edge. - for (auto &resp : rpcResp.responses()) { - auto *vertices = resp.get_vertices(); - if (vertices == nullptr) { - continue; - } - auto *eschema = resp.get_edge_schema(); - if (eschema == nullptr) { - continue; - } - std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> schemas; - std::transform(eschema->cbegin(), eschema->cend(), std::inserter(schemas, schemas.begin()), - [] (auto &s) { - return std::make_pair(s.first, std::make_shared<ResultSchemaProvider>(s.second)); - }); - - for (auto &vdata : *vertices) { - for (auto &edge : vdata.edge_data) { - RowSetReader rsReader(schemas[edge.type], edge.data); - auto iter = rsReader.begin(); - while (iter) { - VertexID dst; - EdgeRanking rank; - auto rc = iter->getVid(kDst, dst); - if (rc != ResultType::SUCCEEDED) { - doError(Status::Error("Get dst error when go reversely."), - ectx()->getGraphStats()->getGoStats()); - return; - } - rc = iter->getVid(kRank, rank); - if (rc != ResultType::SUCCEEDED) { - doError(Status::Error("Get rank error when go reversely."), - ectx()->getGraphStats()->getGoStats()); - return; - } - auto type = edge.type > 0 ? edge.type : -edge.type; - auto &edgeKeys = edgeKeysMapping[type]; - edgeKeys.emplace_back(); - edgeKeys.back().set_src(dst); - edgeKeys.back().set_dst(vdata.get_vertex_id()); - edgeKeys.back().set_ranking(rank); - edgeKeys.back().set_edge_type(type); - ++iter; - } - } - } - } - - for (auto &prop : expCtx_->aliasProps()) { - EdgeType edgeType; - if (!expCtx_->getEdgeType(prop.first, edgeType)) { - doError(Status::Error("No schema found for `%s'", prop.first.c_str()), - ectx()->getGraphStats()->getGoStats()); - return; - } - - edgeType = edgeType > 0 ? edgeType : -edgeType; - - auto &edgeProps = edgePropsMapping[edgeType]; - edgeProps.emplace_back(); - edgeProps.back().owner = storage::cpp2::PropOwner::EDGE; - edgeProps.back().name = prop.second; - edgeProps.back().id.set_edge_type(edgeType); - } - - using EdgePropResponse = storage::StorageRpcResponse<storage::cpp2::EdgePropResponse>; - std::vector<folly::SemiFuture<EdgePropResponse>> futures; - - auto spaceId = ectx()->rctx()->session()->space(); - auto *runner = ectx()->rctx()->runner(); - - for (auto &pair : edgeKeysMapping) { - auto *storage = ectx()->getStorageClient(); - auto future = storage->getEdgeProps(spaceId, - pair.second, - edgePropsMapping[pair.first]); - futures.emplace_back(std::move(future)); - } - - auto cb = [this, stepResp = std::move(rpcResp), - dstids = std::move(dstids)] (auto &&result) mutable { - for (auto &t : result) { - if (t.hasException()) { - LOG(ERROR) << "Exception caught: " << t.exception().what(); - doError(Status::Error("Exeception when get edge props in reversely traversal."), - ectx()->getGraphStats()->getGoStats()); - return; - } - auto resp = std::move(t).value(); - for (auto &edgePropResp : resp.responses()) { - auto status = edgeHolder_->add(edgePropResp); - if (!status.ok()) { - LOG(ERROR) << "Error when handle edges: " << status; - doError(std::move(status), ectx()->getGraphStats()->getGoStats()); - return; - } - } - } - - if (expCtx_->hasDstTagProp()) { - fetchVertexProps(std::move(dstids), std::move(stepResp)); - return; - } - - finishExecution(std::move(stepResp)); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Exception when handle edges."), - ectx()->getGraphStats()->getGoStats()); - }; - - folly::collectAll(std::move(futures)).via(runner).thenValue(cb).thenError(error); -} - - -void GoExecutor::onVertexProps(RpcResponse &&rpcResp) { - UNUSED(rpcResp); -} - -std::vector<std::string> GoExecutor::getEdgeNamesFromResp(RpcResponse &rpcResp) const { - std::vector<std::string> names; - auto spaceId = ectx()->rctx()->session()->space(); - auto &resp = rpcResp.responses(); - auto *edgeSchema = resp[0].get_edge_schema(); - if (edgeSchema == nullptr) { - return names; - } - - for (auto &schema : *edgeSchema) { - auto edgeType = schema.first; - auto status = ectx()->schemaManager()->toEdgeName(spaceId, edgeType); - DCHECK(status.ok()); - auto edgeName = status.value(); - names.emplace_back(std::move(edgeName)); - } - - return names; -} - -std::vector<VertexID> GoExecutor::getDstIdsFromResp(RpcResponse &rpcResp) const { - std::unordered_set<VertexID> set; - for (auto &resp : rpcResp.responses()) { - auto *vertices = resp.get_vertices(); - if (vertices == nullptr) { - continue; - } - - auto *eschema = resp.get_edge_schema(); - if (eschema == nullptr) { - continue; - } - std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> schema; - - std::transform(eschema->cbegin(), eschema->cend(), std::inserter(schema, schema.begin()), - [](auto &s) { - return std::make_pair( - s.first, std::make_shared<ResultSchemaProvider>(s.second)); - }); - - for (auto &vdata : *vertices) { - for (auto &edata : vdata.edge_data) { - auto it = schema.find(edata.type); - DCHECK(it != schema.end()); - RowSetReader rsReader(it->second, edata.data); - auto iter = rsReader.begin(); - while (iter) { - VertexID dst; - auto rc = iter->getVid(kDst, dst); - CHECK(rc == ResultType::SUCCEEDED); - if (!isFinalStep() && backTracker_ != nullptr) { - backTracker_->add(vdata.get_vertex_id(), dst); - } - set.emplace(dst); - ++iter; - } - } - } - } - return std::vector<VertexID>(set.begin(), set.end()); -} - -void GoExecutor::finishExecution(RpcResponse &&rpcResp) { - // MayBe we can do better. - std::vector<std::unique_ptr<YieldColumn>> yc; - if (expCtx_->isOverAllEdge() && yields_.empty()) { - auto edgeNames = getEdgeNamesFromResp(rpcResp); - if (edgeNames.empty()) { - doError(Status::Error("get edge name failed"), ectx()->getGraphStats()->getGoStats()); - return; - } - for (const auto &name : edgeNames) { - auto dummy = new std::string(name); - auto dummy_exp = new EdgeDstIdExpression(dummy); - auto ptr = std::make_unique<YieldColumn>(dummy_exp); - dummy_exp->setContext(expCtx_.get()); - yields_.emplace_back(ptr.get()); - yc.emplace_back(std::move(ptr)); - } - } - - std::unique_ptr<InterimResult> outputs; - if (!setupInterimResult(std::move(rpcResp), outputs)) { - return; - } - - if (onResult_) { - onResult_(std::move(outputs)); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(getResultColumnNames()); - if (outputs != nullptr && outputs->hasData()) { - auto ret = outputs->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - doError(std::move(ret).status(), ectx()->getGraphStats()->getGoStats()); - return; - } - resp_->set_rows(std::move(ret).value()); - } - } - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getGoStats()); -} - -StatusOr<std::vector<storage::cpp2::PropDef>> GoExecutor::getStepOutProps() { - std::vector<storage::cpp2::PropDef> props; - for (auto &e : edgeTypes_) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::EDGE; - pd.name = kDst; - pd.id.set_edge_type(e); - props.emplace_back(std::move(pd)); - // We need ranking when go reverly in final step, - // because we have to fetch the coresponding edges. - if (isReversely() && isFinalStep()) { - storage::cpp2::PropDef rankPd; - rankPd.owner = storage::cpp2::PropOwner::EDGE; - rankPd.name = kRank; - rankPd.id.set_edge_type(e); - props.emplace_back(std::move(rankPd)); - } - } - - if (!isFinalStep()) { - return props; - } - - auto spaceId = ectx()->rctx()->session()->space(); - for (auto &tagProp : expCtx_->srcTagProps()) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::SOURCE; - pd.name = tagProp.second; - auto status = ectx()->schemaManager()->toTagID(spaceId, tagProp.first); - if (!status.ok()) { - return Status::Error("No schema found for '%s'", tagProp.first.c_str()); - } - auto tagId = status.value(); - pd.id.set_tag_id(tagId); - props.emplace_back(std::move(pd)); - } - - if (isReversely()) { - return props; - } - - for (auto &prop : expCtx_->aliasProps()) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::EDGE; - pd.name = prop.second; - - EdgeType edgeType; - - if (!expCtx_->getEdgeType(prop.first, edgeType)) { - return Status::Error("the edge was not found '%s'", prop.first.c_str()); - } - pd.id.set_edge_type(edgeType); - props.emplace_back(std::move(pd)); - } - - return props; -} - - -StatusOr<std::vector<storage::cpp2::PropDef>> GoExecutor::getDstProps() { - std::vector<storage::cpp2::PropDef> props; - auto spaceId = ectx()->rctx()->session()->space(); - for (auto &tagProp : expCtx_->dstTagProps()) { - storage::cpp2::PropDef pd; - pd.owner = storage::cpp2::PropOwner::DEST; - pd.name = tagProp.second; - auto status = ectx()->schemaManager()->toTagID(spaceId, tagProp.first); - if (!status.ok()) { - return Status::Error("No schema found for '%s'", tagProp.first.c_str()); - } - auto tagId = status.value(); - pd.id.set_tag_id(tagId); - props.emplace_back(std::move(pd)); - } - return props; -} - - -void GoExecutor::fetchVertexProps(std::vector<VertexID> ids, RpcResponse &&rpcResp) { - auto spaceId = ectx()->rctx()->session()->space(); - auto status = getDstProps(); - if (!status.ok()) { - doError(Status::Error("Get dest props failed"), ectx()->getGraphStats()->getGoStats()); - return; - } - auto returns = status.value(); - auto future = ectx()->getStorageClient()->getVertexProps(spaceId, ids, returns); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this, stepOutResp = std::move(rpcResp)] (auto &&result) mutable { - auto completeness = result.completeness(); - if (completeness == 0) { - doError(Status::Error("Get dest props failed"), ectx()->getGraphStats()->getGoStats()); - return; - } else if (completeness != 100) { - LOG(INFO) << "Get neighbors partially failed: " << completeness << "%"; - for (auto &error : result.failedParts()) { - LOG(ERROR) << "part: " << error.first - << "error code: " << static_cast<int>(error.second); - } - } - if (vertexHolder_ == nullptr) { - vertexHolder_ = std::make_unique<VertexHolder>(); - } - for (auto &resp : result.responses()) { - vertexHolder_->add(resp); - } - finishExecution(std::move(stepOutResp)); - return; - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Exception when handle vertex props."), - ectx()->getGraphStats()->getGoStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -std::vector<std::string> GoExecutor::getResultColumnNames() const { - std::vector<std::string> result; - result.reserve(yields_.size()); - for (auto *col : yields_) { - if (col->alias() == nullptr) { - result.emplace_back(col->expr()->toString()); - } else { - result.emplace_back(*col->alias()); - } - } - return result; -} - - -bool GoExecutor::setupInterimResult(RpcResponse &&rpcResp, std::unique_ptr<InterimResult> &result) { - // Generic results - result = std::make_unique<InterimResult>(getResultColumnNames()); - std::shared_ptr<SchemaWriter> schema; - std::unique_ptr<RowSetWriter> rsWriter; - auto uniqResult = std::make_unique<std::unordered_set<std::string>>(); - auto cb = [&] (std::vector<VariantType> record, - std::vector<nebula::cpp2::SupportedType> colTypes) { - if (schema == nullptr) { - schema = std::make_shared<SchemaWriter>(); - auto colnames = getResultColumnNames(); - if (record.size() != colTypes.size()) { - LOG(FATAL) << "data nums: " << record.size() - << " != type nums: " << colTypes.size(); - } - for (auto i = 0u; i < record.size(); i++) { - SupportedType type; - if (colTypes[i] == SupportedType::UNKNOWN) { - switch (record[i].which()) { - case VAR_INT64: - // all integers in InterimResult are regarded as type of INT - type = SupportedType::INT; - break; - case VAR_DOUBLE: - type = SupportedType::DOUBLE; - break; - case VAR_BOOL: - type = SupportedType::BOOL; - break; - case VAR_STR: - type = SupportedType::STRING; - break; - default: - LOG(FATAL) << "Unknown VariantType: " << record[i].which(); - } - } else { - type = colTypes[i]; - } - schema->appendCol(colnames[i], type); - } // for - rsWriter = std::make_unique<RowSetWriter>(schema); - } // if - - RowWriter writer(schema); - for (auto &column : record) { - switch (column.which()) { - case VAR_INT64: - writer << boost::get<int64_t>(column); - break; - case VAR_DOUBLE: - writer << boost::get<double>(column); - break; - case VAR_BOOL: - writer << boost::get<bool>(column); - break; - case VAR_STR: - writer << boost::get<std::string>(column); - break; - default: - LOG(FATAL) << "Unknown VariantType: " << column.which(); - } - } - // TODO Consider float/double, and need to reduce mem copy. - std::string encode = writer.encode(); - if (distinct_) { - auto ret = uniqResult->emplace(encode); - if (ret.second) { - rsWriter->addRow(std::move(encode)); - } - } else { - rsWriter->addRow(std::move(encode)); - } - }; // cb - if (!processFinalResult(rpcResp, cb)) { - return false; - } - - if (rsWriter != nullptr) { - result->setInterim(std::move(rsWriter)); - } - return true; -} - - -void GoExecutor::onEmptyInputs() { - auto resultColNames = getResultColumnNames(); - auto outputs = std::make_unique<InterimResult>(std::move(resultColNames)); - if (onResult_) { - onResult_(std::move(outputs)); - } else if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - } - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getGoStats()); -} - - -bool GoExecutor::processFinalResult(RpcResponse &rpcResp, Callback cb) const { - auto all = rpcResp.responses(); - auto spaceId = ectx()->rctx()->session()->space(); - for (auto &resp : all) { - if (resp.get_vertices() == nullptr) { - continue; - } - - std::unordered_map<TagID, std::shared_ptr<ResultSchemaProvider>> tagSchema; - auto *vschema = resp.get_vertex_schema(); - if (vschema != nullptr) { - std::transform(vschema->cbegin(), vschema->cend(), - std::inserter(tagSchema, tagSchema.begin()), [](auto &schema) { - return std::make_pair( - schema.first, - std::make_shared<ResultSchemaProvider>(schema.second)); - }); - } - - std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> edgeSchema; - auto *eschema = resp.get_edge_schema(); - if (eschema != nullptr) { - std::transform(eschema->cbegin(), eschema->cend(), - std::inserter(edgeSchema, edgeSchema.begin()), [](auto &schema) { - return std::make_pair( - schema.first, - std::make_shared<ResultSchemaProvider>(schema.second)); - }); - } - - if (tagSchema.empty() && edgeSchema.empty()) { - continue; - } - - for (auto &vdata : resp.vertices) { - DCHECK(vdata.__isset.edge_data); - auto tagData = vdata.get_tag_data(); - for (auto &edata : vdata.edge_data) { - auto it = edgeSchema.find(edata.type); - DCHECK(it != edgeSchema.end()); - RowSetReader rsReader(it->second, edata.data); - auto iter = rsReader.begin(); - auto edgeType = edata.type; - while (iter) { - std::vector<SupportedType> colTypes; - bool saveTypeFlag = false; - auto &getters = expCtx_->getters(); - getters.getAliasProp = [&iter, - &spaceId, - &edgeType, - &saveTypeFlag, - &colTypes, - &edgeSchema, - srcid = vdata.get_vertex_id(), - this](const std::string &edgeName, - const std::string &prop) -> OptVariantType { - EdgeType type; - auto found = expCtx_->getEdgeType(edgeName, type); - if (!found) { - return Status::Error( - "Get edge type for `%s' failed in getters.", edgeName.c_str()); - } - - if (isReversely()) { - auto dst = RowReader::getPropByName(&*iter, kDst); - if (saveTypeFlag) { - colTypes.back() = edgeHolder_->getType( - boost::get<VertexID>(value(dst)), - srcid, - edgeType > 0 ? edgeType : -edgeType, prop); - } - if (edgeType != type && edgeType != -type) { - return edgeHolder_->getDefaultProp(-type, prop); - } - return edgeHolder_->get(boost::get<VertexID>(value(dst)), - srcid, - edgeType > 0 ? edgeType : -edgeType, prop); - } else { - if (saveTypeFlag) { - colTypes.back() = iter->getSchema()->getFieldType(prop).type; - } - if (edgeType != type && edgeType != -type) { - auto sit = edgeSchema.find(type); - if (sit == edgeSchema.end()) { - return Status::Error("get schema failed"); - } - return RowReader::getDefaultProp(sit->second.get(), prop); - } - auto res = RowReader::getPropByName(&*iter, prop); - if (!ok(res)) { - return Status::Error( - folly::sformat("get prop({}.{}) failed", edgeName, prop)); - } - - return value(std::move(res)); - } - }; - getters.getSrcTagProp = - [&iter, &spaceId, &tagData, &tagSchema, &saveTypeFlag, &colTypes, this]( - const std::string &tag, const std::string &prop) -> OptVariantType { - TagID tagId; - auto found = expCtx_->getTagId(tag, tagId); - if (!found) { - return Status::Error( - "Get tag id for `%s' failed in getters.", tag.c_str()); - } - - auto it2 = - std::find_if(tagData.cbegin(), tagData.cend(), [&tagId](auto &td) { - if (td.tag_id == tagId) { - return true; - } - - return false; - }); - - if (it2 == tagData.cend()) { - return RowReader::getDefaultProp(iter->getSchema().get(), prop); - } - - if (saveTypeFlag) { - colTypes.back() = tagSchema[tagId]->getFieldType(prop).type; - } - DCHECK(it2->__isset.data); - auto vreader = RowReader::getRowReader(it2->data, tagSchema[tagId]); - auto res = RowReader::getPropByName(vreader.get(), prop); - if (!ok(res)) { - return Status::Error( - folly::sformat("get prop({}.{}) failed", tag, prop)); - } - return value(res); - }; - getters.getDstTagProp = [&iter, &spaceId, &saveTypeFlag, &colTypes, this]( - const std::string &tag, - const std::string &prop) -> OptVariantType { - auto dst = RowReader::getPropByName(&*iter, "_dst"); - if (!ok(dst)) { - return Status::Error( - folly::sformat("get prop({}.{}) failed", tag, prop)); - } - auto vid = boost::get<int64_t>(value(std::move(dst))); - - TagID tagId; - auto found = expCtx_->getTagId(tag, tagId); - if (!found) { - return Status::Error( - "Get tag id for `%s' failed in getters.", tag.c_str()); - } - - if (saveTypeFlag) { - SupportedType type = vertexHolder_->getType(vid, tagId, prop); - colTypes.back() = type; - } - return vertexHolder_->get(vid, tagId, prop); - }; - getters.getVariableProp = [&saveTypeFlag, &colTypes, &vdata, - this](const std::string &prop) { - if (saveTypeFlag) { - colTypes.back() = getPropTypeFromInterim(prop); - } - return getPropFromInterim(vdata.get_vertex_id(), prop); - }; - getters.getInputProp = [&saveTypeFlag, &colTypes, &vdata, - this](const std::string &prop) { - if (saveTypeFlag) { - colTypes.back() = getPropTypeFromInterim(prop); - } - return getPropFromInterim(vdata.get_vertex_id(), prop); - }; - - // Evaluate filter - if (filter_ != nullptr) { - auto value = filter_->eval(); - if (!value.ok()) { - doError(std::move(value).status(), - ectx()->getGraphStats()->getGoStats()); - return false; - } - if (!Expression::asBool(value.value())) { - ++iter; - continue; - } - } - std::vector<VariantType> record; - record.reserve(yields_.size()); - saveTypeFlag = true; - for (auto *column : yields_) { - colTypes.emplace_back(SupportedType::UNKNOWN); - auto *expr = column->expr(); - auto value = expr->eval(); - if (!value.ok()) { - doError(std::move(value).status(), - ectx()->getGraphStats()->getGoStats()); - return false; - } - if (column->expr()->isTypeCastingExpression()) { - auto exprPtr = static_cast<TypeCastingExpression *>(column->expr()); - colTypes.back() = SchemaHelper::columnTypeToSupportedType( - exprPtr->getType()); - } - record.emplace_back(std::move(value.value())); - } - cb(std::move(record), std::move(colTypes)); - ++iter; - } // while `iter' - } - } // for `vdata' - } // for `resp' - return true; -} - -OptVariantType GoExecutor::VertexHolder::getDefaultProp(TagID tid, const std::string &prop) const { - for (auto it = data_.cbegin(); it != data_.cend(); ++it) { - auto it2 = it->second.find(tid); - if (it2 != it->second.cend()) { - return RowReader::getDefaultProp(std::get<0>(it2->second).get(), prop); - } - } - - return Status::Error("Unknown Vertex"); -} - -SupportedType GoExecutor::VertexHolder::getDefaultPropType(TagID tid, - const std::string &prop) const { - for (auto it = data_.cbegin(); it != data_.cend(); ++it) { - auto it2 = it->second.find(tid); - if (it2 != it->second.cend()) { - return std::get<0>(it2->second)->getFieldType(prop).type; - } - } - - return nebula::cpp2::SupportedType::UNKNOWN; -} - -OptVariantType GoExecutor::VertexHolder::get(VertexID id, TagID tid, - const std::string &prop) const { - auto iter = data_.find(id); - if (iter == data_.end()) { - return getDefaultProp(tid, prop); - } - - auto iter2 = iter->second.find(tid); - if (iter2 == iter->second.end()) { - return getDefaultProp(tid, prop); - } - - auto reader = RowReader::getRowReader(std::get<1>(iter2->second), std::get<0>(iter2->second)); - - auto res = RowReader::getPropByName(reader.get(), prop); - if (!ok(res)) { - return Status::Error(folly::sformat("get prop({}) failed", prop)); - } - return value(std::move(res)); -} - -SupportedType GoExecutor::VertexHolder::getType(VertexID id, TagID tid, const std::string &prop) { - auto iter = data_.find(id); - if (iter == data_.end()) { - return getDefaultPropType(tid, prop); - } - - auto iter2 = iter->second.find(tid); - if (iter2 == iter->second.end()) { - return getDefaultPropType(tid, prop); - } - - return std::get<0>(iter2->second)->getFieldType(prop).type; -} - -void GoExecutor::VertexHolder::add(const storage::cpp2::QueryResponse &resp) { - auto *vertices = resp.get_vertices(); - if (vertices == nullptr) { - return; - } - - auto *vertexSchema = resp.get_vertex_schema(); - if (vertexSchema == nullptr) { - return; - } - for (auto &vdata : *vertices) { - std::unordered_map<TagID, VData> m; - for (auto &td : vdata.tag_data) { - DCHECK(td.__isset.data); - auto it = vertexSchema->find(td.tag_id); - DCHECK(it != vertexSchema->end()); - m[td.tag_id] = {std::make_shared<ResultSchemaProvider>(it->second), td.data}; - } - data_[vdata.vertex_id] = std::move(m); - } -} - - -Status GoExecutor::EdgeHolder::add(const storage::cpp2::EdgePropResponse &resp) { - if (resp.get_schema() == nullptr || - resp.get_data() == nullptr || - resp.get_data()->empty()) { - return Status::OK(); - } - - auto eschema = std::make_shared<ResultSchemaProvider>(*resp.get_schema()); - RowSetReader rsReader(eschema, *resp.get_data()); - auto collector = std::make_unique<Collector>(); - auto iter = rsReader.begin(); - while (iter) { - auto src = collector->getProp(eschema.get(), kSrc, &*iter); - auto dst = collector->getProp(eschema.get(), kDst, &*iter); - auto type = collector->getProp(eschema.get(), kType, &*iter); - if (!src.ok() || !dst.ok() || !type.ok()) { - ++iter; - continue; - } - EdgeKey key; - std::get<0>(key) = boost::get<int64_t>(src.value()); - std::get<1>(key) = boost::get<int64_t>(dst.value()); - std::get<2>(key) = boost::get<int64_t>(type.value()); - RowWriter rWriter(eschema); - auto fields = iter->numFields(); - for (auto i = 0; i < fields; i++) { - auto result = RowReader::getPropByIndex(&*iter, i); - if (!ok(result)) { - return Status::Error("Get prop failed when add edge."); - } - collector->collect(value(result), &rWriter); - } - edges_.emplace(key, std::make_pair(eschema, rWriter.encode())); - schemas_.emplace(boost::get<int64_t>(type.value()), eschema); - ++iter; - } - - return Status::OK(); -} - - -OptVariantType GoExecutor::EdgeHolder::get(VertexID src, - VertexID dst, - EdgeType type, - const std::string &prop) const { - auto iter = edges_.find(std::make_tuple(src, dst, type)); - CHECK(iter != edges_.end()); - auto reader = RowReader::getRowReader(iter->second.second, iter->second.first); - auto result = RowReader::getPropByName(reader.get(), prop); - if (!ok(result)) { - return Status::Error("Prop not found: `%s'", prop.c_str()); - } - return value(result); -} - - -SupportedType GoExecutor::EdgeHolder::getType(VertexID src, - VertexID dst, - EdgeType type, - const std::string &prop) const { - auto iter = edges_.find(std::make_tuple(src, dst, type)); - CHECK(iter != edges_.end()); - return iter->second.first->getFieldType(prop).type; -} - - -OptVariantType GoExecutor::EdgeHolder::getDefaultProp(EdgeType type, - const std::string &prop) { - auto sit = schemas_.find(type); - if (sit == schemas_.end()) { - return Status::Error("Get default prop failed in reversely traversal."); - } - - return RowReader::getDefaultProp(sit->second.get(), prop); -} - - -OptVariantType GoExecutor::getPropFromInterim(VertexID id, const std::string &prop) const { - auto rootId = id; - if (backTracker_ != nullptr) { - DCHECK_NE(steps_ , 1u); - rootId = backTracker_->get(id); - } - DCHECK(index_ != nullptr); - return index_->getColumnWithVID(rootId, prop); -} - - -SupportedType GoExecutor::getPropTypeFromInterim(const std::string &prop) const { - DCHECK(index_ != nullptr); - return index_->getColumnType(prop); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/GoExecutor.h b/src/executor/GoExecutor.h deleted file mode 100644 index f232119b45b8821bebdbe8fe9ce260f03f341546..0000000000000000000000000000000000000000 --- a/src/executor/GoExecutor.h +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_GOEXECUTOR_H_ -#define GRAPH_GOEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "storage/client/StorageClient.h" - -namespace nebula { - -namespace storage { -namespace cpp2 { -class QueryResponse; -} // namespace cpp2 -} // namespace storage - -namespace graph { - -class GoExecutor final : public TraverseExecutor { -public: - GoExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "GoExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - /** - * To do some preparing works on the clauses - */ - Status prepareClauses(); - - Status prepareStep(); - - Status prepareFrom(); - - Status prepareOver(); - - Status prepareWhere(); - - Status prepareYield(); - - Status prepareNeededProps(); - - Status prepareDistinct(); - - Status prepareOverAll(); - - /** - * To check if this is the final step. - */ - bool isFinalStep() const { - return curStep_ == steps_; - } - - /** - * To check if `UPTO' is specified. - * If so, we are supposed to apply the filter in each step. - */ - bool isUpto() const { - return upto_; - } - - bool isReversely() const { - return isReversely_; - } - - /** - * To obtain the source ids from various places, - * such as the literal id list, inputs from the pipeline or results of variable. - */ - Status setupStarts(); - - /** - * To step out for one step. - */ - void stepOut(); - - using RpcResponse = storage::StorageRpcResponse<storage::cpp2::QueryResponse>; - /** - * Callback invoked upon the response of stepping out arrives. - */ - void onStepOutResponse(RpcResponse &&rpcResp); - - /** - * Callback invoked when the stepping out action reaches the dead end. - */ - void onEmptyInputs(); - - /** - * Callback invoked upon the response of retrieving terminal vertex arrives. - */ - void onVertexProps(RpcResponse &&rpcResp); - - StatusOr<std::vector<storage::cpp2::PropDef>> getStepOutProps(); - StatusOr<std::vector<storage::cpp2::PropDef>> getDstProps(); - - void fetchVertexProps(std::vector<VertexID> ids, RpcResponse &&rpcResp); - - void maybeFinishExecution(RpcResponse &&rpcResp); - - /** - * To retrieve or generate the column names for the execution result. - */ - std::vector<std::string> getResultColumnNames() const; - - /** - * To retrieve the dst ids from a stepping out response. - */ - std::vector<VertexID> getDstIdsFromResp(RpcResponse &rpcResp) const; - - /** - * get the edgeName from response when over all edges - */ - std::vector<std::string> getEdgeNamesFromResp(RpcResponse &rpcResp) const; - /** - * All required data have arrived, finish the execution. - */ - void finishExecution(RpcResponse &&rpcResp); - - /** - * To setup an intermediate representation of the execution result, - * which is about to be piped to the next executor. - */ - bool setupInterimResult(RpcResponse &&rpcResp, std::unique_ptr<InterimResult> &result); - - /** - * To setup the header of the execution result, i.e. the column names. - */ - void setupResponseHeader(cpp2::ExecutionResponse &resp) const; - - /** - * To setup the body of the execution result. - */ - bool setupResponseBody(RpcResponse &rpcResp, cpp2::ExecutionResponse &resp) const; - - /** - * To iterate on the final data collection, and evaluate the filter and yield columns. - * For each row that matches the filter, `cb' would be invoked. - */ - using Callback = std::function<void(std::vector<VariantType>, - std::vector<nebula::cpp2::SupportedType>)>; - bool processFinalResult(RpcResponse &rpcResp, Callback cb) const; - - /** - * A container to hold the mapping from vertex id to its properties, used for lookups - * during the final evaluation process. - */ - class VertexHolder final { - public: - OptVariantType getDefaultProp(TagID tid, const std::string &prop) const; - OptVariantType get(VertexID id, TagID tid, const std::string &prop) const; - void add(const storage::cpp2::QueryResponse &resp); - nebula::cpp2::SupportedType getDefaultPropType(TagID tid, const std::string &prop) const; - nebula::cpp2::SupportedType getType(VertexID id, TagID tid, const std::string &prop); - - private: - using VData = std::tuple<std::shared_ptr<ResultSchemaProvider>, std::string>; - std::unordered_map<VertexID, std::unordered_map<TagID, VData>> data_; - }; - - class VertexBackTracker final { - public: - void add(VertexID src, VertexID dst) { - VertexID value = src; - auto iter = mapping_.find(src); - if (iter != mapping_.end()) { - value = iter->second; - } - mapping_[dst] = value; - } - - VertexID get(VertexID id) { - auto iter = mapping_.find(id); - DCHECK(iter != mapping_.end()); - return iter->second; - } - - private: - std::unordered_map<VertexID, VertexID> mapping_; - }; - - class EdgeHolder final { - public: - Status add(const storage::cpp2::EdgePropResponse &resp); - OptVariantType get(VertexID src, - VertexID dst, - EdgeType type, - const std::string &prop) const; - nebula::cpp2::SupportedType getType(VertexID src, - VertexID dst, - EdgeType type, - const std::string &prop) const; - OptVariantType getDefaultProp(EdgeType type, - const std::string &prop); - - private: - using EdgeKey = std::tuple<VertexID, VertexID, EdgeType>; - using EdgeValue = std::pair<std::shared_ptr<ResultSchemaProvider>, std::string>; - std::unordered_map<EdgeKey, EdgeValue> edges_; - std::unordered_map<EdgeType, std::shared_ptr<ResultSchemaProvider>> schemas_; - }; - - OptVariantType getPropFromInterim(VertexID id, const std::string &prop) const; - - nebula::cpp2::SupportedType getPropTypeFromInterim(const std::string &prop) const; - - enum FromType { - kInstantExpr, - kVariable, - kPipe, - }; - -private: - GoSentence *sentence_{nullptr}; - FromType fromType_{kInstantExpr}; - uint32_t steps_{1}; - uint32_t curStep_{1}; - bool upto_{false}; - bool isReversely_{false}; - std::vector<EdgeType> edgeTypes_; - std::string *varname_{nullptr}; - std::string *colname_{nullptr}; - Expression *filter_{nullptr}; - std::vector<YieldColumn*> yields_; - std::unique_ptr<YieldClauseWrapper> yieldClauseWrapper_; - bool distinct_{false}; - bool distinctPushDown_{false}; - std::unique_ptr<InterimResult> inputs_; - using InterimIndex = InterimResult::InterimResultIndex; - std::unique_ptr<InterimIndex> index_; - std::unique_ptr<ExpressionContext> expCtx_; - std::vector<VertexID> starts_; - std::unique_ptr<VertexHolder> vertexHolder_; - std::unique_ptr<EdgeHolder> edgeHolder_; - std::unique_ptr<VertexBackTracker> backTracker_; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - // The name of Tag or Edge, index of prop in data - using SchemaPropIndex = std::unordered_map<std::pair<std::string, std::string>, int64_t>; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_GOEXECUTOR_H_ diff --git a/src/executor/GraphStats.h b/src/executor/GraphStats.h deleted file mode 100644 index fe50755ea0e580bb02ad521475a743d92395bd90..0000000000000000000000000000000000000000 --- a/src/executor/GraphStats.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_GRAPHSTATS_H -#define GRAPH_GRAPHSTATS_H - -#include "stats/StatsManager.h" -#include "stats/Stats.h" - -namespace nebula { -namespace graph { - -class GraphStats final { -public: - GraphStats() { - storageClientStats_ = std::make_unique<stats::Stats>("graph", "storageCliet"); - metaClientStats_ = std::make_unique<stats::Stats>("graph", "metaClient"); - graphAllStats_ = std::make_unique<stats::Stats>("graph", "graph_all"); - parseErrorStats_ = std::make_unique<stats::Stats>("graph", "parse_error"); - insertVStats_ = std::make_unique<stats::Stats>("graph", "insert_vertex"); - insertEStats_ = std::make_unique<stats::Stats>("graph", "insert_edge"); - deleteVStats_ = std::make_unique<stats::Stats>("graph", "delete_vertex"); - deleteEStats_ = std::make_unique<stats::Stats>("graph", "delete_edge"); - updateVStats_ = std::make_unique<stats::Stats>("graph", "update_vertex"); - updateEStats_ = std::make_unique<stats::Stats>("graph", "update_edge"); - goStats_ = std::make_unique<stats::Stats>("graph", "go"); - findPathStats_ = std::make_unique<stats::Stats>("graph", "find_path"); - fetchVStats_ = std::make_unique<stats::Stats>("graph", "fetch_vertex"); - fetchEStats_ = std::make_unique<stats::Stats>("graph", "fetch_edge"); - } - - ~GraphStats() = default; - -public: - stats::Stats* getStorageClientStats() const { return storageClientStats_.get(); } - stats::Stats* getMetaClientStats() const { return metaClientStats_.get(); } - stats::Stats* getGraphAllStats() const { return graphAllStats_.get(); } - stats::Stats* getParseErrorStats() const { return parseErrorStats_.get(); } - stats::Stats* getInsertVertexStats() const { return insertVStats_.get(); } - stats::Stats* getInsertEdgeStats() const { return insertEStats_.get(); } - stats::Stats* getDeleteVertexStats() const { return deleteVStats_.get(); } - stats::Stats* getDeleteEdgeStats() const { return deleteEStats_.get(); } - stats::Stats* getUpdateVertexStats() const { return updateVStats_.get(); } - stats::Stats* getUpdateEdgeStats() const { return updateEStats_.get(); } - stats::Stats* getGoStats() const { return goStats_.get(); } - stats::Stats* getFindPathStats() const { return findPathStats_.get(); } - stats::Stats* getFetchVerticesStats() const { return fetchVStats_.get(); } - stats::Stats* getFetchEdgesStats() const { return fetchEStats_.get(); } - -private: - std::unique_ptr<stats::Stats> storageClientStats_; // storageClient stats - std::unique_ptr<stats::Stats> metaClientStats_; // metaClient stats - std::unique_ptr<stats::Stats> graphAllStats_; // graph stats - std::unique_ptr<stats::Stats> parseErrorStats_; // graph parse error stats - std::unique_ptr<stats::Stats> insertVStats_; // insert vertexes stats - std::unique_ptr<stats::Stats> insertEStats_; // insert edges stats - std::unique_ptr<stats::Stats> deleteVStats_; // delete vertexes stats - std::unique_ptr<stats::Stats> deleteEStats_; // delete edges stats - std::unique_ptr<stats::Stats> updateVStats_; // update vertex stats - std::unique_ptr<stats::Stats> updateEStats_; // update edge stats - std::unique_ptr<stats::Stats> goStats_; // go stats - std::unique_ptr<stats::Stats> findPathStats_; // findPath stats - std::unique_ptr<stats::Stats> fetchVStats_; // fetch vertex stats - std::unique_ptr<stats::Stats> fetchEStats_; // fetch edge stats -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_GRAPHSTATS_H diff --git a/src/executor/GroupByExecutor.cpp b/src/executor/GroupByExecutor.cpp deleted file mode 100644 index 13ee5eac5e9faffb85d76382c1892002e398f9e6..0000000000000000000000000000000000000000 --- a/src/executor/GroupByExecutor.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. -* -* This source code is licensed under Apache 2.0 License, -* attached with Common Clause Condition 1.0, found in the LICENSES directory. -*/ - -#include "base/Base.h" -#include "graph/GroupByExecutor.h" -#include "graph/AggregateFunction.h" - -namespace nebula { -namespace graph { - -GroupByExecutor::GroupByExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<GroupBySentence*>(sentence); -} - - -Status GroupByExecutor::prepare() { - expCtx_ = std::make_unique<ExpressionContext>(); - Status status; - do { - status = prepareYield(); - if (!status.ok()) { - break; - } - - status = prepareGroup(); - if (!status.ok()) { - break; - } - } while (false); - - if (!status.ok()) { - LOG(ERROR) << "Preparing failed: " << status; - return status; - } - - return status; -} - - -Status GroupByExecutor::prepareYield() { - auto status = Status::OK(); - auto *clause = sentence_->yieldClause(); - std::vector<YieldColumn*> yields; - if (clause != nullptr) { - yields = clause->columns(); - } - - if (yields.empty()) { - return Status::SyntaxError("Yield cols is empty"); - } - for (auto *col : yields) { - std::string aggFun; - if ((col->getFunName() != kCount && col->getFunName() != kCountDist) - && col->expr()->toString() == "*") { - return Status::SyntaxError("Syntax error: near `*'"); - } - - col->expr()->setContext(expCtx_.get()); - status = col->expr()->prepare(); - if (!status.ok()) { - LOG(ERROR) << status; - return status; - } - yieldCols_.emplace_back(col); - - if (col->alias() != nullptr) { - if (col->expr()->isInputExpression()) { - aliases_.emplace(*col->alias(), col); - } - } - } - - return status; -} - - -Status GroupByExecutor::prepareGroup() { - auto status = Status::OK(); - do { - auto *clause = sentence_->groupClause(); - std::vector<YieldColumn*> groups; - if (clause != nullptr) { - groups = clause->columns(); - } - - if (groups.empty()) { - status = Status::SyntaxError("Group cols is empty"); - break; - } - for (auto *col : groups) { - if (col->getFunName() != "") { - status = Status::SyntaxError("Use invalid group function `%s'", - col->getFunName().c_str()); - break; - } - col->expr()->setContext(expCtx_.get()); - status = col->expr()->prepare(); - if (!status.ok()) { - break; - } - groupCols_.emplace_back(col); - } - if (!status.ok()) { - break; - } - } while (false); - - return status; -} - - -Status GroupByExecutor::checkAll() { - // Get index of input data - for (auto i = 0u; i < schema_->getNumFields(); i++) { - auto fieldName = schema_->getFieldName(i); - schemaMap_[fieldName] = i; - } - - // Check group col - std::unordered_set<std::string> inputGroupCols; - for (auto &it : groupCols_) { - // Check input col - if (it->expr()->isInputExpression()) { - auto groupName = static_cast<InputPropertyExpression*>(it->expr())->prop(); - auto findIt = schemaMap_.find(*groupName); - if (findIt == schemaMap_.end()) { - LOG(ERROR) << "Group `" << *groupName << "' isn't in output fields"; - return Status::SyntaxError("Group `%s' isn't in output fields", groupName->c_str()); - } - inputGroupCols.emplace(*groupName); - continue; - } - - // Function call - if (it->expr()->isFunCallExpression()) { - continue; - } - - // Check alias col - auto groupName = it->expr()->toString(); - auto alisaIt = aliases_.find(groupName); - if (alisaIt != aliases_.end()) { - it = alisaIt->second; - auto gName = static_cast<InputPropertyExpression*>(it->expr())->prop(); - if (it->expr()->isInputExpression()) { - inputGroupCols.emplace(*gName); - } - continue; - } - return Status::SyntaxError("Group `%s' isn't in output fields", groupName.c_str()); - } - - // Check yield cols - for (auto &it : yieldCols_) { - if (it->expr()->isInputExpression()) { - auto yieldName = static_cast<InputPropertyExpression*>(it->expr())->prop(); - auto findIt = schemaMap_.find(*yieldName); - if (findIt == schemaMap_.end()) { - LOG(ERROR) << "Yield `" << *yieldName << "' isn't in output fields"; - return Status::SyntaxError("Yield `%s' isn't in output fields", yieldName->c_str()); - } - // Check input yield filed without agg fun and not in group cols - if (inputGroupCols.find(*yieldName) == inputGroupCols.end() && - it->getFunName().empty()) { - LOG(ERROR) << "Yield `" << *yieldName << "' isn't in group fields"; - return Status::SyntaxError("Yield `%s' isn't in group fields", yieldName->c_str()); - } - } else if (it->expr()->isVariableExpression()) { - LOG(ERROR) << "Can't support variableExpression: " << it->expr()->toString(); - return Status::SyntaxError("Can't support variableExpression"); - } - } - return Status::OK(); -} - - -void GroupByExecutor::execute() { - FLOG_INFO("Executing Group by: %s", sentence_->toString().c_str()); - DCHECK(onError_); - DCHECK(onFinish_); - - if (rows_.empty()) { - onEmptyInputs(); - return; - } - - auto status = checkAll(); - if (!status.ok()) { - onError_(std::move(status)); - return; - } - - status = groupingData(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - status = generateOutputSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - - if (onResult_) { - auto ret = setupInterimResult(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - onResult_(std::move(ret).value()); - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - - -Status GroupByExecutor::groupingData() { - using FunCols = std::vector<std::shared_ptr<AggFun>>; - // key : the column values of group by, val: function table of aggregated columns - using GroupData = std::unordered_map<ColVals, FunCols, ColsHasher>; - - GroupData data; - for (auto& it : rows_) { - ColVals groupVals; - FunCols calVals; - - // Firstly: group the cols - for (auto &col : groupCols_) { - auto &getters = expCtx_->getters(); - cpp2::ColumnValue::Type valType = cpp2::ColumnValue::Type::__EMPTY__; - getters.getInputProp = [&] (const std::string & prop) -> OptVariantType { - auto indexIt = schemaMap_.find(prop); - if (indexIt == schemaMap_.end()) { - LOG(ERROR) << prop << " is nonexistent"; - return Status::Error("%s is nonexistent", prop.c_str()); - } - auto val = it.columns[indexIt->second]; - valType = val.getType(); - return toVariantType(val); - }; - - auto eval = col->expr()->eval(); - if (!eval.ok()) { - return eval.status(); - } - - auto cVal = toColumnValue(eval.value(), valType); - if (!cVal.ok()) { - return cVal.status(); - } - groupVals.vec.emplace_back(std::move(cVal).value()); - } - - auto findIt = data.find(groupVals); - - // Secondly: get the value of the aggregated column - - // Get all aggregation function - if (findIt == data.end()) { - for (auto &col : yieldCols_) { - auto funPtr = funVec[col->getFunName()](); - calVals.emplace_back(std::move(funPtr)); - } - } else { - calVals = findIt->second; - } - - // Apply value - auto i = 0u; - for (auto &col : calVals) { - auto &getters = expCtx_->getters(); - cpp2::ColumnValue::Type valType = cpp2::ColumnValue::Type::__EMPTY__; - getters.getInputProp = [&] (const std::string &prop) -> OptVariantType{ - auto indexIt = schemaMap_.find(prop); - if (indexIt == schemaMap_.end()) { - LOG(ERROR) << prop << " is nonexistent"; - return Status::Error("%s is nonexistent", prop.c_str()); - } - auto val = it.columns[indexIt->second]; - valType = val.getType(); - return toVariantType(val); - }; - auto eval = yieldCols_[i]->expr()->eval(); - if (!eval.ok()) { - return eval.status(); - } - - auto cVal = toColumnValue(std::move(eval).value(), valType); - if (!cVal.ok()) { - return cVal.status(); - } - col->apply(cVal.value()); - i++; - } - - if (findIt == data.end()) { - data.emplace(std::move(groupVals), std::move(calVals)); - } - } - - // Generate result data - rows_.clear(); - for (auto& item : data) { - std::vector<cpp2::ColumnValue> row; - for (auto& col : item.second) { - row.emplace_back(col->getResult()); - } - rows_.emplace_back(); - rows_.back().set_columns(std::move(row)); - } - - return Status::OK(); -} - - -std::vector<std::string> GroupByExecutor::getResultColumnNames() const { - std::vector<std::string> result; - result.reserve(yieldCols_.size()); - for (auto col : yieldCols_) { - if (col->alias() == nullptr) { - result.emplace_back(col->toString()); - } else { - result.emplace_back(*col->alias()); - } - } - return result; -} - - -void GroupByExecutor::feedResult(std::unique_ptr<InterimResult> result) { - if (result == nullptr) { - LOG(ERROR) << "result is nullptr"; - return; - } - - if (!result->hasData()) { - return; - } - - auto ret = result->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - return; - } - rows_ = std::move(ret).value(); - schema_ = result->schema(); -} - - -Status GroupByExecutor::generateOutputSchema() { - using nebula::cpp2::SupportedType; - if (resultSchema_ == nullptr) { - resultSchema_ = std::make_shared<SchemaWriter>(); - auto colnames = getResultColumnNames(); - CHECK(!rows_.empty()); - for (auto i = 0u; i < rows_[0].columns.size(); i++) { - SupportedType type; - switch (rows_[0].columns[i].getType()) { - case cpp2::ColumnValue::Type::id: - type = SupportedType::VID; - break; - case cpp2::ColumnValue::Type::bool_val: - type = SupportedType::BOOL; - break; - case cpp2::ColumnValue::Type::integer: - type = SupportedType::INT; - break; - case cpp2::ColumnValue::Type::str: - type = SupportedType::STRING; - break; - case cpp2::ColumnValue::Type::double_precision: - type = SupportedType::DOUBLE; - break; - case cpp2::ColumnValue::Type::timestamp: - type = SupportedType::TIMESTAMP; - break; - default: - LOG(ERROR) << "Unknown VariantType: " << rows_[0].columns[i].getType(); - return Status::Error("Unknown VariantType: %d", rows_[0].columns[i].getType()); - } - // TODO(laura) : should handle exist colname - resultSchema_->appendCol(colnames[i], type); - } - } - return Status::OK(); -} - - -StatusOr<std::unique_ptr<InterimResult>> GroupByExecutor::setupInterimResult() { - auto result = std::make_unique<InterimResult>(getResultColumnNames()); - if (rows_.empty() || resultSchema_ == nullptr) { - return result; - } - // Generate results - std::unique_ptr<RowSetWriter> rsWriter = std::make_unique<RowSetWriter>(resultSchema_); - - InterimResult::getResultWriter(rows_, rsWriter.get()); - if (rsWriter != nullptr) { - result->setInterim(std::move(rsWriter)); - } - return result; -} - - -void GroupByExecutor::onEmptyInputs() { - if (onResult_) { - auto result = std::make_unique<InterimResult>(getResultColumnNames()); - onResult_(std::move(result)); - } - onFinish_(Executor::ProcessControl::kNext); -} - - -void GroupByExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp.set_column_names(getResultColumnNames()); - - if (rows_.empty()) { - return; - } - resp.set_rows(std::move(rows_)); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/GroupByExecutor.h b/src/executor/GroupByExecutor.h deleted file mode 100644 index ff8998b56833b2f78773e83c8d5205ae3a80074e..0000000000000000000000000000000000000000 --- a/src/executor/GroupByExecutor.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_GROUPBYEXECUTOR_H_ -#define GRAPH_GROUPBYEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class GroupByExecutor final : public TraverseExecutor { -public: - GroupByExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "GroupByExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - Status prepareGroup(); - Status prepareYield(); - Status checkAll(); - - Status groupingData(); - Status generateOutputSchema(); - - std::vector<std::string> getResultColumnNames() const; - StatusOr<std::unique_ptr<InterimResult>> setupInterimResult(); - - void onEmptyInputs(); - -private: - GroupBySentence *sentence_{nullptr}; - std::vector<cpp2::RowValue> rows_; - std::shared_ptr<const meta::SchemaProviderIf> schema_{nullptr}; - - std::vector<YieldColumn*> groupCols_; - std::vector<YieldColumn*> yieldCols_; - std::shared_ptr<SchemaWriter> resultSchema_{nullptr}; - std::unique_ptr<ExpressionContext> expCtx_; - // key: alias , value input name - std::unordered_map<std::string, YieldColumn*> aliases_; - // input <fieldName, index> - std::unordered_map<std::string, int64_t> schemaMap_; -}; -} // namespace graph -} // namespace nebula -#endif // GRAPH_GROUPBYEXECUTOR_H diff --git a/src/executor/IngestExecutor.cpp b/src/executor/IngestExecutor.cpp deleted file mode 100644 index eadf10763bfde5bc919d8cfbb322a3cab17bee1d..0000000000000000000000000000000000000000 --- a/src/executor/IngestExecutor.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "http/HttpClient.h" -#include "graph/IngestExecutor.h" -#include "process/ProcessUtils.h" -#include "webservice/Common.h" - -#include <folly/executors/Async.h> -#include <folly/futures/Future.h> - -namespace nebula { -namespace graph { - -IngestExecutor::IngestExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<IngestSentence*>(sentence); -} - -Status IngestExecutor::prepare() { - return Status::OK(); -} - -void IngestExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - auto *mc = ectx()->getMetaClient(); - auto addresses = mc->getAddresses(); - auto metaHost = network::NetworkUtils::intToIPv4(addresses[0].first); - auto spaceId = ectx()->rctx()->session()->space(); - - auto func = [metaHost, spaceId]() { - static const char *tmp = "http://%s:%d/%s?space=%d"; - auto url = folly::stringPrintf(tmp, metaHost.c_str(), - FLAGS_ws_meta_http_port, - "ingest-dispatch", spaceId); - auto result = http::HttpClient::get(url); - if (result.ok() && result.value() == "SSTFile ingest successfully") { - LOG(INFO) << "Ingest Successfully"; - return true; - } else { - LOG(ERROR) << "Ingest Failed"; - return false; - } - }; - auto future = folly::async(func); - - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp) { - DCHECK(onError_); - onError_(Status::Error("Ingest Failed")); - return; - } - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void IngestExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/IngestExecutor.h b/src/executor/IngestExecutor.h deleted file mode 100644 index 1ceb4a54dd2bc56ed61b9e58462e4501499fd336..0000000000000000000000000000000000000000 --- a/src/executor/IngestExecutor.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_INGESTEXECUTOR_H -#define GRAPH_INGESTEXECUTOR_H - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class IngestExecutor final : public Executor { -public: - IngestExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "IngestExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - IngestSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_INGESTEXECUTOR_H - diff --git a/src/executor/InsertEdgeExecutor.cpp b/src/executor/InsertEdgeExecutor.cpp deleted file mode 100644 index 0b60c454af33f4b57fa47443aac35647fdaf1ffe..0000000000000000000000000000000000000000 --- a/src/executor/InsertEdgeExecutor.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/InsertEdgeExecutor.h" -#include "storage/client/StorageClient.h" - -namespace nebula { -namespace graph { - -InsertEdgeExecutor::InsertEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<InsertEdgeSentence*>(sentence); -} - - -Status InsertEdgeExecutor::prepare() { - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - return Status::OK(); -} - - -Status InsertEdgeExecutor::check() { - Status status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - LOG(ERROR) << "Please choose the space before insert edge"; - return status; - } - - spaceId_ = ectx()->rctx()->session()->space(); - overwritable_ = sentence_->overwritable(); - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId_, *sentence_->edge()); - if (!edgeStatus.ok()) { - status = edgeStatus.status(); - return status; - } - edgeType_ = edgeStatus.value(); - props_ = sentence_->properties(); - rows_ = sentence_->rows(); - - expCtx_->setStorageClient(ectx()->getStorageClient()); - schema_ = ectx()->schemaManager()->getEdgeSchema(spaceId_, edgeType_); - if (schema_ == nullptr) { - LOG(ERROR) << "No schema found for " << sentence_->edge(); - return Status::Error("No schema found for `%s'", sentence_->edge()->c_str()); - } - - if (props_.size() > schema_->getNumFields()) { - LOG(ERROR) << "Input props number " << props_.size() - << ", schema fields number " << schema_->getNumFields(); - return Status::Error("Wrong number of props"); - } - - auto *mc = ectx()->getMetaClient(); - - for (size_t i = 0; i < schema_->getNumFields(); i++) { - std::string name = schema_->getFieldName(i); - auto it = std::find_if(props_.begin(), props_.end(), - [name](std::string *prop) { return *prop == name;}); - - if (it == props_.end()) { - auto valueResult = mc->getEdgeDefaultValue(spaceId_, edgeType_, name).get(); - - if (!valueResult.ok()) { - LOG(ERROR) << "Not exist default value: " << name; - return Status::Error("Not exist default value"); - } else { - VLOG(3) << "Default Value: " << name << " : " << valueResult.value(); - defaultValues_.emplace(name, valueResult.value()); - } - } else { - int index = std::distance(props_.begin(), it); - propsPosition_.emplace(name, index); - } - } - - return Status::OK(); -} - - -StatusOr<std::vector<storage::cpp2::Edge>> InsertEdgeExecutor::prepareEdges() { - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - auto space = ectx()->rctx()->session()->space(); - expCtx_->setSpace(space); - - std::vector<storage::cpp2::Edge> edges(rows_.size() * 2); // inbound and outbound - auto index = 0; - for (auto i = 0u; i < rows_.size(); i++) { - auto *row = rows_[i]; - auto sid = row->srcid(); - sid->setContext(expCtx_.get()); - auto status = sid->prepare(); - if (!status.ok()) { - return status; - } - auto ovalue = sid->eval(); - if (!ovalue.ok()) { - return ovalue.status(); - } - - auto v = ovalue.value(); - if (!Expression::isInt(v)) { - return Status::Error("Vertex ID should be of type integer"); - } - auto src = Expression::asInt(v); - - auto did = row->dstid(); - did->setContext(expCtx_.get()); - status = did->prepare(); - if (!status.ok()) { - return status; - } - ovalue = did->eval(); - if (!ovalue.ok()) { - return ovalue.status(); - } - - v = ovalue.value(); - if (!Expression::isInt(v)) { - return Status::Error("Vertex ID should be of type integer"); - } - auto dst = Expression::asInt(v); - - int64_t rank = row->rank(); - - auto expressions = row->values(); - - std::vector<VariantType> values; - values.reserve(expressions.size()); - for (auto *expr : expressions) { - status = expr->prepare(); - if (!status.ok()) { - return status; - } - - ovalue = expr->eval(); - if (!ovalue.ok()) { - return ovalue.status(); - } - values.emplace_back(ovalue.value()); - } - - RowWriter writer(schema_); - for (size_t schemaIndex = 0; schemaIndex < schema_->getNumFields(); schemaIndex++) { - auto fieldName = schema_->getFieldName(schemaIndex); - auto positionIter = propsPosition_.find(fieldName); - - VariantType value; - auto schemaType = schema_->getFieldType(schemaIndex); - if (positionIter != propsPosition_.end()) { - auto position = propsPosition_[fieldName]; - value = values[position]; - if (!checkValueType(schemaType, value)) { - DCHECK(onError_); - LOG(ERROR) << "ValueType is wrong, schema type " - << static_cast<int32_t>(schemaType.type) - << ", input type " << value.which(); - return Status::Error("ValueType is wrong"); - } - } else { - // fetch default value from cache - auto result = transformDefaultValue(schemaType.type, defaultValues_[fieldName]); - if (!result.ok()) { - return result.status(); - } - - value = result.value(); - VLOG(3) << "Supplement default value : " << fieldName << " : " << value; - } - - if (schemaType.type == nebula::cpp2::SupportedType::TIMESTAMP) { - auto timestamp = toTimestamp(value); - if (!timestamp.ok()) { - return timestamp.status(); - } - writeVariantType(writer, timestamp.value()); - } else { - writeVariantType(writer, value); - } - } - - { - auto &out = edges[index++]; - out.key.set_src(src); - out.key.set_dst(dst); - out.key.set_ranking(rank); - out.key.set_edge_type(edgeType_); - out.props = writer.encode(); - out.__isset.key = true; - out.__isset.props = true; - } - { - auto &in = edges[index++]; - in.key.set_src(dst); - in.key.set_dst(src); - in.key.set_ranking(rank); - in.key.set_edge_type(-edgeType_); - in.props = ""; - in.__isset.key = true; - in.__isset.props = true; - } - } - - return edges; -} - - -void InsertEdgeExecutor::execute() { - auto status = check(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getInsertEdgeStats()); - return; - } - - auto result = prepareEdges(); - if (!result.ok()) { - LOG(ERROR) << "Insert edge failed, error " << result.status(); - doError(result.status(), ectx()->getGraphStats()->getInsertEdgeStats()); - return; - } - - auto future = ectx()->getStorageClient()->addEdges(spaceId_, - std::move(result).value(), - overwritable_); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - // For insertion, we regard partial success as failure. - auto completeness = resp.completeness(); - if (completeness != 100) { - const auto& failedCodes = resp.failedParts(); - for (auto it = failedCodes.begin(); it != failedCodes.end(); it++) { - LOG(ERROR) << "Insert edge failed, error " << static_cast<int32_t>(it->second) - << ", part " << it->first; - } - doError(Status::Error("Internal Error"), ectx()->getGraphStats()->getInsertEdgeStats()); - return; - } - doFinish(Executor::ProcessControl::kNext, - ectx()->getGraphStats()->getInsertEdgeStats(), - rows_.size()); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error"), ectx()->getGraphStats()->getInsertEdgeStats()); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula - - diff --git a/src/executor/InsertEdgeExecutor.h b/src/executor/InsertEdgeExecutor.h deleted file mode 100644 index 6faf713aa7ca89bd0275c320ce138d246c39ce23..0000000000000000000000000000000000000000 --- a/src/executor/InsertEdgeExecutor.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_INSERTEDGEEXECUTOR_H_ -#define GRAPH_INSERTEDGEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class InsertEdgeExecutor final : public Executor { -public: - InsertEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "InsertEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status check(); - StatusOr<std::vector<storage::cpp2::Edge>> prepareEdges(); - -private: - using EdgeSchema = std::shared_ptr<const meta::SchemaProviderIf>; - - InsertEdgeSentence *sentence_{nullptr}; - std::unique_ptr<ExpressionContext> expCtx_; - bool overwritable_{true}; - EdgeType edgeType_{0}; - EdgeSchema schema_; - std::vector<std::string*> props_; - std::vector<EdgeRowItem*> rows_; - GraphSpaceID spaceId_{-1}; - std::unordered_map<std::string, std::string> defaultValues_; - std::unordered_map<std::string, int32_t> propsPosition_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_INSERTEDGEEXECUTOR_H_ diff --git a/src/executor/InsertVertexExecutor.cpp b/src/executor/InsertVertexExecutor.cpp deleted file mode 100644 index 44d51a1b7ba14a8c3d942eed735d704615be67f0..0000000000000000000000000000000000000000 --- a/src/executor/InsertVertexExecutor.cpp +++ /dev/null @@ -1,256 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/InsertVertexExecutor.h" -#include "storage/client/StorageClient.h" -#include "meta/NebulaSchemaProvider.h" - -namespace nebula { -namespace graph { - -InsertVertexExecutor::InsertVertexExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<InsertVertexSentence*>(sentence); -} - - -Status InsertVertexExecutor::prepare() { - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setStorageClient(ectx()->getStorageClient()); - return Status::OK(); -} - - -Status InsertVertexExecutor::check() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - return status; - } - - rows_ = sentence_->rows(); - if (rows_.empty()) { - return Status::Error("VALUES cannot be empty"); - } - - auto tagItems = sentence_->tagItems(); - overwritable_ = sentence_->overwritable(); - spaceId_ = ectx()->rctx()->session()->space(); - - tagIds_.reserve(tagItems.size()); - schemas_.reserve(tagItems.size()); - tagProps_.reserve(tagItems.size()); - - for (auto& item : tagItems) { - auto *tagName = item->tagName(); - auto tagStatus = ectx()->schemaManager()->toTagID(spaceId_, *tagName); - if (!tagStatus.ok()) { - LOG(ERROR) << "No schema found for " << tagName; - return Status::Error("No schema found for `%s'", tagName->c_str()); - } - - auto tagId = tagStatus.value(); - auto schema = ectx()->schemaManager()->getTagSchema(spaceId_, tagId); - if (schema == nullptr) { - LOG(ERROR) << "No schema found for " << tagName; - return Status::Error("No schema found for `%s'", tagName->c_str()); - } - - auto props = item->properties(); - if (props.size() > schema->getNumFields()) { - LOG(ERROR) << "Input props number " << props.size() - << ", schema fields number " << schema->getNumFields(); - return Status::Error("Wrong number of props"); - } - - auto *mc = ectx()->getMetaClient(); - - std::unordered_map<std::string, int32_t> propsPosition; - for (size_t i = 0; i < schema->getNumFields(); i++) { - std::string name = schema->getFieldName(i); - auto it = std::find_if(props.begin(), props.end(), - [name](std::string *prop) { return *prop == name;}); - - // If the property name not find in schema's field - // We need to check the default value and save it. - if (it == props.end()) { - auto valueResult = mc->getTagDefaultValue(spaceId_, tagId, name).get(); - if (!valueResult.ok()) { - LOG(ERROR) << "Not exist default value: " << name; - return Status::Error("Not exist default value"); - } else { - VLOG(3) << "Default Value: " << name << ":" << valueResult.value(); - defaultValues_.emplace(name, valueResult.value()); - } - } else { - int index = std::distance(props.begin(), it); - propsPosition.emplace(name, index); - } - } - - tagIds_.emplace_back(tagId); - schemas_.emplace_back(std::move(schema)); - tagProps_.emplace_back(std::move(props)); - propsPositions_.emplace_back(std::move(propsPosition)); - } - return Status::OK(); -} - -StatusOr<std::vector<storage::cpp2::Vertex>> InsertVertexExecutor::prepareVertices() { - expCtx_->setStorageClient(ectx()->getStorageClient()); - expCtx_->setSpace(spaceId_); - - std::vector<storage::cpp2::Vertex> vertices(rows_.size()); - for (auto i = 0u; i < rows_.size(); i++) { - auto *row = rows_[i]; - auto rid = row->id(); - rid->setContext(expCtx_.get()); - - auto status = rid->prepare(); - if (!status.ok()) { - return status; - } - auto ovalue = rid->eval(); - if (!ovalue.ok()) { - return ovalue.status(); - } - - auto v = ovalue.value(); - if (!Expression::isInt(v)) { - return Status::Error("Vertex ID should be of type integer"); - } - auto id = Expression::asInt(v); - auto expressions = row->values(); - - std::vector<VariantType> values; - values.reserve(expressions.size()); - for (auto *expr : expressions) { - status = expr->prepare(); - if (!status.ok()) { - return status; - } - ovalue = expr->eval(); - if (!ovalue.ok()) { - return ovalue.status(); - } - values.emplace_back(ovalue.value()); - } - - storage::cpp2::Vertex vertex; - std::vector<storage::cpp2::Tag> tags(tagIds_.size()); - - int32_t valuePosition = 0; - for (auto index = 0u; index < tagIds_.size(); index++) { - auto &tag = tags[index]; - auto tagId = tagIds_[index]; - auto props = tagProps_[index]; - auto schema = schemas_[index]; - auto propsPosition = propsPositions_[index]; - - RowWriter writer(schema); - VariantType value; - auto schemaNumFields = schema->getNumFields(); - for (size_t schemaIndex = 0; schemaIndex < schemaNumFields; schemaIndex++) { - auto fieldName = schema->getFieldName(schemaIndex); - auto positionIter = propsPosition.find(fieldName); - - auto schemaType = schema->getFieldType(schemaIndex); - if (positionIter != propsPosition.end()) { - auto position = propsPosition[fieldName]; - value = values[position + valuePosition]; - - if (!checkValueType(schemaType, value)) { - LOG(ERROR) << "ValueType is wrong, schema type " - << static_cast<int32_t>(schemaType.type) - << ", input type " << value.which(); - return Status::Error("ValueType is wrong"); - } - } else { - // fetch default value from cache - auto result = transformDefaultValue(schemaType.type, defaultValues_[fieldName]); - if (!result.ok()) { - return result.status(); - } - - value = result.value(); - VLOG(3) << "Supplement default value : " << fieldName << " : " << value; - } - - if (schemaType.type == nebula::cpp2::SupportedType::TIMESTAMP) { - auto timestamp = toTimestamp(value); - if (!timestamp.ok()) { - return timestamp.status(); - } - writeVariantType(writer, timestamp.value()); - } else { - writeVariantType(writer, value); - } - } - - tag.set_tag_id(tagId); - tag.set_props(writer.encode()); - valuePosition += propsPosition.size(); - } - - vertex.set_id(id); - vertex.set_tags(std::move(tags)); - vertices.emplace_back(std::move(vertex)); - } - - return vertices; -} - - -void InsertVertexExecutor::execute() { - auto status = check(); - if (!status.ok()) { - doError(std::move(status), ectx()->getGraphStats()->getInsertVertexStats()); - return; - } - - auto result = prepareVertices(); - if (!result.ok()) { - LOG(ERROR) << "Insert vertices failed, error " << result.status().toString(); - doError(result.status(), ectx()->getGraphStats()->getInsertVertexStats()); - return; - } - auto future = ectx()->getStorageClient()->addVertices(spaceId_, - std::move(result).value(), - overwritable_); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - // For insertion, we regard partial success as failure. - auto completeness = resp.completeness(); - if (completeness != 100) { - const auto& failedCodes = resp.failedParts(); - for (auto it = failedCodes.begin(); it != failedCodes.end(); it++) { - LOG(ERROR) << "Insert vertices failed, error " << static_cast<int32_t>(it->second) - << ", part " << it->first; - } - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getInsertVertexStats()); - return; - } - doFinish(Executor::ProcessControl::kNext, - ectx()->getGraphStats()->getInsertVertexStats(), - rows_.size()); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal Error"), - ectx()->getGraphStats()->getInsertVertexStats()); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula - - diff --git a/src/executor/InsertVertexExecutor.h b/src/executor/InsertVertexExecutor.h deleted file mode 100644 index a9fa65512d39d9961b6f49ebc3751900f6a470a0..0000000000000000000000000000000000000000 --- a/src/executor/InsertVertexExecutor.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_INSERTVERTEXEXECUTOR_H_ -#define GRAPH_INSERTVERTEXEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class InsertVertexExecutor final : public Executor { -public: - InsertVertexExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "InsertVertexExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - Status check(); - StatusOr<std::vector<storage::cpp2::Vertex>> prepareVertices(); - -private: - using TagSchema = std::shared_ptr<const meta::SchemaProviderIf>; - - InsertVertexSentence *sentence_{nullptr}; - std::unique_ptr<ExpressionContext> expCtx_; - bool overwritable_{true}; - std::vector<VertexRowItem*> rows_; - std::vector<TagID> tagIds_; - std::vector<TagSchema> schemas_; - std::vector<std::vector<std::string*>> tagProps_; - std::vector<std::unordered_map<std::string, int32_t>> propsPositions_; - GraphSpaceID spaceId_{-1}; - std::unordered_map<std::string, std::string> defaultValues_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_INSERTVERTEXEXECUTOR_H_ diff --git a/src/executor/InterimResult.cpp b/src/executor/InterimResult.cpp deleted file mode 100644 index 2ffe8eaf77a38f06b95324e622c89e75e5a50015..0000000000000000000000000000000000000000 --- a/src/executor/InterimResult.cpp +++ /dev/null @@ -1,642 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/InterimResult.h" -#include "dataman/RowReader.h" - -namespace nebula { -namespace graph { - -constexpr char NotSupported[] = "Type not supported yet"; - -InterimResult::InterimResult(std::vector<VertexID> vids) { - vids_ = std::move(vids); -} - -InterimResult::InterimResult(std::vector<std::string> &&colNames) { - colNames_ = std::move(colNames); -} - -void InterimResult::setInterim(std::unique_ptr<RowSetWriter> rsWriter) { - rsWriter_ = std::move(rsWriter); - rsReader_ = std::make_unique<RowSetReader>(rsWriter_->schema(), rsWriter_->data()); -} - -StatusOr<std::vector<VertexID>> InterimResult::getVIDs(const std::string &col) const { - if (!vids_.empty()) { - DCHECK(rsReader_ == nullptr); - return vids_; - } - if (!hasData()) { - return Status::Error("Interim has no data."); - } - std::vector<VertexID> result; - auto iter = rsReader_->begin(); - while (iter) { - VertexID vid; - auto rc = iter->getVid(col, vid); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Column `%s' not found", col.c_str()); - } - result.emplace_back(vid); - ++iter; - } - return result; -} - -StatusOr<std::vector<VertexID>> InterimResult::getDistinctVIDs(const std::string &col) const { - if (!vids_.empty()) { - DCHECK(rsReader_ == nullptr); - return vids_; - } - if (!hasData()) { - return Status::Error("Interim has no data."); - } - std::unordered_set<VertexID> uniq; - auto iter = rsReader_->begin(); - while (iter) { - VertexID vid; - auto rc = iter->getVid(col, vid); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Column `%s' not found", col.c_str()); - } - uniq.emplace(vid); - ++iter; - } - std::vector<VertexID> result(uniq.begin(), uniq.end()); - return result; -} - -StatusOr<std::vector<cpp2::RowValue>> InterimResult::getRows() const { - if (!hasData()) { - return Status::Error("Interim has no data."); - } - auto schema = rsReader_->schema(); - auto columnCnt = schema->getNumFields(); - std::vector<cpp2::RowValue> rows; - folly::StringPiece piece; - using nebula::cpp2::SupportedType; - auto rowIter = rsReader_->begin(); - while (rowIter) { - std::vector<cpp2::ColumnValue> row; - row.reserve(columnCnt); - auto fieldIter = schema->begin(); - while (fieldIter) { - auto type = fieldIter->getType().type; - auto field = fieldIter->getName(); - row.emplace_back(); - switch (type) { - case SupportedType::VID: { - int64_t v; - auto rc = rowIter->getVid(field, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get vid from interim failed."); - } - row.back().set_id(v); - break; - } - case SupportedType::DOUBLE: { - double v; - auto rc = rowIter->getDouble(field, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get double from interim failed."); - } - row.back().set_double_precision(v); - break; - } - case SupportedType::BOOL: { - bool v; - auto rc = rowIter->getBool(field, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get bool from interim failed."); - } - row.back().set_bool_val(v); - break; - } - case SupportedType::STRING: { - auto rc = rowIter->getString(field, piece); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get bool from interim failed."); - } - row.back().set_str(piece.toString()); - break; - } - case SupportedType::INT: { - int64_t v; - auto rc = rowIter->getInt(field, v); - CHECK(rc == ResultType::SUCCEEDED); - row.back().set_integer(v); - break; - } - case SupportedType::TIMESTAMP: { - int64_t v; - auto rc = rowIter->getInt(field, v); - CHECK(rc == ResultType::SUCCEEDED); - row.back().set_timestamp(v); - break; - } - default: - std::string err = - folly::sformat("Unknown Type: %d", static_cast<int32_t>(type)); - LOG(ERROR) << err; - return Status::Error(err); - } - ++fieldIter; - } - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - ++rowIter; - } - return rows; -} - -StatusOr<std::unique_ptr<InterimResult::InterimResultIndex>> -InterimResult::buildIndex(const std::string &vidColumn) const { - using nebula::cpp2::SupportedType; - std::unique_ptr<InterimResultIndex> index; - - if (!hasData()) { - return Status::Error("Interim has no data."); - } - auto schema = rsReader_->schema(); - auto columnCnt = schema->getNumFields(); - uint32_t vidIndex = 0u; - - index = std::make_unique<InterimResultIndex>(); - for (auto i = 0u; i < columnCnt; i++) { - auto name = schema->getFieldName(i); - if (vidColumn == name) { - if (schema->getFieldType(i).type != SupportedType::VID) { - return Status::Error("The specific vid column `%s' is not type of VID.", - vidColumn.c_str()); - } - vidIndex = i; - } - index->columnToIndex_[name] = i; - } - - auto rowIter = rsReader_->begin(); - auto rowIndex = 0u; - while (rowIter) { - Row row; - row.reserve(columnCnt); - for (auto i = 0u; i < columnCnt; i++) { - auto type = schema->getFieldType(i).type; - switch (type) { - case SupportedType::VID: { - int64_t v; - auto rc = rowIter->getVid(i, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get vid from interim failed."); - } - if (i == vidIndex) { - index->vidToRowIndex_[v] = rowIndex++; - } - row.emplace_back(v); - break; - } - case SupportedType::DOUBLE: { - double v; - auto rc = rowIter->getDouble(i, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get double from interim failed."); - } - row.emplace_back(v); - break; - } - case SupportedType::BOOL: { - bool v; - auto rc = rowIter->getBool(i, v); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get bool from interim failed."); - } - row.emplace_back(v); - break; - } - case SupportedType::STRING: { - folly::StringPiece piece; - auto rc = rowIter->getString(i, piece); - if (rc != ResultType::SUCCEEDED) { - return Status::Error("Get bool from interim failed."); - } - row.emplace_back(piece.toString()); - break; - } - case SupportedType::INT: - case SupportedType::TIMESTAMP: { - int64_t v; - auto rc = rowIter->getInt(i, v); - CHECK(rc == ResultType::SUCCEEDED); - row.emplace_back(v); - break; - } - default: - std::string err = - folly::sformat("Unknown Type: %d", static_cast<int32_t>(type)); - LOG(ERROR) << err; - return Status::Error(err); - } - } - index->rows_.emplace_back(std::move(row)); - ++rowIter; - } - index->schema_ = schema; - return std::move(index); -} - - -OptVariantType InterimResult::InterimResultIndex::getColumnWithVID(VertexID id, - const std::string &col) const { - uint32_t rowIndex = 0; - { - auto iter = vidToRowIndex_.find(id); - DCHECK(iter != vidToRowIndex_.end()); - rowIndex = iter->second; - } - uint32_t columnIndex = 0; - { - auto iter = columnToIndex_.find(col); - if (iter == columnToIndex_.end()) { - LOG(ERROR) << "Prop `" << col << "' not found"; - return Status::Error("Prop `%s' not found", col.c_str()); - } - columnIndex = iter->second; - } - return rows_[rowIndex][columnIndex]; -} - - -nebula::cpp2::SupportedType InterimResult::InterimResultIndex::getColumnType( - const std::string &col) const { - uint32_t columnIndex = 0; - auto iter = columnToIndex_.find(col); - if (iter == columnToIndex_.end()) { - LOG(ERROR) << "Prop `" << col << "' not found"; - return nebula::cpp2::SupportedType::UNKNOWN; - } - columnIndex = iter->second; - - - if (schema_ == nullptr) { - return nebula::cpp2::SupportedType::UNKNOWN; - } - auto type = schema_->getFieldType(columnIndex); - return type.type; -} - - -Status InterimResult::castTo(cpp2::ColumnValue *col, - const nebula::cpp2::SupportedType &type) { - using nebula::cpp2::SupportedType; - switch (type) { - case SupportedType::VID: - return castToVid(col); - case SupportedType::INT: - return castToInt(col); - case SupportedType::TIMESTAMP: - return castToTimestamp(col); - case SupportedType::DOUBLE: - return castToDouble(col); - case SupportedType::BOOL: - return castToBool(col); - case SupportedType::STRING: - return castToStr(col); - default: - // Notice: if we implement some other type, - // we should update here. - LOG(ERROR) << NotSupported << static_cast<int32_t>(type); - return Status::Error(NotSupported); - } -} - -Status InterimResult::castToInt(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::integer: - break; - case cpp2::ColumnValue::Type::id: - col->set_integer(col->get_id()); - break; - case cpp2::ColumnValue::Type::timestamp: - col->set_integer(col->get_timestamp()); - break; - case cpp2::ColumnValue::Type::double_precision: { - auto d2i = static_cast<int64_t>(col->get_double_precision()); - col->set_integer(d2i); - break; - } - case cpp2::ColumnValue::Type::bool_val: { - auto b2i = static_cast<int64_t>(col->get_bool_val()); - col->set_integer(b2i); - break; - } - case cpp2::ColumnValue::Type::str: { - auto r = folly::tryTo<int64_t>(col->get_str()); - if (r.hasValue()) { - col->set_integer(r.value()); - break; - } else { - return Status::Error( - "Casting from string %s to double failed.", col->get_str().c_str()); - } - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -Status InterimResult::castToVid(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::id: - break; - case cpp2::ColumnValue::Type::integer: - col->set_id(col->get_integer()); - break; - case cpp2::ColumnValue::Type::timestamp: - col->set_id(col->get_timestamp()); - break; - case cpp2::ColumnValue::Type::double_precision: { - auto d2i = static_cast<int64_t>(col->get_double_precision()); - col->set_id(d2i); - break; - } - case cpp2::ColumnValue::Type::bool_val: { - auto b2i = static_cast<int64_t>(col->get_bool_val()); - col->set_id(b2i); - break; - } - case cpp2::ColumnValue::Type::str: { - auto r = folly::tryTo<int64_t>(col->get_str()); - if (r.hasValue()) { - col->set_id(r.value()); - break; - } else { - return Status::Error( - "Casting from string %s to double failed.", col->get_str().c_str()); - } - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -Status InterimResult::castToTimestamp(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::timestamp: - break; - case cpp2::ColumnValue::Type::integer: - col->set_timestamp(col->get_integer()); - break; - case cpp2::ColumnValue::Type::id: - col->set_timestamp(col->get_id()); - break; - case cpp2::ColumnValue::Type::double_precision: { - auto d2i = static_cast<int64_t>(col->get_double_precision()); - col->set_timestamp(d2i); - break; - } - case cpp2::ColumnValue::Type::bool_val: { - auto b2i = static_cast<int64_t>(col->get_bool_val()); - col->set_timestamp(b2i); - break; - } - case cpp2::ColumnValue::Type::str: { - auto r = folly::tryTo<int64_t>(col->get_str()); - if (r.hasValue()) { - col->set_timestamp(r.value()); - break; - } else { - return Status::Error( - "Casting from string %s to double failed.", col->get_str().c_str()); - } - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -Status InterimResult::castToDouble(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::id: { - auto i2d = static_cast<double>(col->get_id()); - col->set_double_precision(i2d); - break; - } - case cpp2::ColumnValue::Type::integer: { - auto i2d = static_cast<double>(col->get_integer()); - col->set_double_precision(i2d); - break; - } - case cpp2::ColumnValue::Type::double_precision: - break; - case cpp2::ColumnValue::Type::bool_val: { - auto b2d = static_cast<double>(col->get_bool_val()); - col->set_double_precision(b2d); - break; - } - case cpp2::ColumnValue::Type::str: { - auto r = folly::tryTo<double>(col->get_str()); - if (r.hasValue()) { - col->set_double_precision(r.value()); - break; - } else { - return Status::Error( - "Casting from string %s to double failed.", col->get_str().c_str()); - } - } - case cpp2::ColumnValue::Type::timestamp: { - auto i2d = static_cast<double>(col->get_timestamp()); - col->set_double_precision(i2d); - break; - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -Status InterimResult::castToBool(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::id: { - auto i2b = col->get_id() != 0; - col->set_bool_val(i2b); - break; - } - case cpp2::ColumnValue::Type::integer: { - auto i2b = col->get_integer() != 0; - col->set_bool_val(i2b); - break; - } - case cpp2::ColumnValue::Type::double_precision: { - auto d2b = col->get_double_precision() != 0.0; - col->set_bool_val(d2b); - break; - } - case cpp2::ColumnValue::Type::bool_val: - break; - case cpp2::ColumnValue::Type::str: { - auto s2b = col->get_str().empty(); - col->set_bool_val(s2b); - break; - } - case cpp2::ColumnValue::Type::timestamp: { - auto i2b = col->get_timestamp() != 0; - col->set_bool_val(i2b); - break; - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -Status InterimResult::castToStr(cpp2::ColumnValue *col) { - switch (col->getType()) { - case cpp2::ColumnValue::Type::id: { - auto i2s = folly::to<std::string>(col->get_id()); - col->set_str(std::move(i2s)); - break; - } - case cpp2::ColumnValue::Type::integer: { - auto i2s = folly::to<std::string>(col->get_integer()); - col->set_str(std::move(i2s)); - break; - } - case cpp2::ColumnValue::Type::double_precision: { - auto d2s = folly::to<std::string>(col->get_double_precision()); - col->set_str(std::move(d2s)); - break; - } - case cpp2::ColumnValue::Type::bool_val: { - auto b2s = folly::to<std::string>(col->get_bool_val()); - col->set_str(std::move(b2s)); - break; - } - case cpp2::ColumnValue::Type::str: - break; - case cpp2::ColumnValue::Type::timestamp: { - auto i2s = folly::to<std::string>(col->get_timestamp()); - col->set_str(std::move(i2s)); - break; - } - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col->getType()); - return Status::Error(NotSupported); - } - return Status::OK(); -} - -StatusOr<std::unique_ptr<InterimResult>> -InterimResult::getInterim( - std::shared_ptr<const meta::SchemaProviderIf> resultSchema, - std::vector<cpp2::RowValue> &rows) { - auto rsWriter = std::make_unique<RowSetWriter>(resultSchema); - for (auto &r : rows) { - RowWriter writer(resultSchema); - auto &cols = r.get_columns(); - for (auto &col : cols) { - switch (col.getType()) { - case cpp2::ColumnValue::Type::id: - writer << col.get_id(); - break; - case cpp2::ColumnValue::Type::integer: - writer << col.get_integer(); - break; - case cpp2::ColumnValue::Type::double_precision: - writer << col.get_double_precision(); - break; - case cpp2::ColumnValue::Type::bool_val: - writer << col.get_bool_val(); - break; - case cpp2::ColumnValue::Type::str: - writer << col.get_str(); - break; - case cpp2::ColumnValue::Type::timestamp: - writer << col.get_timestamp(); - break; - default: - LOG(ERROR) << NotSupported << static_cast<int32_t>(col.getType()); - return Status::Error(NotSupported); - } - } - rsWriter->addRow(writer); - } - - std::vector<std::string> colNames; - auto iter = resultSchema->begin(); - while (iter) { - colNames.emplace_back(iter->getName()); - ++iter; - } - auto result = std::make_unique<InterimResult>(std::move(colNames)); - result->setInterim(std::move(rsWriter)); - return std::move(result); -} - -Status InterimResult::applyTo(std::function<Status(const RowReader *reader)> visitor, - int64_t limit) const { - auto status = Status::OK(); - auto iter = rsReader_->begin(); - while (iter && (limit > 0)) { - status = visitor(&*iter); - if (!status.ok()) { - break; - } - --limit; - ++iter; - } - return status; -} - -Status InterimResult::getResultWriter(const std::vector<cpp2::RowValue> &rows, - RowSetWriter *rsWriter) { - if (rsWriter == nullptr) { - return Status::Error("rsWriter is nullptr"); - } - using Type = cpp2::ColumnValue::Type; - for (auto &row : rows) { - RowWriter writer(rsWriter->schema()); - auto columns = row.get_columns(); - for (auto &column : columns) { - switch (column.getType()) { - case Type::id: - writer << column.get_id(); - break; - case Type::integer: - writer << column.get_integer(); - break; - case Type::double_precision: - writer << column.get_double_precision(); - break; - case Type::bool_val: - writer << column.get_bool_val(); - break; - case Type::str: - writer << column.get_str(); - break; - case Type::timestamp: - writer << column.get_timestamp(); - break; - default: - LOG(ERROR) << "Not Support: " << column.getType(); - return Status::Error("Not Support: %d", column.getType()); - } - } - rsWriter->addRow(writer); - } - - return Status::OK(); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/InterimResult.h b/src/executor/InterimResult.h deleted file mode 100644 index 92af69b626262c80edd728fa97956c40df4e248a..0000000000000000000000000000000000000000 --- a/src/executor/InterimResult.h +++ /dev/null @@ -1,109 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_INTERIMRESULT_H_ -#define GRAPH_INTERIMRESULT_H_ - -#include "base/Base.h" -#include "base/StatusOr.h" -#include "filter/Expressions.h" -#include "dataman/RowSetReader.h" -#include "dataman/RowSetWriter.h" -#include "dataman/SchemaWriter.h" - -namespace nebula { -namespace graph { -/** - * The intermediate form of execution result, used in pipeline and variable. - */ -class InterimResult final { -public: - InterimResult() = default; - ~InterimResult() = default; - InterimResult(const InterimResult &) = delete; - InterimResult& operator=(const InterimResult &) = delete; - InterimResult(InterimResult &&) = default; - InterimResult& operator=(InterimResult &&) = default; - - explicit InterimResult(std::vector<VertexID> vids); - explicit InterimResult(std::vector<std::string> &&colNames); - - static StatusOr<std::unique_ptr<InterimResult>> getInterim( - std::shared_ptr<const meta::SchemaProviderIf> resultSchema, - std::vector<cpp2::RowValue> &rows); - static Status castTo(cpp2::ColumnValue *col, - const nebula::cpp2::SupportedType &type); - static Status castToInt(cpp2::ColumnValue *col); - static Status castToVid(cpp2::ColumnValue *col); - static Status castToTimestamp(cpp2::ColumnValue *col); - static Status castToDouble(cpp2::ColumnValue *col); - static Status castToBool(cpp2::ColumnValue *col); - static Status castToStr(cpp2::ColumnValue *col); - - static Status getResultWriter(const std::vector<cpp2::RowValue> &rows, - RowSetWriter *rsWriter); - - void setColNames(std::vector<std::string> &&colNames) { - colNames_ = std::move(colNames); - } - - void setInterim(std::unique_ptr<RowSetWriter> rsWriter); - - bool hasData() const { - return (rsWriter_ != nullptr) && (rsReader_ != nullptr); - } - - std::shared_ptr<const meta::SchemaProviderIf> schema() const { - if (!hasData()) { - return nullptr; - } - return rsReader_->schema(); - } - - std::vector<std::string> getColNames() const { - return colNames_; - } - - StatusOr<std::vector<VertexID>> getVIDs(const std::string &col) const; - - StatusOr<std::vector<VertexID>> getDistinctVIDs(const std::string &col) const; - - StatusOr<std::vector<cpp2::RowValue>> getRows() const; - - class InterimResultIndex; - StatusOr<std::unique_ptr<InterimResultIndex>> - buildIndex(const std::string &vidColumn) const; - - Status applyTo(std::function<Status(const RowReader *reader)> visitor, - int64_t limit = INT64_MAX) const; - - class InterimResultIndex final { - public: - OptVariantType getColumnWithVID(VertexID id, const std::string &col) const; - nebula::cpp2::SupportedType getColumnType(const std::string &col) const; - - private: - friend class InterimResult; - using Row = std::vector<VariantType>; - std::vector<Row> rows_; - using SchemaPtr = std::shared_ptr<const meta::SchemaProviderIf>; - SchemaPtr schema_{nullptr}; - std::unordered_map<std::string, uint32_t> columnToIndex_; - std::unordered_map<VertexID, uint32_t> vidToRowIndex_; - }; - -private: - using Row = std::vector<VariantType>; - std::vector<std::string> colNames_; - std::unique_ptr<RowSetReader> rsReader_; - std::unique_ptr<RowSetWriter> rsWriter_; - std::vector<VertexID> vids_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_INTERIMRESULT_H_ diff --git a/src/executor/LimitExecutor.cpp b/src/executor/LimitExecutor.cpp deleted file mode 100644 index 10d2d2058f154923b165a6c66ae4d4df537dfbce..0000000000000000000000000000000000000000 --- a/src/executor/LimitExecutor.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/LimitExecutor.h" - -namespace nebula { -namespace graph { - -LimitExecutor::LimitExecutor(Sentence *sentence, ExecutionContext *ectx) : TraverseExecutor(ectx) { - sentence_ = static_cast<LimitSentence*>(sentence); -} - - -Status LimitExecutor::prepare() { - offset_ = sentence_->offset(); - if (offset_ < 0) { - return Status::SyntaxError("skip `%ld' is illegal", offset_); - } - count_ = sentence_->count(); - if (count_ < 0) { - return Status::SyntaxError("count `%ld' is illegal", count_); - } - - return Status::OK(); -} - - -void LimitExecutor::execute() { - FLOG_INFO("Executing Limit: %s", sentence_->toString().c_str()); - if (inputs_ == nullptr || !inputs_->hasData() || count_ == 0) { - onEmptyInputs(); - return; - } - - auto ret = inputs_->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto inRows = std::move(ret).value(); - if (inRows.size() > static_cast<uint64_t>(offset_ + count_)) { - rows_.resize(count_); - rows_.assign(std::make_move_iterator(inRows.begin()) + offset_, - std::make_move_iterator(inRows.begin()) + offset_ + count_); - } else if (inRows.size() > static_cast<uint64_t>(offset_) && - inRows.size() <= static_cast<uint64_t>(offset_ + count_)) { - rows_.resize(inRows.size() - offset_); - rows_.assign(std::make_move_iterator(inRows.begin()) + offset_, - std::make_move_iterator(inRows.end())); - } - - if (onResult_) { - auto output = setupInterimResult(); - onResult_(std::move(output)); - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - - -void LimitExecutor::feedResult(std::unique_ptr<InterimResult> result) { - if (result == nullptr) { - LOG(ERROR) << "Get null input."; - return; - } - inputs_ = std::move(result); - colNames_ = inputs_->getColNames(); -} - - -std::unique_ptr<InterimResult> LimitExecutor::setupInterimResult() { - auto result = std::make_unique<InterimResult>(std::move(colNames_)); - if (rows_.empty()) { - return result; - } - - auto rsWriter = std::make_unique<RowSetWriter>(inputs_->schema()); - using Type = cpp2::ColumnValue::Type; - for (auto &row : rows_) { - RowWriter writer(inputs_->schema()); - auto columns = row.get_columns(); - for (auto &column : columns) { - switch (column.getType()) { - case cpp2::ColumnValue::Type::id: - writer << column.get_id(); - break; - case Type::integer: - writer << column.get_integer(); - break; - case Type::double_precision: - writer << column.get_double_precision(); - break; - case Type::bool_val: - writer << column.get_bool_val(); - break; - case Type::str: - writer << column.get_str(); - break; - case cpp2::ColumnValue::Type::timestamp: - writer << column.get_timestamp(); - break; - default: - LOG(FATAL) << "Not Support: " << column.getType(); - } - } - rsWriter->addRow(writer); - } - - if (rsWriter != nullptr) { - result->setInterim(std::move(rsWriter)); - } - return result; -} - - -void LimitExecutor::onEmptyInputs() { - if (onResult_) { - auto result = std::make_unique<InterimResult>(std::move(colNames_)); - onResult_(std::move(result)); - } - onFinish_(Executor::ProcessControl::kNext); -} - - -void LimitExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp.set_column_names(std::move(colNames_)); - - if (rows_.empty()) { - return; - } - resp.set_rows(std::move(rows_)); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/LimitExecutor.h b/src/executor/LimitExecutor.h deleted file mode 100644 index 4a69945e2b1de7adeca446e3d493179a8e4283e0..0000000000000000000000000000000000000000 --- a/src/executor/LimitExecutor.h +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_LIMITEXECUTOR_H_ -#define GRAPH_LIMITEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class LimitExecutor final : public TraverseExecutor { -public: - LimitExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "LimitExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - std::unique_ptr<InterimResult> setupInterimResult(); - - void onEmptyInputs(); - -private: - LimitSentence *sentence_{nullptr}; - std::unique_ptr<InterimResult> inputs_; - std::vector<std::string> colNames_; - std::vector<cpp2::RowValue> rows_; - int64_t offset_{-1}; - int64_t count_{-1}; -}; -} // namespace graph -} // namespace nebula - -#endif // GRAPH_LIMITEXECUTOR_H diff --git a/src/executor/MatchExecutor.cpp b/src/executor/MatchExecutor.cpp deleted file mode 100644 index e058f4fb5fc9a7048acc99c7558a1b3095dea7ee..0000000000000000000000000000000000000000 --- a/src/executor/MatchExecutor.cpp +++ /dev/null @@ -1,24 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/MatchExecutor.h" - -namespace nebula { -namespace graph { - -MatchExecutor::MatchExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<MatchSentence*>(sentence); -} - - -Status MatchExecutor::prepare() { - return Status::Error("Does not support"); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/MatchExecutor.h b/src/executor/MatchExecutor.h deleted file mode 100644 index 53d88964b025dbbd1a0350d473dde8d4bb2d654d..0000000000000000000000000000000000000000 --- a/src/executor/MatchExecutor.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_MATCHEXECUTOR_H_ -#define GRAPH_MATCHEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class MatchExecutor final : public TraverseExecutor { -public: - MatchExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "UseExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void feedResult(std::unique_ptr<InterimResult> result) override { - UNUSED(result); - } - - void execute() override {} - -private: - MatchSentence *sentence_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_MATCHEXECUTOR_H_ diff --git a/src/executor/OrderByExecutor.cpp b/src/executor/OrderByExecutor.cpp deleted file mode 100644 index 8e5969b73371b53cda4250513a6b7436634f9b9c..0000000000000000000000000000000000000000 --- a/src/executor/OrderByExecutor.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/OrderByExecutor.h" - -namespace nebula { -namespace graph { -namespace cpp2 { - -bool ColumnValue::operator < (const ColumnValue& rhs) const { - DCHECK_EQ(type_, rhs.type_); - auto& lhs = *this; - switch (lhs.type_) { - case Type::bool_val: - { - return lhs.value_.bool_val < rhs.value_.bool_val; - } - case Type::integer: - { - return lhs.value_.integer < rhs.value_.integer; - } - case Type::id: - { - return lhs.value_.id < rhs.value_.id; - } - case Type::single_precision: - { - return lhs.value_.single_precision < rhs.value_.single_precision; - } - case Type::double_precision: - { - return lhs.value_.double_precision < rhs.value_.double_precision; - } - case Type::str: - { - return lhs.value_.str < rhs.value_.str; - } - case Type::timestamp: - { - return lhs.value_.timestamp < rhs.value_.timestamp; - } - case Type::year: - { - return lhs.value_.year < rhs.value_.year; - } - case Type::month: - { - return lhs.value_.month < rhs.value_.month; - } - case Type::date: - { - return lhs.value_.date < rhs.value_.date; - } - case Type::datetime: - { - return lhs.value_.datetime < rhs.value_.datetime; - } - default: - { - return false; - } - } - return false; -} -} // namespace cpp2 - -OrderByExecutor::OrderByExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<OrderBySentence*>(sentence); -} - -Status OrderByExecutor::prepare() { - return Status::OK(); -} - -void OrderByExecutor::feedResult(std::unique_ptr<InterimResult> result) { - if (result == nullptr) { - return; - } - DCHECK(sentence_ != nullptr); - inputs_ = std::move(result); - colNames_ = inputs_->getColNames(); - auto ret = inputs_->getRows(); - if (!ret.ok()) { - return; - } - rows_ = std::move(ret).value(); -} - -void OrderByExecutor::execute() { - DCHECK(onFinish_); - DCHECK(onError_); - FLOG_INFO("Executing Order By: %s", sentence_->toString().c_str()); - auto status = beforeExecute(); - if (!status.ok()) { - LOG(ERROR) << "Error happened before execute: " << status.toString(); - onError_(std::move(status)); - return; - } - - auto comparator = [this] (cpp2::RowValue& lhs, cpp2::RowValue& rhs) { - const auto &lhsColumns = lhs.get_columns(); - const auto &rhsColumns = rhs.get_columns(); - for (auto &factor : this->sortFactors_) { - auto fieldIndex = factor.first; - auto orderType = factor.second; - if (lhsColumns[fieldIndex] == rhsColumns[fieldIndex]) { - continue; - } - - if (orderType == OrderFactor::OrderType::ASCEND) { - return lhsColumns[fieldIndex] < rhsColumns[fieldIndex]; - } else if (orderType == OrderFactor::OrderType::DESCEND) { - return lhsColumns[fieldIndex] > rhsColumns[fieldIndex]; - } else { - LOG(FATAL) << "Unkown Order Type: " << orderType; - } - } - return false; - }; - - if (!sortFactors_.empty()) { - std::sort(rows_.begin(), rows_.end(), comparator); - } - - if (onResult_) { - onResult_(setupInterimResult()); - } - onFinish_(Executor::ProcessControl::kNext); -} - -Status OrderByExecutor::beforeExecute() { - if (inputs_ == nullptr || !inputs_->hasData()) { - return Status::OK(); - } - - auto schema = inputs_->schema(); - auto factors = sentence_->factors(); - sortFactors_.reserve(factors.size()); - for (auto &factor : factors) { - auto expr = static_cast<InputPropertyExpression*>(factor->expr()); - folly::StringPiece field = *(expr->prop()); - auto fieldIndex = schema->getFieldIndex(field); - if (fieldIndex == -1) { - return Status::Error("Field (%s) not exist in input schema.", field.str().c_str()); - } - auto pair = std::make_pair(schema->getFieldIndex(field), factor->orderType()); - sortFactors_.emplace_back(std::move(pair)); - } - return Status::OK(); -} - -std::unique_ptr<InterimResult> OrderByExecutor::setupInterimResult() { - auto result = std::make_unique<InterimResult>(std::move(colNames_)); - if (rows_.empty()) { - return result; - } - - auto schema = inputs_->schema(); - auto rsWriter = std::make_unique<RowSetWriter>(schema); - using Type = cpp2::ColumnValue::Type; - for (auto &row : rows_) { - RowWriter writer(schema); - auto columns = row.get_columns(); - for (auto &column : columns) { - switch (column.getType()) { - case Type::id: - writer << column.get_id(); - break; - case Type::integer: - writer << column.get_integer(); - break; - case Type::double_precision: - writer << column.get_double_precision(); - break; - case Type::bool_val: - writer << column.get_bool_val(); - break; - case Type::str: - writer << column.get_str(); - break; - case Type::timestamp: - writer << column.get_timestamp(); - break; - default: - LOG(FATAL) << "Not Support: " << column.getType(); - } - } - rsWriter->addRow(writer); - } - - result->setInterim(std::move(rsWriter)); - return result; -} - -void OrderByExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp.set_column_names(std::move(colNames_)); - - if (rows_.empty()) { - return; - } - resp.set_rows(std::move(rows_)); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/OrderByExecutor.h b/src/executor/OrderByExecutor.h deleted file mode 100644 index 5005355dfd49ff71acfac0fbd562a09953849ca7..0000000000000000000000000000000000000000 --- a/src/executor/OrderByExecutor.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_ORDERBYEXECUTOR_H_ -#define GRAPH_ORDERBYEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class OrderByExecutor final : public TraverseExecutor { -public: - OrderByExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "OrderByExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - std::unique_ptr<InterimResult> setupInterimResult(); - - Status beforeExecute(); - -private: - OrderBySentence *sentence_{nullptr}; - std::unique_ptr<InterimResult> inputs_; - std::vector<std::string> colNames_; - std::vector<cpp2::RowValue> rows_; - std::vector<std::pair<int64_t, OrderFactor::OrderType>> sortFactors_; -}; -} // namespace graph -} // namespace nebula -#endif // GRAPH_ORDERBYEXECUTOR_H_ diff --git a/src/executor/PermissionManager.h b/src/executor/PermissionManager.h deleted file mode 100644 index 1e64a854b650c03d53441494847bbee593b3955c..0000000000000000000000000000000000000000 --- a/src/executor/PermissionManager.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - - -#ifndef GRAPH_PERMISSIONMANAGER_H -#define GRAPH_PERMISSIONMANAGER_H - -// Operation and permission define: -// Operation | GOD | ADMIN | USER | GUEST -// ---------------- | ------------- | ------------- | ------------- | ------------- -// kGo | Y | Y | Y | Y -// kSet | Y | Y | Y | Y -// kPipe | Y | Y | Y | Y -// kUse | Y | Y | Y | Y -// kMatch | Y | Y | Y | Y -// kAssignment | Y | Y | Y | Y -// kCreateTag | Y | Y | | -// kAlterTag | Y | Y | | -// kCreateEdge | Y | Y | | -// kAlterEdge | Y | Y | | -// kDescribeTag | Y | Y | Y | Y -// kDescribeEdge | Y | Y | Y | Y -// kRemoveTag | Y | Y | | -// kRemoveEdge | Y | Y | | -// kInsertVertex | Y | Y | Y | -// kInsertEdge | Y | Y | Y | -// kShow | Y | Y | Y | Y -// kDeleteVertex | Y | Y | Y | -// kDeleteEdge | Y | Y | Y | -// kFind | Y | Y | Y | Y -// kCreateSpace | Y | | | -// kDropSpace | Y | Y | | -// kYield | Y | Y | Y | Y -// kCreateUser | Y | | | -// kDropUser | Y | | | -// kAlterUser | Y | Y | Y | Y -// kGrant | Y | Y | | -// kRevoke | Y | Y | | -// kChangePassword | Y | Y | Y | Y - - -#endif // GRAPH_PERMISSIONMANAGER_H diff --git a/src/executor/PipeExecutor.cpp b/src/executor/PipeExecutor.cpp deleted file mode 100644 index 80532c090deedc41dc86c60404114a79591a2799..0000000000000000000000000000000000000000 --- a/src/executor/PipeExecutor.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/PipeExecutor.h" - -namespace nebula { -namespace graph { - -PipeExecutor::PipeExecutor(Sentence *sentence, - ExecutionContext *ectx) : TraverseExecutor(ectx) { - sentence_ = static_cast<PipedSentence*>(sentence); -} - - -Status PipeExecutor::prepare() { - auto status = syntaxPreCheck(); - if (!status.ok()) { - return status; - } - - left_ = makeTraverseExecutor(sentence_->left()); - right_ = makeTraverseExecutor(sentence_->right()); - DCHECK(left_ != nullptr); - DCHECK(right_ != nullptr); - - auto onError = [this] (Status s) { - /** - * TODO(dutor) - * If we allow concurrent execution of both sides, we must wait for all their - * internal on-fly async-requests' to arrive before call `onError_'. - * For the sake of simplicity, we don't allow the pipeline way for now. - */ - onError_(std::move(s)); - }; - - // Setup dependencies - { - auto onFinish = [this] (Executor::ProcessControl ctr) { - UNUSED(ctr); - // Start executing `right_' when `left_' is finished. - right_->execute(); - }; - left_->setOnFinish(onFinish); - - auto onResult = [this] (std::unique_ptr<InterimResult> result) { - // Feed results from `left_' to `right_' - // result should never be null, it should give the column names at least. - DCHECK(result != nullptr); - right_->feedResult(std::move(result)); - }; - left_->setOnResult(onResult); - - left_->setOnError(onError); - } - { - auto onFinish = [this] (Executor::ProcessControl ctr) { - // This executor is done when `right_' finishes. - DCHECK(onFinish_); - onFinish_(ctr); - }; - right_->setOnFinish(onFinish); - - if (onResult_) { - auto onResult = [this] (std::unique_ptr<InterimResult> result) { - // This executor takes results of `right_' as results. - // result should never be null, it should give the column names at least. - DCHECK(result != nullptr); - onResult_(std::move(result)); - }; - right_->setOnResult(onResult); - } else { - // `right_' is the right most part of the pipeline - } - - right_->setOnError(onError); - } - - status = left_->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - left_->name(), status.toString().c_str()); - return status; - } - - status = right_->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - right_->name(), status.toString().c_str()); - return status; - } - - - return Status::OK(); -} - -Status PipeExecutor::syntaxPreCheck() { - // Set op not support input, - // because '$-' would be ambiguous in such a situation: - // Go | (Go | Go $- UNION GO) - if (sentence_->right()->kind() == Sentence::Kind::kSet) { - return Status::SyntaxError("Set op not support input."); - } - - if (sentence_->left()->kind() == Sentence::Kind::kFindPath) { - return Status::SyntaxError("Can not reference the result of FindPath."); - } - - return Status::OK(); -} - -void PipeExecutor::execute() { - left_->execute(); -} - - -void PipeExecutor::feedResult(std::unique_ptr<InterimResult> result) { - left_->feedResult(std::move(result)); -} - - -void PipeExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - /** - * `setupResponse()' could be invoked if and only if this executor - * is the right most one, i.e. `onResult_' wasn't set. - */ - DCHECK(!onResult_); - right_->setupResponse(resp); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/PipeExecutor.h b/src/executor/PipeExecutor.h deleted file mode 100644 index 2053437ecbde5211ae2551c6b050f798ec44fa69..0000000000000000000000000000000000000000 --- a/src/executor/PipeExecutor.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_PIPEEXECUTOR_H_ -#define GRAPH_PIPEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" - -namespace nebula { -namespace graph { - -class PipeExecutor final : public TraverseExecutor { -public: - PipeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "PipeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - Status syntaxPreCheck(); - -private: - PipedSentence *sentence_{nullptr}; - std::unique_ptr<TraverseExecutor> left_; - std::unique_ptr<TraverseExecutor> right_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_PIPEEXECUTOR_H_ diff --git a/src/executor/README.md b/src/executor/README.md deleted file mode 100644 index 07dd0c5c770357eace1b04f76e762baabca37471..0000000000000000000000000000000000000000 --- a/src/executor/README.md +++ /dev/null @@ -1 +0,0 @@ -# Overview diff --git a/src/executor/ReturnExecutor.cpp b/src/executor/ReturnExecutor.cpp deleted file mode 100644 index 083c2afdfef517cf17b41b122fe661d2ef9b3f6c..0000000000000000000000000000000000000000 --- a/src/executor/ReturnExecutor.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/ReturnExecutor.h" -#include "graph/InterimResult.h" - -namespace nebula { -namespace graph { -ReturnExecutor::ReturnExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<ReturnSentence*>(sentence); -} - -Status ReturnExecutor::prepare() { - return Status::OK(); -} - -void ReturnExecutor::execute() { - FLOG_INFO("Executing Return: %s", sentence_->toString().c_str()); - DCHECK(onFinish_); - DCHECK(onError_); - DCHECK(sentence_); - - auto *var = sentence_->var(); - auto *condition = sentence_->condition(); - if (var == nullptr) { - // Shall never reach here. - onError_(Status::SyntaxError("Variable not declared.")); - return; - } - - if ((condition != nullptr) && (*condition != *var)) { - onError_(Status::SyntaxError( - "Variable(%s) to be returned is not euqal to condition(%s)", var, condition)); - return; - } - - bool existing = false; - auto *varInputs = ectx()->variableHolder()->get(*var, &existing); - if (varInputs == nullptr && !existing) { - onError_(Status::Error("Variable(%s) not declared.", var)); - return; - } - - if (varInputs == nullptr || !varInputs->hasData()) { - onFinish_(Executor::ProcessControl::kNext); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - auto colNames = varInputs->getColNames(); - resp_->set_column_names(std::move(colNames)); - auto ret = varInputs->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - onError_(std::move(ret).status()); - return; - } - auto rows = ret.value(); - if (rows.empty()) { - onFinish_(Executor::ProcessControl::kNext); - return; - } - resp_->set_rows(std::move(rows)); - // Will return if variable has values. - onFinish_(Executor::ProcessControl::kReturn); - } -} - -void ReturnExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - } - resp = std::move(*resp_); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/ReturnExecutor.h b/src/executor/ReturnExecutor.h deleted file mode 100644 index f4c6c40aeb2be90dea421e28080269a452868a51..0000000000000000000000000000000000000000 --- a/src/executor/ReturnExecutor.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_RETURNEXECUTOR_H_ -#define GRAPH_RETURNEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { -class ReturnExecutor final : public Executor { -public: - ReturnExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "ReturnExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - ReturnSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; -} // namespace graph -} // namespace nebula -#endif diff --git a/src/executor/SchemaHelper.cpp b/src/executor/SchemaHelper.cpp deleted file mode 100644 index 0a939b6ec4f2f8de936bdfbc3de9f97c0e959157..0000000000000000000000000000000000000000 --- a/src/executor/SchemaHelper.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/SchemaHelper.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -// static -nebula::cpp2::SupportedType SchemaHelper::columnTypeToSupportedType(nebula::ColumnType type) { - switch (type) { - case nebula::ColumnType::BOOL: - return nebula::cpp2::SupportedType::BOOL; - case nebula::ColumnType::INT: - return nebula::cpp2::SupportedType::INT; - case nebula::ColumnType::DOUBLE: - return nebula::cpp2::SupportedType::DOUBLE; - case nebula::ColumnType::STRING: - return nebula::cpp2::SupportedType::STRING; - case nebula::ColumnType::TIMESTAMP: - return nebula::cpp2::SupportedType::TIMESTAMP; - default: - return nebula::cpp2::SupportedType::UNKNOWN; - } -} - -// static -Status SchemaHelper::createSchema(const std::vector<ColumnSpecification*>& specs, - const std::vector<SchemaPropItem*>& schemaProps, - nebula::cpp2::Schema& schema) { - auto status = Status::OK(); - - std::unordered_set<std::string> nameSet; - for (auto& spec : specs) { - if (nameSet.find(*spec->name()) != nameSet.end()) { - return Status::Error("Duplicate column name `%s'", spec->name()->c_str()); - } - nameSet.emplace(*spec->name()); - nebula::cpp2::ColumnDef column; - column.name = *spec->name(); - column.type.type = columnTypeToSupportedType(spec->type()); - nebula::cpp2::Value v; - if (spec->hasDefault()) { - switch (spec->type()) { - case nebula::ColumnType::BOOL: - v.set_bool_value(spec->getBoolValue()); - column.set_default_value(std::move(v)); - break; - case nebula::ColumnType::INT: - v.set_int_value(spec->getIntValue()); - column.set_default_value(std::move(v)); - break; - case nebula::ColumnType::DOUBLE: - v.set_double_value(spec->getDoubleValue()); - column.set_default_value(std::move(v)); - break; - case nebula::ColumnType::STRING: - v.set_string_value(spec->getStringValue()); - column.set_default_value(std::move(v)); - break; - default: - LOG(ERROR) << "Unsupport Type"; - return Status::Error("Unsupport Type"); - } - } - schema.columns.emplace_back(std::move(column)); - } - - if (!schemaProps.empty()) { - for (auto& schemaProp : schemaProps) { - switch (schemaProp->getPropType()) { - case SchemaPropItem::TTL_DURATION: - status = setTTLDuration(schemaProp, schema); - if (!status.ok()) { - return status; - } - break; - case SchemaPropItem::TTL_COL: - status = setTTLCol(schemaProp, schema); - if (!status.ok()) { - return status; - } - break; - } - } - - if (schema.schema_prop.get_ttl_duration() && - (*schema.schema_prop.get_ttl_duration() != 0)) { - // Disable implicit TTL mode - if (!schema.schema_prop.get_ttl_col() || - (schema.schema_prop.get_ttl_col() && schema.schema_prop.get_ttl_col()->empty())) { - return Status::Error("Implicit ttl_col not support"); - } - } - } - - return Status::OK(); -} - - -// static -Status SchemaHelper::setTTLDuration(SchemaPropItem* schemaProp, nebula::cpp2::Schema& schema) { - auto ret = schemaProp->getTtlDuration(); - if (!ret.ok()) { - return ret.status(); - } - - auto ttlDuration = ret.value(); - schema.schema_prop.set_ttl_duration(ttlDuration); - return Status::OK(); -} - - -// static -Status SchemaHelper::setTTLCol(SchemaPropItem* schemaProp, nebula::cpp2::Schema& schema) { - auto ret = schemaProp->getTtlCol(); - if (!ret.ok()) { - return ret.status(); - } - - auto ttlColName = ret.value(); - // Check the legality of the ttl column name - for (auto& col : schema.columns) { - if (col.name == ttlColName) { - // Only integer columns and timestamp columns can be used as ttl_col - // TODO(YT) Ttl_duration supports datetime type - if (col.type.type != nebula::cpp2::SupportedType::INT && - col.type.type != nebula::cpp2::SupportedType::TIMESTAMP) { - return Status::Error("Ttl column type illegal"); - } - schema.schema_prop.set_ttl_col(ttlColName); - return Status::OK(); - } - } - return Status::Error("Ttl column name not exist in columns"); -} - - -// static -Status SchemaHelper::alterSchema(const std::vector<AlterSchemaOptItem*>& schemaOpts, - const std::vector<SchemaPropItem*>& schemaProps, - std::vector<nebula::meta::cpp2::AlterSchemaItem>& options, - nebula::cpp2::SchemaProp& prop) { - for (auto& schemaOpt : schemaOpts) { - nebula::meta::cpp2::AlterSchemaItem schemaItem; - auto opType = schemaOpt->toType(); - schemaItem.set_op(opType); - nebula::cpp2::Schema schema; - if (opType == nebula::meta::cpp2::AlterSchemaOp::DROP) { - const auto& colNames = schemaOpt->columnNames(); - for (auto& colName : colNames) { - nebula::cpp2::ColumnDef column; - column.name = *colName; - schema.columns.emplace_back(std::move(column)); - } - } else { - const auto& specs = schemaOpt->columnSpecs(); - for (auto& spec : specs) { - nebula::cpp2::ColumnDef column; - column.name = *spec->name(); - column.type.type = columnTypeToSupportedType(spec->type()); - schema.columns.emplace_back(std::move(column)); - } - } - - schemaItem.set_schema(std::move(schema)); - options.emplace_back(std::move(schemaItem)); - } - - for (auto& schemaProp : schemaProps) { - auto propType = schemaProp->getPropType(); - StatusOr<int64_t> retInt; - StatusOr<std::string> retStr; - int ttlDuration; - switch (propType) { - case SchemaPropItem::TTL_DURATION: - retInt = schemaProp->getTtlDuration(); - if (!retInt.ok()) { - return retInt.status(); - } - ttlDuration = retInt.value(); - prop.set_ttl_duration(ttlDuration); - break; - case SchemaPropItem::TTL_COL: - // Check the legality of the column in meta - retStr = schemaProp->getTtlCol(); - if (!retStr.ok()) { - return retStr.status(); - } - prop.set_ttl_col(retStr.value()); - break; - default: - return Status::Error("Property type not support"); - } - } - return Status::OK(); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/SchemaHelper.h b/src/executor/SchemaHelper.h deleted file mode 100644 index 057bc44a95dafb7bb040abd89e3e587bb45026f8..0000000000000000000000000000000000000000 --- a/src/executor/SchemaHelper.h +++ /dev/null @@ -1,44 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_SCHEMAHELPER_H_ -#define GRAPH_SCHEMAHELPER_H_ - -#include "base/Base.h" -#include "base/Status.h" -#include "gen-cpp2/common_types.h" -#include "parser/MaintainSentences.h" - -/** - * SchemaHelper is the interface of `create schema' used in `create tag/edge' and `alter schema' - * used in `alter tag/edge'. - */ - -namespace nebula { -namespace graph { - -class SchemaHelper final { -public: - static Status createSchema(const std::vector<ColumnSpecification*>& specs, - const std::vector<SchemaPropItem*>& schemaProps, - nebula::cpp2::Schema& schema); - - static Status setTTLDuration(SchemaPropItem* schemaProp, nebula::cpp2::Schema& schema); - - static Status setTTLCol(SchemaPropItem* schemaProp, nebula::cpp2::Schema& schema); - - static Status alterSchema(const std::vector<AlterSchemaOptItem*>& schemaOpts, - const std::vector<SchemaPropItem*>& schemaProps, - std::vector<nebula::meta::cpp2::AlterSchemaItem>& options, - nebula::cpp2::SchemaProp& schemaProp); - - static nebula::cpp2::SupportedType columnTypeToSupportedType(nebula::ColumnType type); -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_SCHEMAHELPER_H_ diff --git a/src/executor/SequentialExecutor.cpp b/src/executor/SequentialExecutor.cpp deleted file mode 100644 index 9071daeef0b530dba210bbc2ce13369bce84647b..0000000000000000000000000000000000000000 --- a/src/executor/SequentialExecutor.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/SequentialExecutor.h" -#include "graph/GoExecutor.h" -#include "graph/PipeExecutor.h" -#include "graph/UseExecutor.h" - -namespace nebula { -namespace graph { - -SequentialExecutor::SequentialExecutor(SequentialSentences *sentences, - ExecutionContext *ectx) : Executor(ectx) { - sentences_ = sentences; -} - - -Status SequentialExecutor::prepare() { - for (auto i = 0U; i < sentences_->sentences_.size(); i++) { - auto *sentence = sentences_->sentences_[i].get(); - auto executor = makeExecutor(sentence); - if (executor == nullptr) { - return Status::Error("The statement has not been implemented"); - } - auto status = executor->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - executor->name(), status.toString().c_str()); - return status; - } - executors_.emplace_back(std::move(executor)); - } - /** - * For the time being, we execute sentences one by one. We may allow concurrent - * or out of order execution in the future. - */ - // For an executor except the last one, it executes the next one on finished. - // If any fails, the whole execution would abort. - auto onError = [this] (Status status) { - DCHECK(onError_); - onError_(std::move(status)); - }; - for (auto i = 0U; i < executors_.size() - 1; i++) { - auto onFinish = [this, current = i, next = i + 1] (Executor::ProcessControl ctr) { - switch (ctr) { - case Executor::ProcessControl::kReturn: { - DCHECK(onFinish_); - respExecutorIndex_ = current; - onFinish_(ctr); - break; - } - case Executor::ProcessControl::kNext: - default: { - executors_[next]->execute(); - break; - } - } - }; - executors_[i]->setOnFinish(onFinish); - executors_[i]->setOnError(onError); - } - // The whole execution is done upon the last executor finishes. - auto onFinish = [this] (Executor::ProcessControl ctr) { - DCHECK(onFinish_); - respExecutorIndex_ = executors_.size() - 1; - onFinish_(ctr); - }; - executors_.back()->setOnFinish(onFinish); - executors_.back()->setOnError(onError); - - return Status::OK(); -} - - -void SequentialExecutor::execute() { - executors_.front()->execute(); -} - - -void SequentialExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - executors_[respExecutorIndex_]->setupResponse(resp); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/SequentialExecutor.h b/src/executor/SequentialExecutor.h deleted file mode 100644 index 094328aa1b4304ae2d3e77777ff06fb6f96207f5..0000000000000000000000000000000000000000 --- a/src/executor/SequentialExecutor.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_SEQUENTIALEXECUTOR_H_ -#define GRAPH_SEQUENTIALEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - - -namespace nebula { -namespace graph { - -class SequentialExecutor final : public Executor { -public: - SequentialExecutor(SequentialSentences *sentences, ExecutionContext *ectx); - - const char* name() const override { - return "SequentialExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - SequentialSentences *sentences_{nullptr}; - std::vector<std::unique_ptr<Executor>> executors_; - uint32_t respExecutorIndex_{0}; -}; - - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_SEQUENTIALEXECUTOR_H_ diff --git a/src/executor/SetExecutor.cpp b/src/executor/SetExecutor.cpp deleted file mode 100644 index 6762b177bed1b63f303a9d42efab9ea75c6762ae..0000000000000000000000000000000000000000 --- a/src/executor/SetExecutor.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/SetExecutor.h" - -namespace nebula { -namespace graph { -namespace cpp2 { -bool RowValue::operator<(const RowValue& rhs) const { - auto &lhs = *this; - return (lhs.columns < rhs.columns); -} -} - -SetExecutor::SetExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<SetSentence*>(sentence); -} - -Status SetExecutor::prepare() { - left_ = makeTraverseExecutor(sentence_->left()); - right_ = makeTraverseExecutor(sentence_->right()); - DCHECK(left_ != nullptr); - DCHECK(right_ != nullptr); - - setLeft(); - setRight(); - - auto status = left_->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - left_->name(), status.toString().c_str()); - return status; - } - - status = right_->prepare(); - if (!status.ok()) { - FLOG_ERROR("Prepare executor `%s' failed: %s", - right_->name(), status.toString().c_str()); - return status; - } - - return Status::OK(); -} - -void SetExecutor::setLeft() { - futures_.emplace_back(leftP_.getFuture()); - auto onFinish = [this] (Executor::ProcessControl ctr) { - UNUSED(ctr); - leftP_.setValue(); - }; - - auto onResult = [this] (std::unique_ptr<InterimResult> result) { - DCHECK(result != nullptr); - this->leftResult_ = std::move(result); - VLOG(3) << "Left result set."; - }; - - auto onError = [this] (Status s) { - VLOG(3) << "Left error:" << s.toString(); - leftS_ = std::move(s); - leftP_.setValue(); - }; - - left_->setOnResult(onResult); - left_->setOnFinish(onFinish); - left_->setOnError(onError); -} - -void SetExecutor::setRight() { - futures_.emplace_back(rightP_.getFuture()); - auto onFinish = [this] (Executor::ProcessControl ctr) { - UNUSED(ctr); - rightP_.setValue(); - }; - - auto onResult = [this] (std::unique_ptr<InterimResult> result) { - DCHECK(result != nullptr); - this->rightResult_ = std::move(result); - VLOG(3) << "Right result set."; - }; - - auto onError = [this] (Status s) { - VLOG(3) << "Right error: " << s.toString(); - rightS_ = std::move(s); - rightP_.setValue(); - }; - - right_->setOnResult(onResult); - right_->setOnFinish(onFinish); - right_->setOnError(onError); -} - -void SetExecutor::execute() { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - onError_(std::move(status)); - return; - } - - auto *runner = ectx()->rctx()->runner(); - runner->add([this] () mutable { left_->execute(); }); - runner->add([this] () mutable { right_->execute(); }); - - auto cb = [this] (auto &&result) { - UNUSED(result); - if (!leftS_.ok() || !rightS_.ok()) { - std::string msg; - msg += "lhs has error: "; - msg += leftS_.toString(); - msg += " rhs has error: "; - msg += rightS_.toString(); - onError_(Status::Error(msg)); - return; - } - - if (leftResult_ == nullptr || rightResult_ == nullptr) { - // Should not reach here. - LOG(ERROR) << "Get null input."; - onError_(Status::Error("Get null input.")); - return; - } - - colNames_ = leftResult_->getColNames(); - // If the column count not match, we will not do set op. - if (colNames_.size() != rightResult_->getColNames().size()) { - std::string err = "Field count not match."; - LOG(ERROR) << err; - onError_(Status::Error(std::move(err))); - return; - } - if (!leftResult_->hasData() && !rightResult_->hasData()) { - VLOG(3) << "Set op no input."; - onEmptyInputs(); - return; - } - - // Set op share the same priority, they would execute sequentially. - switch (sentence_->op()) { - case SetSentence::Operator::UNION: - doUnion(); - break; - case SetSentence::Operator::INTERSECT: - doIntersect(); - break; - case SetSentence::Operator::MINUS: - doMinus(); - break; - default: - LOG(FATAL) << "Unknown operator: " << sentence_->op(); - } - }; - folly::collectAll(futures_).via(runner).thenValue(cb); -} - -void SetExecutor::doUnion() { - VLOG(3) << "Do Union."; - if (!leftResult_->hasData()) { - VLOG(3) << "Union has right result."; - rightResult_->setColNames(std::move(colNames_)); - finishExecution(std::move(rightResult_)); - return; - } - - if (!rightResult_->hasData()) { - VLOG(3) << "Union has left result."; - finishExecution(std::move(leftResult_)); - return; - } - - Status status = checkSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - - auto ret = leftResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto leftRows = std::move(ret).value(); - - ret = rightResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto rightRows = std::move(ret).value(); - - if (!castingMap_.empty()) { - auto stat = doCasting(rightRows); - if (!stat.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - } - - leftRows.insert(leftRows.end(), - std::make_move_iterator(rightRows.begin()), - std::make_move_iterator(rightRows.end())); - if (sentence_->distinct()) { - doDistinct(leftRows); - } - - finishExecution(std::move(leftRows)); - return; -} - -Status SetExecutor::checkSchema() { - auto leftSchema = leftResult_->schema(); - auto rightSchema = rightResult_->schema(); - auto leftIter = leftSchema->begin(); - auto rightIter = rightSchema->begin(); - - auto index = 0u; - while (leftIter && rightIter) { - if (leftIter->getType() != rightIter->getType()) { - // Implicit type casting would happen if the type do no match. - // If type casting failed. the whole statement would fail. - castingMap_.emplace_back(index, leftIter->getType()); - } - - ++index; - ++leftIter; - ++rightIter; - } - - if (leftIter || rightIter) { - // If the column count not match, we will not do set op. - return Status::Error("Field count not match."); - } - - resultSchema_ = std::move(leftSchema); - - return Status::OK(); -} - -Status SetExecutor::doCasting(std::vector<cpp2::RowValue> &rows) const { - for (auto &row : rows) { - auto cols = row.get_columns(); - for (auto &pair : castingMap_) { - auto stat = - InterimResult::castTo(&cols[pair.first], pair.second.get_type()); - if (!stat.ok()) { - return stat; - } - } - row.set_columns(std::move(cols)); - } - - return Status::OK(); -} - - -void SetExecutor::doDistinct(std::vector<cpp2::RowValue> &rows) const { - std::sort(rows.begin(), rows.end()); - auto it = std::unique(rows.begin(), rows.end()); - rows.erase(it, rows.end()); -} - -void SetExecutor::doIntersect() { - VLOG(3) << "Do InterSect."; - if (!leftResult_->hasData() || !rightResult_->hasData()) { - VLOG(3) << "No intersect."; - onEmptyInputs(); - return; - } - - Status status = checkSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - - auto ret = leftResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto leftRows = std::move(ret).value(); - - ret = rightResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto rightRows = std::move(ret).value(); - - if (!castingMap_.empty()) { - Status stat = doCasting(rightRows); - if (!stat.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - } - - std::vector<cpp2::RowValue> rows; - for (auto &lr : leftRows) { - for (auto &rr : rightRows) { - if (rr == lr) { - rows.emplace_back(std::move(rr)); - break; - } - } - } - - finishExecution(std::move(rows)); - return; -} - -void SetExecutor::doMinus() { - VLOG(3) << "Do Minus."; - if (!leftResult_->hasData()) { - VLOG(3) << "Minus has only right result."; - onEmptyInputs(); - return; - } - - if (!rightResult_->hasData()) { - VLOG(3) << "Minus has left result."; - finishExecution(std::move(leftResult_)); - return; - } - - Status status = checkSchema(); - if (!status.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - - auto ret = leftResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto leftRows = std::move(ret).value(); - - ret = rightResult_->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - auto rightRows = std::move(ret).value(); - - if (!castingMap_.empty()) { - Status stat = doCasting(rightRows); - if (!stat.ok()) { - DCHECK(onError_); - onError_(status); - return; - } - } - - for (auto &rr : rightRows) { - for (auto iter = leftRows.begin(); iter < leftRows.end();) { - if (rr == *iter) { - iter = leftRows.erase(iter); - } else { - ++iter; - } - } - } - - finishExecution(std::move(leftRows)); - return; -} - -void SetExecutor::onEmptyInputs() { - if (onResult_) { - auto result = std::make_unique<InterimResult>(std::move(colNames_)); - onResult_(std::move(result)); - } else if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(colNames_)); - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - -void SetExecutor::finishExecution(std::unique_ptr<InterimResult> result) { - if (result == nullptr) { - result = std::make_unique<InterimResult>(std::move(colNames_)); - } - if (onResult_) { - onResult_(std::move(result)); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - auto colNames = result->getColNames(); - resp_->set_column_names(std::move(colNames)); - if (result->hasData()) { - auto ret = result->getRows(); - if (!ret.ok()) { - DCHECK(onError_); - onError_(std::move(ret).status()); - return; - } - resp_->set_rows(std::move(ret).value()); - } - } - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - -void SetExecutor::finishExecution(std::vector<cpp2::RowValue> rows) { - if (onResult_) { - auto ret = InterimResult::getInterim(resultSchema_, rows); - if (!ret.ok()) { - LOG(ERROR) << "Get Interim result failed."; - onError_(std::move(ret).status()); - return; - } - onResult_(std::move(ret).value()); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(colNames_)); - resp_->set_rows(std::move(rows)); - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - -void SetExecutor::feedResult(std::unique_ptr<InterimResult> result) { - // Feed input for set operator is an act of reservation. - UNUSED(result); - LOG(FATAL) << "Set operation not support input yet."; -} - -void SetExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(colNames_)); - return; - } - - resp = std::move(*resp_); -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/SetExecutor.h b/src/executor/SetExecutor.h deleted file mode 100644 index 62cc819411a73b408cd82c4ca072260c387eb976..0000000000000000000000000000000000000000 --- a/src/executor/SetExecutor.h +++ /dev/null @@ -1,78 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_SETEXECUTOR_H_ -#define GRAPH_SETEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "meta/SchemaProviderIf.h" -#include <boost/thread/latch.hpp> - -namespace nebula { -namespace graph { - -class SetExecutor final : public TraverseExecutor { -public: - SetExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "SetExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - void setLeft(); - - void setRight(); - - void finishExecution(std::unique_ptr<InterimResult> result); - - void finishExecution(std::vector<cpp2::RowValue> leftRows); - - void doUnion(); - - void doIntersect(); - - void doMinus(); - - Status checkSchema(); - - Status doCasting(std::vector<cpp2::RowValue> &rows) const; - - void doDistinct(std::vector<cpp2::RowValue> &rows) const; - - void onEmptyInputs(); - -private: - SetSentence *sentence_{nullptr}; - std::unique_ptr<TraverseExecutor> left_; - std::unique_ptr<TraverseExecutor> right_; - std::unique_ptr<InterimResult> leftResult_; - std::unique_ptr<InterimResult> rightResult_; - folly::Promise<folly::Unit> leftP_; - folly::Promise<folly::Unit> rightP_; - std::vector<folly::Future<folly::Unit>> futures_; - Status leftS_; - Status rightS_; - std::vector<std::pair<uint64_t, nebula::cpp2::ValueType>> castingMap_; - std::vector<std::string> colNames_; - std::shared_ptr<const meta::SchemaProviderIf> resultSchema_; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_SETEXECUTOR_H_ diff --git a/src/executor/ShowExecutor.cpp b/src/executor/ShowExecutor.cpp deleted file mode 100644 index a1b44f026858a078fd1c4fd3eb50c60f83cfac52..0000000000000000000000000000000000000000 --- a/src/executor/ShowExecutor.cpp +++ /dev/null @@ -1,646 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "graph/ShowExecutor.h" -#include "network/NetworkUtils.h" - -namespace nebula { -namespace graph { - -using nebula::network::NetworkUtils; - -ShowExecutor::ShowExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<ShowSentence*>(sentence); -} - - -Status ShowExecutor::prepare() { - return Status::OK(); -} - - -void ShowExecutor::execute() { - if (sentence_->showType() == ShowSentence::ShowType::kShowParts || - sentence_->showType() == ShowSentence::ShowType::kShowTags || - sentence_->showType() == ShowSentence::ShowType::kShowEdges || - sentence_->showType() == ShowSentence::ShowType::kShowCreateTag || - sentence_->showType() == ShowSentence::ShowType::kShowCreateEdge) { - auto status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - DCHECK(onError_); - onError_(std::move(status)); - return; - } - } - auto showType = sentence_->showType(); - switch (showType) { - case ShowSentence::ShowType::kShowHosts: - showHosts(); - break; - case ShowSentence::ShowType::kShowSpaces: - showSpaces(); - break; - case ShowSentence::ShowType::kShowParts: - showParts(); - break; - case ShowSentence::ShowType::kShowTags: - showTags(); - break; - case ShowSentence::ShowType::kShowEdges: - showEdges(); - break; - case ShowSentence::ShowType::kShowUsers: - case ShowSentence::ShowType::kShowUser: - case ShowSentence::ShowType::kShowRoles: - // TODO(boshengchen) - break; - case ShowSentence::ShowType::kShowCreateSpace: - showCreateSpace(); - break; - case ShowSentence::ShowType::kShowCreateTag: - showCreateTag(); - break; - case ShowSentence::ShowType::kShowCreateEdge: - showCreateEdge(); - break; - case ShowSentence::ShowType::kShowSnapshots: - showSnapshots(); - break; - case ShowSentence::ShowType::kUnknown: - onError_(Status::Error("Type unknown")); - break; - // intentionally no `default' - } -} - - -void ShowExecutor::showHosts() { - auto future = ectx()->getMetaClient()->listHosts(); - auto *runner = ectx()->rctx()->runner(); - constexpr static char kNoValidPart[] = "No valid partition"; - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto hostItems = std::move(resp).value(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"Ip", "Port", "Status", "Leader count", - "Leader distribution", "Partition distribution"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - std::sort(hostItems.begin(), hostItems.end(), [](const auto& a, const auto& b) { - // sort with online/offline and ip - if (a.get_status() == b.get_status()) { - return a.hostAddr.ip < b.hostAddr.ip; - } - return a.get_status() < b.get_status(); - }); - - for (auto& item : hostItems) { - std::vector<cpp2::ColumnValue> row; - row.resize(6); - auto hostAddr = HostAddr(item.hostAddr.ip, item.hostAddr.port); - row[0].set_str(NetworkUtils::ipFromHostAddr(hostAddr)); - row[1].set_str(folly::to<std::string>(NetworkUtils::portFromHostAddr(hostAddr))); - switch (item.get_status()) { - case meta::cpp2::HostStatus::ONLINE: - row[2].set_str("online"); - break; - case meta::cpp2::HostStatus::OFFLINE: - case meta::cpp2::HostStatus::UNKNOWN: - row[2].set_str("offline"); - break; - } - - int32_t leaderCount = 0; - std::string leaders; - for (auto& spaceEntry : item.get_leader_parts()) { - leaderCount += spaceEntry.second.size(); - leaders += spaceEntry.first + ": " + - folly::to<std::string>(spaceEntry.second.size()) + ", "; - } - if (!leaders.empty()) { - leaders.resize(leaders.size() - 2); - } - - row[3].set_integer(leaderCount); - - std::string parts; - for (auto& spaceEntry : item.get_all_parts()) { - parts += spaceEntry.first + ": " + - folly::to<std::string>(spaceEntry.second.size()) + ", "; - } - if (!parts.empty()) { - parts.resize(parts.size() - 2); - } else { - // if there is no valid parition on a host at all - leaders = kNoValidPart; - parts = kNoValidPart; - } - row[4].set_str(leaders); - row[5].set_str(parts); - - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showSpaces() { - auto future = ectx()->getMetaClient()->listSpaces(); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto retShowSpaces = std::move(resp).value(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"Name"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - - for (auto &space : retShowSpaces) { - std::vector<cpp2::ColumnValue> row; - row.emplace_back(); - row.back().set_str(std::move(space.second)); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showParts() { - auto spaceId = ectx()->rctx()->session()->space(); - auto future = ectx()->getMetaClient()->listParts(spaceId); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto partItems = std::move(resp).value(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"Partition ID", "Leader", "Peers", "Losts"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - - std::sort(partItems.begin(), partItems.end(), - [] (const auto& a, const auto& b) { - return a.get_part_id() < b.get_part_id(); - }); - - for (auto& item : partItems) { - std::vector<cpp2::ColumnValue> row; - row.resize(4); - row[0].set_integer(item.get_part_id()); - - if (item.__isset.leader) { - auto leader = item.get_leader(); - std::vector<HostAddr> leaders = {{leader->ip, leader->port}}; - std::string leaderStr = NetworkUtils::toHosts(leaders); - row[1].set_str(leaderStr); - } else { - row[1].set_str(""); - } - - std::vector<HostAddr> peers; - for (auto& peer : item.get_peers()) { - peers.emplace_back(peer.ip, peer.port); - } - std::string peersStr = NetworkUtils::toHosts(peers); - row[2].set_str(peersStr); - - std::vector<HostAddr> losts; - for (auto& lost : item.get_losts()) { - losts.emplace_back(lost.ip, lost.port); - } - std::string lostsStr = NetworkUtils::toHosts(losts); - row[3].set_str(lostsStr); - - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showTags() { - auto spaceId = ectx()->rctx()->session()->space(); - auto future = ectx()->getMetaClient()->listTagSchemas(spaceId); - auto *runner = ectx()->rctx()->runner(); - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto value = std::move(resp).value(); - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"ID", "Name"}; - resp_->set_column_names(std::move(header)); - - std::map<nebula::cpp2::TagID, std::string> tagItems; - for (auto &tag : value) { - tagItems.emplace(tag.get_tag_id(), tag.get_tag_name()); - } - - for (auto &item : tagItems) { - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_integer(item.first); - row[1].set_str(item.second); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showEdges() { - auto spaceId = ectx()->rctx()->session()->space(); - auto future = ectx()->getMetaClient()->listEdgeSchemas(spaceId); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto value = std::move(resp).value(); - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"ID", "Name"}; - resp_->set_column_names(std::move(header)); - - std::map<nebula::cpp2::EdgeType, std::string> edgeItems; - for (auto &edge : value) { - edgeItems.emplace(edge.get_edge_type(), edge.get_edge_name()); - } - - for (auto &item : edgeItems) { - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_integer(item.first); - row[1].set_str(item.second); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showCreateSpace() { - auto *name = sentence_->getName(); - auto future = ectx()->getMetaClient()->getSpace(*name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"Space", "Create Space"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - std::vector<cpp2::ColumnValue> row; - row.resize(2); - auto properties = resp.value().get_properties(); - row[0].set_str(properties.get_space_name()); - - std::string buf; - buf.reserve(256); - buf += folly::stringPrintf("CREATE SPACE %s (", properties.get_space_name().c_str()); - buf += "partition_num = "; - buf += folly::to<std::string>(properties.get_partition_num()); - buf += ", "; - buf += "replica_factor = "; - buf += folly::to<std::string>(properties.get_replica_factor()); - buf += ")"; - - row[1].set_str(buf);; - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showCreateTag() { - auto *name = sentence_->getName(); - auto spaceId = ectx()->rctx()->session()->space(); - - // Get the lastest ver - auto future = ectx()->getMetaClient()->getTagSchema(spaceId, *name); - auto *runner = ectx()->rctx()->runner(); - - - auto cb = [this] (auto &&resp) { - auto *tagName = sentence_->getName(); - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"Tag", "Create Tag"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str(*tagName); - - std::string buf; - buf.reserve(256); - buf += folly::stringPrintf("CREATE TAG %s (\n", tagName->c_str()); - - auto schema = resp.value(); - for (auto& item : schema.columns) { - buf += " "; - buf += item.name; - buf += " "; - buf += valueTypeToString(item.type); - buf += ",\n"; - } - - if (!schema.columns.empty()) { - buf.resize(buf.size() -2); - buf += "\n"; - } - buf += ") "; - nebula::cpp2::SchemaProp prop = schema.schema_prop; - buf += "ttl_duration = "; - if (prop.get_ttl_duration()) { - buf += folly::to<std::string>(*prop.get_ttl_duration()); - } else { - buf += "0"; - } - buf += ", ttl_col = "; - if (prop.get_ttl_col() && !(prop.get_ttl_col()->empty())) { - buf += *prop.get_ttl_col(); - } else { - buf += "\"\""; - } - - row[1].set_str(buf); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::showCreateEdge() { - auto *name = sentence_->getName(); - auto spaceId = ectx()->rctx()->session()->space(); - - // Get the lastest ver - auto future = ectx()->getMetaClient()->getEdgeSchema(spaceId, *name); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - auto *edgeName = sentence_->getName(); - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> header{"Edge", "Create Edge"}; - resp_->set_column_names(std::move(header)); - - std::vector<cpp2::RowValue> rows; - std::vector<cpp2::ColumnValue> row; - row.resize(2); - row[0].set_str(*edgeName); - - std::string buf; - buf.reserve(256); - buf += folly::stringPrintf("CREATE EDGE %s (\n", edgeName->c_str()); - - auto schema = resp.value(); - for (auto& item : schema.columns) { - buf += " "; - buf += item.name; - buf += " "; - buf += valueTypeToString(item.type); - buf += ",\n"; - } - - if (!schema.columns.empty()) { - buf.resize(buf.size() -2); - buf += "\n"; - } - buf += ") "; - nebula::cpp2::SchemaProp prop = schema.schema_prop; - buf += "ttl_duration = "; - if (prop.get_ttl_duration()) { - buf += folly::to<std::string>(*prop.get_ttl_duration()); - } else { - buf += "0"; - } - buf += ", ttl_col = "; - if (prop.get_ttl_col() && !(prop.get_ttl_col()->empty())) { - buf += *prop.get_ttl_col(); - } else { - buf += "\"\""; - } - - row[1].set_str(buf); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -void ShowExecutor::showSnapshots() { - auto future = ectx()->getMetaClient()->listSnapshots(); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(std::move(resp).status()); - return; - } - - auto getStatus = [](meta::cpp2::SnapshotStatus status) -> std::string { - std::string str; - switch (status) { - case meta::cpp2::SnapshotStatus::INVALID : - str = "INVALID"; - break; - case meta::cpp2::SnapshotStatus::VALID : - str = "VALID"; - break; - } - return str; - }; - - auto retShowSnapshots = std::move(resp).value(); - std::vector<cpp2::RowValue> rows; - std::vector<std::string> header{"Name", "Status", "Hosts"}; - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - resp_->set_column_names(std::move(header)); - for (auto &snapshot : retShowSnapshots) { - std::vector<cpp2::ColumnValue> row; - row.resize(3); - row[0].set_str(snapshot.name); - row[1].set_str(getStatus(snapshot.status)); - row[2].set_str(snapshot.hosts); - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error(folly::stringPrintf("Internal error : %s", - e.what().c_str()))); - return; - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void ShowExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/ShowExecutor.h b/src/executor/ShowExecutor.h deleted file mode 100644 index 213c2eb4f03286eaa20a26fe6d5a0f8b6cd0ac6b..0000000000000000000000000000000000000000 --- a/src/executor/ShowExecutor.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_SHOWEXECUTOR_H_ -#define GRAPH_SHOWEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class ShowExecutor final : public Executor { -public: - ShowExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "ShowExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - void showHosts(); - void showSpaces(); - void showParts(); - void showTags(); - void showEdges(); - void showCreateSpace(); - void showCreateTag(); - void showCreateEdge(); - void showSnapshots(); - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - ShowSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_SHOWEXECUTOR_H_ diff --git a/src/executor/TraverseExecutor.cpp b/src/executor/TraverseExecutor.cpp deleted file mode 100644 index 7921e312d8effeaed2d9da915f2647a9b74759f5..0000000000000000000000000000000000000000 --- a/src/executor/TraverseExecutor.cpp +++ /dev/null @@ -1,287 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "parser/TraverseSentences.h" -#include "dataman/RowReader.h" -#include "dataman/RowWriter.h" -#include "graph/GoExecutor.h" -#include "graph/PipeExecutor.h" -#include "graph/OrderByExecutor.h" -#include "graph/FetchVerticesExecutor.h" -#include "graph/FetchEdgesExecutor.h" -#include "dataman/RowReader.h" -#include "dataman/RowWriter.h" -#include "graph/SetExecutor.h" -#include "graph/FindExecutor.h" -#include "graph/MatchExecutor.h" -#include "graph/FindPathExecutor.h" -#include "graph/LimitExecutor.h" -#include "graph/YieldExecutor.h" -#include "graph/GroupByExecutor.h" - -namespace nebula { -namespace graph { - -std::unique_ptr<TraverseExecutor> TraverseExecutor::makeTraverseExecutor(Sentence *sentence) { - return makeTraverseExecutor(sentence, ectx()); -} - - -// static -std::unique_ptr<TraverseExecutor> -TraverseExecutor::makeTraverseExecutor(Sentence *sentence, ExecutionContext *ectx) { - auto kind = sentence->kind(); - std::unique_ptr<TraverseExecutor> executor; - switch (kind) { - case Sentence::Kind::kGo: - executor = std::make_unique<GoExecutor>(sentence, ectx); - break; - case Sentence::Kind::kPipe: - executor = std::make_unique<PipeExecutor>(sentence, ectx); - break; - case Sentence::Kind::kOrderBy: - executor = std::make_unique<OrderByExecutor>(sentence, ectx); - break; - case Sentence::Kind::kFetchVertices: - executor = std::make_unique<FetchVerticesExecutor>(sentence, ectx); - break; - case Sentence::Kind::kFetchEdges: - executor = std::make_unique<FetchEdgesExecutor>(sentence, ectx); - break; - case Sentence::Kind::kSet: - executor = std::make_unique<SetExecutor>(sentence, ectx); - break; - case Sentence::Kind::kMatch: - executor = std::make_unique<MatchExecutor>(sentence, ectx); - break; - case Sentence::Kind::kFind: - executor = std::make_unique<FindExecutor>(sentence, ectx); - break; - case Sentence::Kind::kYield: - executor = std::make_unique<YieldExecutor>(sentence, ectx); - break; - case Sentence::Kind::kFindPath: - executor = std::make_unique<FindPathExecutor>(sentence, ectx); - break; - case Sentence::Kind::kLimit: - executor = std::make_unique<LimitExecutor>(sentence, ectx); - break; - case Sentence::Kind::KGroupBy: - executor = std::make_unique<GroupByExecutor>(sentence, ectx); - break; - case Sentence::Kind::kUnknown: - LOG(FATAL) << "Sentence kind unknown"; - break; - default: - LOG(FATAL) << "Sentence kind illegal: " << kind; - break; - } - return executor; -} - -Status Collector::collect(VariantType &var, RowWriter *writer) { - switch (var.which()) { - case VAR_INT64: - (*writer) << boost::get<int64_t>(var); - break; - case VAR_DOUBLE: - (*writer) << boost::get<double>(var); - break; - case VAR_BOOL: - (*writer) << boost::get<bool>(var); - break; - case VAR_STR: - (*writer) << boost::get<std::string>(var); - break; - default: - std::string errMsg = - folly::stringPrintf("Unknown VariantType: %d", var.which()); - LOG(ERROR) << errMsg; - return Status::Error(errMsg); - } - return Status::OK(); -} - -OptVariantType Collector::getProp(const meta::SchemaProviderIf *schema, - const std::string &prop, - const RowReader *reader) { - DCHECK(reader != nullptr); - DCHECK(schema != nullptr); - using nebula::cpp2::SupportedType; - auto type = schema->getFieldType(prop).type; - switch (type) { - case SupportedType::BOOL: { - bool v; - reader->getBool(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return v; - } - case SupportedType::TIMESTAMP: - case SupportedType::INT: { - int64_t v; - reader->getInt(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return v; - } - case SupportedType::VID: { - VertexID v; - reader->getVid(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return v; - } - case SupportedType::FLOAT: { - float v; - reader->getFloat(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return static_cast<double>(v); - } - case SupportedType::DOUBLE: { - double v; - reader->getDouble(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return v; - } - case SupportedType::STRING: { - folly::StringPiece v; - reader->getString(prop, v); - VLOG(3) << "get prop: " << prop << ", value: " << v; - return v.toString(); - } - default: - std::string errMsg = - folly::stringPrintf("Unknown type: %d", static_cast<int32_t>(type)); - LOG(ERROR) << errMsg; - return Status::Error(errMsg); - } -} - -Status Collector::getSchema(const std::vector<VariantType> &vals, - const std::vector<std::string> &colNames, - const std::vector<nebula::cpp2::SupportedType> &colTypes, - SchemaWriter *outputSchema) { - DCHECK(outputSchema != nullptr); - DCHECK_EQ(vals.size(), colNames.size()); - DCHECK_EQ(vals.size(), colTypes.size()); - using nebula::cpp2::SupportedType; - auto index = 0u; - for (auto &it : colTypes) { - SupportedType type; - if (it == SupportedType::UNKNOWN) { - switch (vals[index].which()) { - case VAR_INT64: - // all integers in InterimResult are regarded as type of INT - type = SupportedType::INT; - break; - case VAR_DOUBLE: - type = SupportedType::DOUBLE; - break; - case VAR_BOOL: - type = SupportedType::BOOL; - break; - case VAR_STR: - type = SupportedType::STRING; - break; - default: - std::string errMsg = - folly::stringPrintf("Unknown VariantType: %d", vals[index].which()); - LOG(ERROR) << errMsg; - return Status::Error(errMsg); - } - } else { - type = it; - } - - outputSchema->appendCol(colNames[index], type); - index++; - } - return Status::OK(); -} - -Status YieldClauseWrapper::prepare( - const InterimResult *inputs, - const VariableHolder *varHolder, - std::vector<YieldColumn*> &yields) { - auto cols = clause_->columns(); - yieldColsHolder_ = std::make_unique<YieldColumns>(); - for (auto *col : cols) { - if (col->expr()->isInputExpression()) { - if (inputs == nullptr) { - return Status::Error("Inputs nullptr."); - } - if (needAllPropsFromInput(col, inputs, yields)) { - continue; - } - } else if (col->expr()->isVariableExpression()) { - if (varHolder == nullptr) { - return Status::Error("VarHolder nullptr."); - } - auto ret = needAllPropsFromVar(col, varHolder, yields); - if (!ret.ok()) { - return std::move(ret).status(); - } - if (ret.value()) { - continue; - } - } - yields.emplace_back(col); - } - - return Status::OK(); -} - -bool YieldClauseWrapper::needAllPropsFromInput(const YieldColumn *col, - const InterimResult *inputs, - std::vector<YieldColumn*> &yields) { - auto *inputExpr = static_cast<InputPropertyExpression*>(col->expr()); - auto *colName = inputExpr->prop(); - if (*colName == "*") { - auto colNames = inputs->getColNames(); - for (auto &prop : colNames) { - Expression *expr = new InputPropertyExpression(new std::string(prop)); - YieldColumn *column = new YieldColumn(expr); - yieldColsHolder_->addColumn(column); - yields.emplace_back(column); - } - return true; - } - return false; -} - -StatusOr<bool> YieldClauseWrapper::needAllPropsFromVar( - const YieldColumn *col, - const VariableHolder *varHolder, - std::vector<YieldColumn*> &yields) { - auto *variableExpr = static_cast<VariablePropertyExpression*>(col->expr()); - auto *colName = variableExpr->prop(); - bool existing = false; - auto *varname = variableExpr->alias(); - auto varInputs = varHolder->get(*varname, &existing); - if (varInputs == nullptr && !existing) { - return Status::Error("Variable `%s' not defined.", varname->c_str()); - } - if (*colName == "*") { - if (varInputs != nullptr) { - auto colNames = varInputs->getColNames(); - for (auto &prop : colNames) { - auto *alias = new std::string(*(variableExpr->alias())); - Expression *expr = - new VariablePropertyExpression(alias, new std::string(prop)); - YieldColumn *column = new YieldColumn(expr); - yieldColsHolder_->addColumn(column); - yields.emplace_back(column); - } - } else { - // should not reach here. - return Status::Error("Variable `%s' is nullptr.", varname->c_str()); - } - return true; - } - return false; -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/TraverseExecutor.h b/src/executor/TraverseExecutor.h deleted file mode 100644 index c02e708515e7d5462ef17b6e23d9ac36a5ab65f3..0000000000000000000000000000000000000000 --- a/src/executor/TraverseExecutor.h +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_TRAVERSEEXECUTOR_H_ -#define GRAPH_TRAVERSEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" -#include "graph/InterimResult.h" -#include "meta/SchemaProviderIf.h" -#include "dataman/RowReader.h" -#include "dataman/RowWriter.h" - -namespace nebula { -namespace graph { - - -class ResultSchema final { -public: - struct Column { - std::string name_; - // TODO(dutor) type - }; - - void addColumn(std::string name) { - columns_.emplace_back(); - columns_.back().name_ = std::move(name); - } - - std::string toString() const { - std::string buf; - buf.reserve(256); - for (auto &column : columns_) { - if (column.name_.empty()) { - buf += "NULL"; - } else { - buf += column.name_; - } - buf += "\t"; - } - if (!buf.empty()) { - buf.resize(buf.size() - 1); - } - return buf; - } - -private: - std::vector<Column> columns_; -}; - - -class Collector final { -public: - static Status collect(VariantType &var, RowWriter *writer); - - static OptVariantType getProp(const meta::SchemaProviderIf *schema, - const std::string &prop, - const RowReader *reader); - - static Status getSchema(const std::vector<VariantType> &vals, - const std::vector<std::string> &colNames, - const std::vector<nebula::cpp2::SupportedType> &colTypes, - SchemaWriter *outputSchema); -}; - -class YieldClauseWrapper final { -public: - explicit YieldClauseWrapper(const YieldClause *clause) { - clause_ = clause; - } - - Status prepare(const InterimResult *inputs, - const VariableHolder *varHolder, - std::vector<YieldColumn*> &yields); - -private: - bool needAllPropsFromInput(const YieldColumn *col, - const InterimResult *inputs, - std::vector<YieldColumn*> &yields); - - StatusOr<bool> needAllPropsFromVar(const YieldColumn *col, - const VariableHolder *varHolder, - std::vector<YieldColumn*> &yields); - -private: - const YieldClause *clause_; - std::unique_ptr<YieldColumns> yieldColsHolder_; -}; - -class TraverseExecutor : public Executor { -public: - explicit TraverseExecutor(ExecutionContext *ectx) : Executor(ectx) {} - - using OnResult = std::function<void(std::unique_ptr<InterimResult>)>; - - virtual void feedResult(std::unique_ptr<InterimResult> result) = 0; - - /** - * `onResult_' must be set except for the right most executor - * inside the chain of pipeline. - * - * For any TraverseExecutor, if `onResult_' is set, it means that - * some other executor depends on its execution result. Otherwise, - * it means that this executor is the right most one, whose results must - * be cached during its execution and are to be used to fill `ExecutionResponse' - * upon `setupResponse()'s invoke. - */ - void setOnResult(OnResult onResult) { - onResult_ = std::move(onResult); - } - - static std::unique_ptr<TraverseExecutor> - makeTraverseExecutor(Sentence *sentence, ExecutionContext *ectx); - -protected: - std::unique_ptr<TraverseExecutor> makeTraverseExecutor(Sentence *sentence); - -protected: - OnResult onResult_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_TRAVERSEEXECUTOR_H_ diff --git a/src/executor/UpdateEdgeExecutor.cpp b/src/executor/UpdateEdgeExecutor.cpp deleted file mode 100644 index 96c7e4a029423e60f3a0fb636256234a9a524f9c..0000000000000000000000000000000000000000 --- a/src/executor/UpdateEdgeExecutor.cpp +++ /dev/null @@ -1,289 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "base/Status.h" -#include "graph/UpdateEdgeExecutor.h" -#include "meta/SchemaManager.h" -#include "dataman/RowReader.h" -#include "dataman/RowWriter.h" -#include "storage/client/StorageClient.h" - -namespace nebula { -namespace graph { - -// UPDATE/UPSERT EDGE <vertex_id> -> <vertex_id> [@<ranking>] OF <edge_type> -// SET <update_decl> [WHEN <conditions>] [YIELD <field_list>] -UpdateEdgeExecutor::UpdateEdgeExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<UpdateEdgeSentence*>(sentence); -} - - -Status UpdateEdgeExecutor::prepare() { - DCHECK(sentence_ != nullptr); - Status status = Status::OK(); - - spaceId_ = ectx()->rctx()->session()->space(); - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setSpace(spaceId_); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - insertable_ = sentence_->getInsertable(); - auto sid = sentence_->getSrcId(); - sid->setContext(expCtx_.get()); - status = sid->prepare(); - if (!status.ok()) { - break; - } - auto src = sid->eval(); - if (!src.ok() || !Expression::isInt(src.value())) { - status = Status::Error("SRC Vertex ID should be of type integer"); - break; - } - edge_.set_src(Expression::asInt(src.value())); - - auto did = sentence_->getDstId(); - did->setContext(expCtx_.get()); - status = did->prepare(); - if (!status.ok()) { - break; - } - auto dst = did->eval(); - if (!dst.ok() || !Expression::isInt(dst.value())) { - status = Status::Error("DST Vertex ID should be of type integer"); - break; - } - edge_.set_dst(Expression::asInt(dst.value())); - edge_.set_ranking(sentence_->getRank()); - - edgeTypeName_ = sentence_->getEdgeType(); - auto edgeStatus = ectx()->schemaManager()->toEdgeType(spaceId_, *edgeTypeName_); - if (!edgeStatus.ok()) { - status = edgeStatus.status(); - break; - } - auto edgeType = edgeStatus.value(); - edge_.set_edge_type(edgeType); - - status = prepareSet(); - if (!status.ok()) { - break; - } - status = prepareWhen(); - if (!status.ok()) { - break; - } - status = prepareYield(); - if (!status.ok()) { - break; - } - } while (false); - - if (!status.ok()) { - stats::Stats::addStatsValue(ectx()->getGraphStats()->getUpdateEdgeStats(), - false, duration().elapsedInUSec()); - } - return status; -} - - -Status UpdateEdgeExecutor::prepareSet() { - auto status = Status::OK(); - auto items = sentence_->updateList()->items(); - for (auto& item : items) { - // item: name_label ASSIGN expression - storage::cpp2::UpdateItem updateItem; - updateItem.name = *edgeTypeName_; - auto propName = item->field(); - updateItem.prop = *propName; - updateItem.value = Expression::encode(item->value()); - updateItems_.emplace_back(std::move(updateItem)); - } - return status; -} - - -Status UpdateEdgeExecutor::prepareWhen() { - auto *clause = sentence_->whenClause(); - if (clause != nullptr) { - filter_ = clause->filter(); - } - return Status::OK(); -} - - -Status UpdateEdgeExecutor::prepareYield() { - auto *clause = sentence_->yieldClause(); - if (clause != nullptr) { - yields_ = clause->columns(); - } - return Status::OK(); -} - - -std::vector<std::string> UpdateEdgeExecutor::getReturnColumns() { - std::vector<std::string> returnColumns; - for (auto *col : yields_) { - auto column = Expression::encode(col->expr()); - returnColumns.emplace_back(std::move(column)); - } - return returnColumns; -} - - -void UpdateEdgeExecutor::finishExecution(storage::cpp2::UpdateResponse &&rpcResp) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> columnNames; - columnNames.reserve(yields_.size()); - for (auto *col : yields_) { - if (col->alias() == nullptr) { - columnNames.emplace_back(col->expr()->toString()); - } else { - columnNames.emplace_back(*col->alias()); - } - } - resp_->set_column_names(std::move(columnNames)); - - std::vector<cpp2::RowValue> rows; - if (rpcResp.__isset.schema && rpcResp.__isset.data) { - auto schema = std::make_shared<ResultSchemaProvider>(rpcResp.schema); - auto reader = RowReader::getRowReader(rpcResp.data, schema); - std::vector<cpp2::ColumnValue> row(yields_.size()); - for (auto index = 0UL; index < yields_.size(); index++) { - auto res = RowReader::getPropByIndex(reader.get(), index); - if (ok(res)) { - auto column = value(std::move(res)); - switch (column.which()) { - case VAR_INT64: - row[index].set_integer(boost::get<int64_t>(column)); - break; - case VAR_DOUBLE: - row[index].set_double_precision(boost::get<double>(column)); - break; - case VAR_BOOL: - row[index].set_bool_val(boost::get<bool>(column)); - break; - case VAR_STR: - row[index].set_str(boost::get<std::string>(column)); - break; - default: - LOG(FATAL) << "Unknown VariantType: " << column.which(); - } - } else { - doError(Status::Error("get property failed"), - ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - } - } - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getUpdateEdgeStats()); -} - - -void UpdateEdgeExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - } - resp = std::move(*resp_); -} - - -void UpdateEdgeExecutor::insertReverselyEdge(storage::cpp2::UpdateResponse &&rpcResp) { - std::vector<storage::cpp2::Edge> edges; - storage::cpp2::Edge reverselyEdge; - reverselyEdge.key.set_src(edge_.dst); - reverselyEdge.key.set_dst(edge_.src); - reverselyEdge.key.set_ranking(edge_.ranking); - reverselyEdge.key.set_edge_type(-edge_.edge_type); - reverselyEdge.props = ""; - edges.emplace_back(reverselyEdge); - auto future = ectx()->getStorageClient()->addEdges(spaceId_, std::move(edges), false); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this, updateResp = std::move(rpcResp)] (auto &&resp) mutable { - auto completeness = resp.completeness(); - if (completeness != 100) { - // Very bad, it should delete the upsert positive edge!!! - doError(Status::Error("Insert the reversely edge failed."), - ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - } - this->finishExecution(std::move(updateResp)); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - // Very bad, it should delete the upsert positive edge!!! - doError(Status::Error("Internal error: insert reversely edge."), - ectx()->getGraphStats()->getUpdateEdgeStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - - -void UpdateEdgeExecutor::execute() { - FLOG_INFO("Executing UpdateEdge: %s", sentence_->toString().c_str()); - std::string filterStr = filter_ ? Expression::encode(filter_) : ""; - auto returns = getReturnColumns(); - auto future = ectx()->getStorageClient()->updateEdge(spaceId_, - edge_, - filterStr, - std::move(updateItems_), - std::move(returns), - insertable_); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - doError(std::move(resp).status(), ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - } - auto rpcResp = std::move(resp).value(); - for (auto& code : rpcResp.get_result().get_failed_codes()) { - switch (code.get_code()) { - case nebula::storage::cpp2::ErrorCode::E_INVALID_FILTER: - doError(Status::Error("Maybe invalid edge or property in WHEN clause!"), - ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - case nebula::storage::cpp2::ErrorCode::E_INVALID_UPDATER: - doError(Status::Error("Maybe invalid property in SET/YIELD clasue!"), - ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - default: - std::string errMsg = - folly::stringPrintf("Maybe edge does not exist or filter failed, " - "part: %d, error code: %d!", - code.get_part_id(), - static_cast<int32_t>(code.get_code())); - LOG(ERROR) << errMsg; - doError(Status::Error(errMsg), - ectx()->getGraphStats()->getUpdateEdgeStats()); - return; - } - } - if (insertable_ && rpcResp.get_upsert()) { - // TODO(zhangguoqing) Making the reverse edge of insertion is transactional - this->insertReverselyEdge(std::move(rpcResp)); - } else { - this->finishExecution(std::move(rpcResp)); - } - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error about updateEdge"), - ectx()->getGraphStats()->getUpdateEdgeStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/UpdateEdgeExecutor.h b/src/executor/UpdateEdgeExecutor.h deleted file mode 100644 index c426228428f6d3fb394228f1d3a075fbffc807d2..0000000000000000000000000000000000000000 --- a/src/executor/UpdateEdgeExecutor.h +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_UPDATEEDGEEXECUTOR_H_ -#define GRAPH_UPDATEEDGEEXECUTOR_H_ - -#include "base/Base.h" -#include "filter/Expressions.h" -#include "graph/Executor.h" -#include "meta/SchemaManager.h" -#include "storage/client/StorageClient.h" - -namespace nebula { - -namespace storage { - -namespace cpp2 { -class UpdateResponse; -} // namespace cpp2 -} // namespace storage - -namespace graph { - -class UpdateEdgeExecutor final : public Executor { -public: - UpdateEdgeExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "UpdateEdgeExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - // To do some preparing works on the clauses - Status prepareSet(); - - Status prepareWhen(); - - Status prepareYield(); - - std::vector<std::string> getReturnColumns(); - - void insertReverselyEdge(storage::cpp2::UpdateResponse &&rpcResp); - - // All required data have arrived, finish the execution. - void finishExecution(storage::cpp2::UpdateResponse &&rpcResp); - -private: - UpdateEdgeSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - bool insertable_{false}; - storage::cpp2::EdgeKey edge_; - const std::string *edgeTypeName_{nullptr}; - std::vector<storage::cpp2::UpdateItem> updateItems_; - Expression *filter_{nullptr}; - std::vector<YieldColumn*> yields_; - std::unique_ptr<ExpressionContext> expCtx_; - GraphSpaceID spaceId_{-1}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_UPDATEEDGEEXECUTOR_H_ diff --git a/src/executor/UpdateVertexExecutor.cpp b/src/executor/UpdateVertexExecutor.cpp deleted file mode 100644 index 384e0ecfd9da98a25678d1e45555ba5d73a19e02..0000000000000000000000000000000000000000 --- a/src/executor/UpdateVertexExecutor.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "filter/Expressions.h" -#include "graph/UpdateVertexExecutor.h" -#include "storage/client/StorageClient.h" -#include "dataman/RowWriter.h" -#include "dataman/RowReader.h" - -namespace nebula { -namespace graph { - -// UPDATE/UPSERT VERTEX <vertex_id> -// SET <update_decl> [WHEN <conditions>] [YIELD <field_list>] -UpdateVertexExecutor::UpdateVertexExecutor(Sentence *sentence, - ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<UpdateVertexSentence*>(sentence); -} - - -Status UpdateVertexExecutor::prepare() { - DCHECK(sentence_ != nullptr); - - spaceId_ = ectx()->rctx()->session()->space(); - expCtx_ = std::make_unique<ExpressionContext>(); - expCtx_->setSpace(spaceId_); - expCtx_->setStorageClient(ectx()->getStorageClient()); - - Status status = Status::OK(); - do { - status = checkIfGraphSpaceChosen(); - if (!status.ok()) { - break; - } - insertable_ = sentence_->getInsertable(); - auto id = sentence_->getVid(); - id->setContext(expCtx_.get()); - status = id->prepare(); - if (!status.ok()) { - break; - } - auto vid = id->eval(); - if (!vid.ok() || !Expression::isInt(vid.value())) { - status = Status::Error("Get Vertex ID failure!"); - break; - } - vertex_ = Expression::asInt(vid.value()); - status = prepareSet(); - if (!status.ok()) { - break; - } - status = prepareWhen(); - if (!status.ok()) { - break; - } - status = prepareYield(); - if (!status.ok()) { - break; - } - } while (false); - - if (status.ok()) { - stats::Stats::addStatsValue(ectx()->getGraphStats()->getUpdateVertexStats(), - false, duration().elapsedInUSec()); - } - return status; -} - - -Status UpdateVertexExecutor::prepareSet() { - auto status = Status::OK(); - auto items = sentence_->updateList()->items(); - for (auto& item : items) { - // item: name_label ASSIGN expression, name_label is alias_ref_expression - storage::cpp2::UpdateItem updateItem; - auto expRet = Expression::decode(*item->field()); - if (!expRet.ok()) { - return Status::SyntaxError("Invalid vertex update item field: " + *item->field()); - } - auto expr = std::move(expRet).value(); - // alias_ref_expression(LABLE DOT LABLE): TagName.PropName - auto* eexpr = static_cast<const AliasPropertyExpression*>(expr.get()); - updateItem.name = *eexpr->alias(); - updateItem.prop = *eexpr->prop(); - updateItem.value = Expression::encode(item->value()); - updateItems_.emplace_back(std::move(updateItem)); - } - return status; -} - - -Status UpdateVertexExecutor::prepareWhen() { - auto *clause = sentence_->whenClause(); - if (clause != nullptr) { - filter_ = clause->filter(); - } - return Status::OK(); -} - - -Status UpdateVertexExecutor::prepareYield() { - auto *clause = sentence_->yieldClause(); - if (clause != nullptr) { - yields_ = clause->columns(); - } - return Status::OK(); -} - - -std::vector<std::string> UpdateVertexExecutor::getReturnColumns() { - std::vector<std::string> returnColumns; - for (auto *col : yields_) { - auto column = Expression::encode(col->expr()); - returnColumns.emplace_back(std::move(column)); - } - return returnColumns; -} - - -void UpdateVertexExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - if (resp_ == nullptr) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - } - resp = std::move(*resp_); -} - - -void UpdateVertexExecutor::finishExecution(storage::cpp2::UpdateResponse &&rpcResp) { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - std::vector<std::string> columnNames; - columnNames.reserve(yields_.size()); - for (auto *col : yields_) { - if (col->alias() == nullptr) { - columnNames.emplace_back(col->expr()->toString()); - } else { - columnNames.emplace_back(*col->alias()); - } - } - resp_->set_column_names(std::move(columnNames)); - - std::vector<cpp2::RowValue> rows; - if (rpcResp.__isset.schema && rpcResp.__isset.data) { - auto schema = std::make_shared<ResultSchemaProvider>(rpcResp.schema); - auto reader = RowReader::getRowReader(rpcResp.data, schema); - std::vector<cpp2::ColumnValue> row(yields_.size()); - for (auto index = 0UL; index < yields_.size(); index++) { - auto res = RowReader::getPropByIndex(reader.get(), index); - if (ok(res)) { - auto column = value(std::move(res)); - switch (column.which()) { - case VAR_INT64: - row[index].set_integer(boost::get<int64_t>(column)); - break; - case VAR_DOUBLE: - row[index].set_double_precision(boost::get<double>(column)); - break; - case VAR_BOOL: - row[index].set_bool_val(boost::get<bool>(column)); - break; - case VAR_STR: - row[index].set_str(boost::get<std::string>(column)); - break; - default: - LOG(FATAL) << "Unknown VariantType: " << column.which(); - } - } else { - doError(Status::Error("get property failed"), - ectx()->getGraphStats()->getUpdateVertexStats()); - return; - } - } - rows.emplace_back(); - rows.back().set_columns(std::move(row)); - } - resp_->set_rows(std::move(rows)); - doFinish(Executor::ProcessControl::kNext, ectx()->getGraphStats()->getUpdateVertexStats()); -} - - -void UpdateVertexExecutor::execute() { - FLOG_INFO("Executing UpdateVertex: %s", sentence_->toString().c_str()); - std::string filterStr = filter_ ? Expression::encode(filter_) : ""; - auto returns = getReturnColumns(); - auto future = ectx()->getStorageClient()->updateVertex(spaceId_, - vertex_, - filterStr, - std::move(updateItems_), - std::move(returns), - insertable_); - auto *runner = ectx()->rctx()->runner(); - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - doError(std::move(resp).status(), ectx()->getGraphStats()->getUpdateVertexStats()); - return; - } - auto rpcResp = std::move(resp).value(); - for (auto& code : rpcResp.get_result().get_failed_codes()) { - switch (code.get_code()) { - case nebula::storage::cpp2::ErrorCode::E_INVALID_FILTER: - doError(Status::Error("Maybe invalid tag or property in WHEN clause!"), - ectx()->getGraphStats()->getUpdateVertexStats()); - return; - case nebula::storage::cpp2::ErrorCode::E_INVALID_UPDATER: - doError(Status::Error("Maybe invalid tag or property in SET/YIELD clasue!"), - ectx()->getGraphStats()->getUpdateVertexStats()); - return; - default: - std::string errMsg = - folly::stringPrintf("Maybe vertex does not exist or filter failed, " - "part: %d, error code: %d!", - code.get_part_id(), - static_cast<int32_t>(code.get_code())); - LOG(ERROR) << errMsg; - doError(Status::Error(errMsg), - ectx()->getGraphStats()->getUpdateVertexStats()); - return; - } - } - this->finishExecution(std::move(rpcResp)); - }; - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - doError(Status::Error("Internal error"), ectx()->getGraphStats()->getUpdateVertexStats()); - }; - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/UpdateVertexExecutor.h b/src/executor/UpdateVertexExecutor.h deleted file mode 100644 index 6c6e83adb94ed121c8fd24d3dc17175e72a5322f..0000000000000000000000000000000000000000 --- a/src/executor/UpdateVertexExecutor.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_UPDATEVERTEXEXECUTOR_H_ -#define GRAPH_UPDATEVERTEXEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" -#include "meta/SchemaManager.h" -#include "storage/client/StorageClient.h" - -namespace nebula { - -namespace storage { -namespace cpp2 { -class UpdateResponse; -} // namespace cpp2 -} // namespace storage - -namespace graph { - -class UpdateVertexExecutor final : public Executor { -public: - UpdateVertexExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "UpdateVertexExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - // To do some preparing works on the clauses - Status prepareSet(); - - Status prepareWhen(); - - Status prepareYield(); - - std::vector<std::string> getReturnColumns(); - - // All required data have arrived, finish the execution. - void finishExecution(storage::cpp2::UpdateResponse &&rpcResp); - -private: - UpdateVertexSentence *sentence_{nullptr}; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - bool insertable_{false}; - VertexID vertex_; - std::vector<storage::cpp2::UpdateItem> updateItems_; - Expression *filter_{nullptr}; - std::vector<YieldColumn*> yields_; - std::unique_ptr<ExpressionContext> expCtx_; - GraphSpaceID spaceId_{-1}; -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_UPDATEVERTEXEXECUTOR_H_ diff --git a/src/executor/UseExecutor.cpp b/src/executor/UseExecutor.cpp deleted file mode 100644 index 831073d41c52eb098ccd7d55f4684faf856c7346..0000000000000000000000000000000000000000 --- a/src/executor/UseExecutor.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/UseExecutor.h" - -namespace nebula { -namespace graph { - -UseExecutor::UseExecutor(Sentence *sentence, ExecutionContext *ectx) : Executor(ectx) { - sentence_ = static_cast<UseSentence*>(sentence); -} - - -Status UseExecutor::prepare() { - return Status::OK(); -} - - -void UseExecutor::execute() { - auto future = ectx()->getMetaClient()->getSpace(*sentence_->space()); - auto *runner = ectx()->rctx()->runner(); - - auto cb = [this] (auto &&resp) { - if (!resp.ok()) { - DCHECK(onError_); - onError_(Status::Error("Space not found for `%s'", sentence_->space()->c_str())); - return; - } - - auto spaceId = resp.value().get_space_id(); - ectx()->rctx()->session()->setSpace(*sentence_->space(), spaceId); - FLOG_INFO("Graph space switched to `%s', space id: %d", - sentence_->space()->c_str(), spaceId); - - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); - }; - - auto error = [this] (auto &&e) { - LOG(ERROR) << "Exception caught: " << e.what(); - DCHECK(onError_); - onError_(Status::Error("Internal error")); - return; - }; - - std::move(future).via(runner).thenValue(cb).thenError(error); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/UseExecutor.h b/src/executor/UseExecutor.h deleted file mode 100644 index 66abd214b131389a6c24da998bec9c0be81777df..0000000000000000000000000000000000000000 --- a/src/executor/UseExecutor.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_USEEXECUTOR_H_ -#define GRAPH_USEEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/Executor.h" - -namespace nebula { -namespace graph { - -class UseExecutor final : public Executor { -public: - UseExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "UseExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - -private: - UseSentence *sentence_{nullptr}; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_USEEXECUTOR_H_ diff --git a/src/executor/VariableHolder.cpp b/src/executor/VariableHolder.cpp deleted file mode 100644 index f949c2bb14c8f890486a3480f57c22cb2129737b..0000000000000000000000000000000000000000 --- a/src/executor/VariableHolder.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/VariableHolder.h" -#include "graph/InterimResult.h" - -namespace nebula { -namespace graph { - -VariableHolder::VariableHolder() { -} - - -VariableHolder::~VariableHolder() { -} - - -VariableHolder::VariableHolder(VariableHolder &&rhs) noexcept { - holder_ = std::move(rhs.holder_); -} - - -VariableHolder& VariableHolder::operator=(VariableHolder &&rhs) noexcept { - if (this == &rhs) { - return *this; - } - holder_ = std::move(rhs.holder_); - return *this; -} - - -void VariableHolder::add(const std::string &var, std::unique_ptr<InterimResult> result) { - holder_[var] = std::move(result); -} - - -const InterimResult* VariableHolder::get(const std::string &var, bool *existing) const { - auto iter = holder_.find(var); - if (iter == holder_.end()) { - if (existing != nullptr) { - *existing = false; - } - return nullptr; - } - if (existing != nullptr) { - *existing = true; - } - return iter->second.get(); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/VariableHolder.h b/src/executor/VariableHolder.h deleted file mode 100644 index 93333961a8185482ee4cc86662988ecbe9a6ac26..0000000000000000000000000000000000000000 --- a/src/executor/VariableHolder.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_VARIABLEHOLDER_H_ -#define GRAPH_VARIABLEHOLDER_H_ - -#include "base/Base.h" - -namespace nebula { -namespace graph { - -class InterimResult; -class VariableHolder final { -public: - VariableHolder(); - ~VariableHolder(); - VariableHolder(const VariableHolder&) = delete; - VariableHolder& operator=(const VariableHolder&) = delete; - VariableHolder(VariableHolder &&) noexcept; - VariableHolder& operator=(VariableHolder &&) noexcept; - - void add(const std::string &var, std::unique_ptr<InterimResult> result); - - const InterimResult* get(const std::string &var, bool *existing = nullptr) const; - -private: - std::unordered_map<std::string, std::unique_ptr<InterimResult>> holder_; -}; - -} // namespace graph -} // namespace nebula - - -#endif // GRAPH_VARIABLEHOLDER_H_ diff --git a/src/executor/YieldExecutor.cpp b/src/executor/YieldExecutor.cpp deleted file mode 100644 index 20f568a41b01dc1773e7c72429f44f5d3315b126..0000000000000000000000000000000000000000 --- a/src/executor/YieldExecutor.cpp +++ /dev/null @@ -1,454 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/YieldExecutor.h" -#include "graph/SchemaHelper.h" -#include "meta/SchemaProviderIf.h" - -namespace nebula { -namespace graph { - -YieldExecutor::YieldExecutor(Sentence *sentence, ExecutionContext *ectx) - : TraverseExecutor(ectx) { - sentence_ = static_cast<YieldSentence*>(sentence); -} - -Status YieldExecutor::prepare() { - Status status = Status::OK(); - expCtx_ = std::make_unique<ExpressionContext>(); - do { - status = prepareWhere(); - if (!status.ok()) { - break; - } - } while (false); - - return status; -} - -Status YieldExecutor::checkAggFun() { - bool hasAggFun = false; - for (auto *col : yields_) { - if (!col->getFunName().empty()) { - hasAggFun = true; - break; - } - } - - if (!hasAggFun) { - return Status::OK(); - } - - for (auto *col : yields_) { - if ((col->expr()->isInputExpression() || col->expr()->isVariableExpression()) - && col->getFunName().empty()) { - std::string error = "Input columns without aggregation " - "are not supported in YIELD statement without GROUP BY, near `" - + col->expr()->toString() + "'"; - return Status::SyntaxError(std::move(error)); - } - auto funPtr = funVec[col->getFunName()](); - aggFuns_.emplace_back(std::move(funPtr)); - } - return Status::OK(); -} - -Status YieldExecutor::prepareYield() { - // this preparation depends on interim result, - // it can only be called after getting results of the previous executor, - // but if we can do the semantic analysis before execution, - // then we can do the preparation before execution - // TODO: make it possible that this preparation not depends on interim result - auto *clause = sentence_->yield(); - yieldClauseWrapper_ = std::make_unique<YieldClauseWrapper>(clause); - auto *varHolder = ectx()->variableHolder(); - auto status = yieldClauseWrapper_->prepare(inputs_.get(), varHolder, yields_); - if (!status.ok()) { - return status; - } - - status = checkAggFun(); - if (!status.ok()) { - return status; - } - - for (auto *col : yields_) { - col->expr()->setContext(expCtx_.get()); - status = col->expr()->prepare(); - if (!status.ok()) { - return status; - } - if (col->alias() == nullptr) { - resultColNames_.emplace_back(col->expr()->toString()); - } else { - resultColNames_.emplace_back(*col->alias()); - } - - // such as YIELD 1+1, it has not type in schema, the type from the eval() - colTypes_.emplace_back(nebula::cpp2::SupportedType::UNKNOWN); - if (col->expr()->isTypeCastingExpression()) { - // type cast - auto exprPtr = static_cast<TypeCastingExpression*>(col->expr()); - colTypes_.back() = SchemaHelper::columnTypeToSupportedType(exprPtr->getType()); - } - } - - return Status::OK(); -} - -Status YieldExecutor::prepareWhere() { - Status status; - auto *clause = sentence_->where(); - if (clause != nullptr) { - filter_ = clause->filter(); - } - if (filter_ != nullptr) { - filter_->setContext(expCtx_.get()); - status = filter_->prepare(); - } - return status; -} - -Status YieldExecutor::syntaxCheck() { - if (expCtx_->hasSrcTagProp() - || expCtx_->hasDstTagProp() - || expCtx_->hasEdgeProp()) { - return Status::SyntaxError( - "Only support input and variable in yield sentence."); - } - - if (expCtx_->hasVariableProp() && expCtx_->hasInputProp()) { - return Status::Error("Not support both input and variable."); - } - - if (expCtx_->hasVariableProp()) { - auto &variables = expCtx_->variables(); - if (variables.size() > 1) { - return Status::Error("Only one variable allowed to use."); - } - - varname_ = *variables.begin(); - } - - return Status::OK(); -} - -void YieldExecutor::execute() { - FLOG_INFO("Executing YIELD: %s", sentence_->toString().c_str()); - Status status; - do { - status = beforeExecute(); - if (!status.ok()) { - break; - } - if (hasSetResult_ || expCtx_->hasVariableProp()) { - status = executeInputs(); - } else { - status = executeConstant(); - } - } while (false); - - if (!status.ok()) { - LOG(INFO) << status.toString(); - DCHECK(onError_); - onError_(std::move(status)); - return; - } -} - -Status YieldExecutor::beforeExecute() { - Status status; - do { - status = prepareYield(); - if (!status.ok()) { - break; - } - status = syntaxCheck(); - if (!status.ok()) { - break; - } - } while (false); - return status; -} - -Status YieldExecutor::executeInputs() { - const auto *inputs = inputs_.get(); - - if (expCtx_->hasVariableProp()) { - bool existing = false; - inputs = ectx()->variableHolder()->get(varname_, &existing); - if (inputs == nullptr && !existing) { - return Status::Error("Variable `%s' not defined.", varname_.c_str()); - } - } - // No error happened, but we are having empty inputs - if (inputs == nullptr || !inputs->hasData()) { - finishExecution(nullptr); - return Status::OK(); - } - - auto outputSchema = std::make_shared<SchemaWriter>(); - auto status = getOutputSchema(inputs, outputSchema.get()); - if (!status.ok()) { - return status; - } - - auto rsWriter = std::make_unique<RowSetWriter>(outputSchema); - auto visitor = - [inputs, &outputSchema, &rsWriter, &status, this] (const RowReader *reader) -> Status { - auto &getters = expCtx_->getters(); - getters.getVariableProp = [inputs, reader] (const std::string &prop) { - return Collector::getProp(inputs->schema().get(), prop, reader); - }; - getters.getInputProp = [inputs, reader] (const std::string &prop) { - return Collector::getProp(inputs->schema().get(), prop, reader); - }; - if (filter_ != nullptr) { - auto val = filter_->eval(); - if (!val.ok()) { - return val.status(); - } - if (!Expression::asBool(val.value())) { - return Status::OK(); - } - } - - if (aggFuns_.empty()) { - auto writer = std::make_unique<RowWriter>(outputSchema); - for (auto col : yields_) { - auto *expr = col->expr(); - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - status = Collector::collect(value.value(), writer.get()); - if (!status.ok()) { - return status; - } - } - rsWriter->addRow(*writer); - } else { - auto i = 0u; - for (auto col : yields_) { - auto *expr = col->expr(); - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - auto cVal = toColumnValue(value.value(), static_cast<cpp2::ColumnValue::Type>( - outputSchema->getFieldType(i).type)); - if (!cVal.ok()) { - return cVal.status(); - } - aggFuns_[i]->apply(cVal.value()); - i++; - } - } - - return Status::OK(); - }; - - status = inputs->applyTo(visitor); - if (!status.ok()) { - return status; - } - - if (!aggFuns_.empty()) { - cpp2::RowValue row; - auto schema = std::make_shared<SchemaWriter>(); - std::vector<cpp2::ColumnValue> cols; - auto i = 0u; - for (auto f : aggFuns_) { - auto val = f->getResult(); - schema->appendCol(outputSchema->getFieldName(i), - static_cast<nebula::cpp2::SupportedType>(val.getType())); - cols.emplace_back(std::move(val)); - i++; - } - row.set_columns(std::move(cols)); - rsWriter->setSchema(std::move(schema)); - status = getAggResultWriter(std::move(row), rsWriter.get()); - if (!status.ok()) { - return status; - } - } - - finishExecution(std::move(rsWriter)); - return Status::OK(); -} - -Status YieldExecutor::getAggResultWriter(cpp2::RowValue row, RowSetWriter* rsWriter) { - std::vector<cpp2::RowValue> rows; - rows.emplace_back(std::move(row)); - return InterimResult::getResultWriter(rows, rsWriter); -} - -Status YieldExecutor::getOutputSchema(const InterimResult *inputs, - SchemaWriter *outputSchema) const { - if (expCtx_ == nullptr || resultColNames_.empty()) { - return Status::Error("No result columns declared."); - } - - auto *inputSchema = inputs->schema().get(); - - auto varProps = expCtx_->variableProps(); - auto varPropFind = std::find_if(varProps.begin(), varProps.end(), - [inputSchema] (const auto &pair) { - return inputSchema->getFieldIndex(pair.second) < 0; - }); - if (varPropFind != varProps.end()) { - return Status::Error( - "column `%s' not exist in variable.", varPropFind->second.c_str()); - } - - auto inProps = expCtx_->inputProps(); - auto inPropFind = std::find_if(inProps.begin(), inProps.end(), - [inputSchema] (const auto &prop) { - return inputSchema->getFieldIndex(prop) < 0; - }); - if (inPropFind != inProps.end()) { - return Status::Error( - "column `%s' not exist in input.", inPropFind->c_str()); - } - - std::vector<VariantType> record; - record.reserve(yields_.size()); - auto visitor = [inputSchema, &record, this] (const RowReader *reader) -> Status { - auto &getters = expCtx_->getters(); - getters.getVariableProp = [inputSchema, reader] (const std::string &prop) { - return Collector::getProp(inputSchema, prop, reader); - }; - getters.getInputProp = [inputSchema, reader] (const std::string &prop) { - return Collector::getProp(inputSchema, prop, reader); - }; - for (auto *column : yields_) { - auto *expr = column->expr(); - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - record.emplace_back(std::move(value).value()); - } - return Status::OK(); - }; - inputs->applyTo(visitor, 1); - - return Collector::getSchema(record, resultColNames_, colTypes_, outputSchema); -} - -Status YieldExecutor::executeConstant() { - auto size = yields_.size(); - std::vector<VariantType> values; - values.reserve(size); - - if (aggFuns_.empty()) { - for (auto *col : yields_) { - auto expr = col->expr(); - auto v = expr->eval(); - if (!v.ok()) { - return v.status(); - } - values.emplace_back(v.value()); - } - - auto outputSchema = std::make_shared<SchemaWriter>(); - auto status = Collector::getSchema( - values, resultColNames_, colTypes_, outputSchema.get()); - if (!status.ok()) { - return status; - } - - RowWriter writer(outputSchema); - auto rsWriter = std::make_unique<RowSetWriter>(outputSchema); - for (auto col : values) { - status = Collector::collect(col, &writer); - if (!status.ok()) { - return status; - } - } - rsWriter->addRow(writer); - finishExecution(std::move(rsWriter)); - } else { - return AggregateConstant(); - } - return Status::OK(); -} - -Status YieldExecutor::AggregateConstant() { - auto i = 0u; - for (auto col : yields_) { - auto *expr = col->expr(); - auto value = expr->eval(); - if (!value.ok()) { - return value.status(); - } - auto status = toColumnValue(value.value(), cpp2::ColumnValue::Type::__EMPTY__); - if (!status.ok()) { - return status.status(); - } - aggFuns_[i]->apply(status.value()); - i++; - } - cpp2::RowValue row; - auto schema = std::make_shared<SchemaWriter>(); - std::vector<cpp2::ColumnValue> cols; - i = 0; - for (auto f : aggFuns_) { - auto val = f->getResult(); - schema->appendCol(resultColNames_[i], - static_cast<nebula::cpp2::SupportedType>(val.getType())); - cols.emplace_back(std::move(val)); - i++; - } - row.set_columns(std::move(cols)); - auto rsWriter = std::make_unique<RowSetWriter>(schema); - auto status = getAggResultWriter(std::move(row), rsWriter.get()); - if (!status.ok()) { - return status; - } - finishExecution(std::move(rsWriter)); - return Status::OK(); -} - -void YieldExecutor::finishExecution(std::unique_ptr<RowSetWriter> rsWriter) { - auto outputs = std::make_unique<InterimResult>(std::move(resultColNames_)); - if (rsWriter != nullptr) { - outputs->setInterim(std::move(rsWriter)); - } - - if (onResult_) { - onResult_(std::move(outputs)); - } else { - resp_ = std::make_unique<cpp2::ExecutionResponse>(); - auto colNames = outputs->getColNames(); - resp_->set_column_names(std::move(colNames)); - if (outputs->hasData()) { - auto ret = outputs->getRows(); - if (!ret.ok()) { - LOG(ERROR) << "Get rows failed: " << ret.status(); - onError_(std::move(ret).status()); - return; - } - resp_->set_rows(std::move(ret).value()); - } - } - DCHECK(onFinish_); - onFinish_(Executor::ProcessControl::kNext); -} - -void YieldExecutor::feedResult(std::unique_ptr<InterimResult> result) { - hasSetResult_ = true; - inputs_ = std::move(result); -} - -void YieldExecutor::setupResponse(cpp2::ExecutionResponse &resp) { - CHECK(resp_ != nullptr); - resp = std::move(*resp_); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/YieldExecutor.h b/src/executor/YieldExecutor.h deleted file mode 100644 index 4976e878c8018d0986f1b1224dcb8dfc1be8bfda..0000000000000000000000000000000000000000 --- a/src/executor/YieldExecutor.h +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_YIELDEXECUTOR_H_ -#define GRAPH_YIELDEXECUTOR_H_ - -#include "base/Base.h" -#include "graph/TraverseExecutor.h" -#include "meta/SchemaProviderIf.h" -#include "graph/AggregateFunction.h" - -namespace nebula { -namespace graph { - -class YieldExecutor final : public TraverseExecutor { -public: - YieldExecutor(Sentence *sentence, ExecutionContext *ectx); - - const char* name() const override { - return "YieldExecutor"; - } - - Status MUST_USE_RESULT prepare() override; - - void execute() override; - - void feedResult(std::unique_ptr<InterimResult> result) override; - - void setupResponse(cpp2::ExecutionResponse &resp) override; - -private: - Status prepareYield(); - - Status prepareWhere(); - - Status syntaxCheck(); - - Status beforeExecute(); - - Status executeInputs(); - - Status getOutputSchema(const InterimResult *inputs, SchemaWriter *outputSchema) const; - - Status executeConstant(); - - void finishExecution(std::unique_ptr<RowSetWriter> rsWriter); - - Status checkAggFun(); - - Status getAggResultWriter(cpp2::RowValue row, RowSetWriter* rsWriter); - - Status AggregateConstant(); - -private: - YieldSentence *sentence_; - std::vector<YieldColumn*> yields_; - std::unique_ptr<YieldClauseWrapper> yieldClauseWrapper_; - std::unique_ptr<ExpressionContext> expCtx_; - Expression *filter_{nullptr}; - std::unique_ptr<InterimResult> inputs_; - std::string varname_; - std::vector<std::string> resultColNames_; - std::unique_ptr<cpp2::ExecutionResponse> resp_; - std::vector<nebula::cpp2::SupportedType> colTypes_; - std::vector<std::shared_ptr<AggFun>> aggFuns_; - bool hasSetResult_{false}; -}; -} // namespace graph -} // namespace nebula - -#endif // GRAPH_YIELDEXECUTOR_H_ diff --git a/src/executor/test/CMakeLists.txt b/src/executor/test/CMakeLists.txt deleted file mode 100644 index cb3af0ec69e3e6dfef2a0c56c9a7907539a94918..0000000000000000000000000000000000000000 --- a/src/executor/test/CMakeLists.txt +++ /dev/null @@ -1,342 +0,0 @@ -# Copyright (c) 2020 vesoft inc. All rights reserved. -# -# This source code is licensed under Apache 2.0 License, -# attached with Common Clause Condition 1.0, found in the LICENSES directory. - -set(GRAPH_TEST_LIBS - $<TARGET_OBJECTS:graph_obj> - $<TARGET_OBJECTS:graph_thrift_obj> - $<TARGET_OBJECTS:storage_service_handler> - $<TARGET_OBJECTS:storage_client> - $<TARGET_OBJECTS:storage_thrift_obj> - $<TARGET_OBJECTS:common_thrift_obj> - $<TARGET_OBJECTS:parser_obj> - $<TARGET_OBJECTS:filter_obj> - $<TARGET_OBJECTS:schema_obj> - $<TARGET_OBJECTS:dataman_obj> - $<TARGET_OBJECTS:http_client_obj> - $<TARGET_OBJECTS:ws_common_obj> - $<TARGET_OBJECTS:storage_client> - $<TARGET_OBJECTS:meta_client> - $<TARGET_OBJECTS:stats_obj> - $<TARGET_OBJECTS:meta_thrift_obj> - $<TARGET_OBJECTS:meta_service_handler> - $<TARGET_OBJECTS:kvstore_obj> - $<TARGET_OBJECTS:raftex_obj> - $<TARGET_OBJECTS:raftex_thrift_obj> - $<TARGET_OBJECTS:wal_obj> - $<TARGET_OBJECTS:time_obj> - $<TARGET_OBJECTS:fs_obj> - $<TARGET_OBJECTS:network_obj> - $<TARGET_OBJECTS:thread_obj> - $<TARGET_OBJECTS:thrift_obj> - $<TARGET_OBJECTS:process_obj> - $<TARGET_OBJECTS:base_obj> - $<TARGET_OBJECTS:meta_gflags_man_obj> - $<TARGET_OBJECTS:gflags_man_obj> - $<TARGET_OBJECTS:ws_common_obj> - $<TARGET_OBJECTS:stats_obj> -) - -nebula_add_library( - graph_test_common_obj OBJECT - TestMain.cpp - TestEnv.cpp - TestBase.cpp -) - -nebula_add_test( - NAME - session_manager_test - SOURCES - SessionManagerTest.cpp - OBJECTS - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest - gtest_main -) - -nebula_add_test( - NAME - query_engine_test - SOURCES - SchemaTest.cpp - ConfigTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - go_test - SOURCES - GoTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - graph_http_test - SOURCES - GraphHttpHandlerTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:graph_http_handler> - $<TARGET_OBJECTS:ws_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:stats_obj> - $<TARGET_OBJECTS:process_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - proxygenhttpserver - proxygenlib - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - data_test - SOURCES - DataTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:stats_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - order_by_test - SOURCES - OrderByTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:stats_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - fetch_vertices_test - SOURCES - FetchVerticesTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - fetch_edges_test - SOURCES - FetchEdgesTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - set_test - SOURCES - SetTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - delete_vertex_sentence_test - SOURCES - DeleteVertexTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - delete_edges_sentence_test - SOURCES - DeleteEdgesTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - update_test - SOURCES - UpdateTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - find_path_test - SOURCES - FindPathTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - group_by_limit_test - SOURCES - GroupByLimitTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - yield_test - SOURCES - YieldTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - geo_test - SOURCES - GeoTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) - -nebula_add_test( - NAME - snapshot_command_test - SOURCES - SnapshotCommandTest.cpp - OBJECTS - $<TARGET_OBJECTS:graph_test_common_obj> - $<TARGET_OBJECTS:client_cpp_obj> - $<TARGET_OBJECTS:adHocSchema_obj> - ${GRAPH_TEST_LIBS} - LIBRARIES - ${THRIFT_LIBRARIES} - ${ROCKSDB_LIBRARIES} - wangle - gtest -) diff --git a/src/executor/test/ConfigTest.cpp b/src/executor/test/ConfigTest.cpp deleted file mode 100644 index 0d93f5d6ceb712bb23072b39bafd23d90896e973..0000000000000000000000000000000000000000 --- a/src/executor/test/ConfigTest.cpp +++ /dev/null @@ -1,265 +0,0 @@ - -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestBase.h" -#include "graph/test/TestEnv.h" -#include "meta/ClientBasedGflagsManager.h" -#include "meta/test/TestUtils.h" -#include "storage/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class ConfigTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } -}; - -std::vector<meta::cpp2::ConfigItem> mockRegisterGflags() { - std::vector<meta::cpp2::ConfigItem> configItems; - { - auto module = meta::cpp2::ConfigModule::STORAGE; - auto type = meta::cpp2::ConfigType::INT64; - int64_t value = 0L; - configItems.emplace_back(meta::toThriftConfigItem(module, "k0", type, - meta::cpp2::ConfigMode::IMMUTABLE, - meta::toThriftValueStr(type, value))); - configItems.emplace_back(meta::toThriftConfigItem(module, "k1", type, - meta::cpp2::ConfigMode::MUTABLE, - meta::toThriftValueStr(type, value))); - } - { - auto module = meta::cpp2::ConfigModule::STORAGE; - auto type = meta::cpp2::ConfigType::BOOL; - auto mode = meta::cpp2::ConfigMode::MUTABLE; - bool value = false; - configItems.emplace_back(meta::toThriftConfigItem(module, "k2", type, mode, - meta::toThriftValueStr(type, value))); - } - { - auto module = meta::cpp2::ConfigModule::META; - auto mode = meta::cpp2::ConfigMode::MUTABLE; - auto type = meta::cpp2::ConfigType::DOUBLE; - double value = 1.0; - configItems.emplace_back(meta::toThriftConfigItem(module, "k1", type, mode, - meta::toThriftValueStr(type, value))); - } - { - auto module = meta::cpp2::ConfigModule::META; - auto mode = meta::cpp2::ConfigMode::MUTABLE; - auto type = meta::cpp2::ConfigType::STRING; - std::string value = "nebula"; - configItems.emplace_back(meta::toThriftConfigItem(module, "k2", type, mode, - meta::toThriftValueStr(type, value))); - } - { - auto type = meta::cpp2::ConfigType::STRING; - auto mode = meta::cpp2::ConfigMode::MUTABLE; - std::string value = "nebula"; - configItems.emplace_back(meta::toThriftConfigItem(meta::cpp2::ConfigModule::GRAPH, "k3", - type, mode, meta::toThriftValueStr(type, value))); - configItems.emplace_back(meta::toThriftConfigItem(meta::cpp2::ConfigModule::META, "k3", - type, mode, meta::toThriftValueStr(type, value))); - configItems.emplace_back(meta::toThriftConfigItem(meta::cpp2::ConfigModule::STORAGE, "k3", - type, mode, meta::toThriftValueStr(type, value))); - } - { - auto module = meta::cpp2::ConfigModule::STORAGE; - auto type = meta::cpp2::ConfigType::NESTED; - auto mode = meta::cpp2::ConfigMode::MUTABLE; - std::string value = R"({ - "disable_auto_compactions":"false", - "write_buffer_size":"1048576" - })"; - configItems.emplace_back(meta::toThriftConfigItem(module, "k4", type, mode, - meta::toThriftValueStr(type, value))); - } - return configItems; -} - -TEST_F(ConfigTest, ConfigTest) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - - auto configItems = mockRegisterGflags(); - auto ret = gEnv->gflagsManager()->registerGflags(std::move(configItems)); - ASSERT_TRUE(ret.ok()); - - // set/get without declaration - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS storage:notRegistered=123"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - - query = "GET CONFIGS storage:notRegistered"; - code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // update immutable config will fail, read-only - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS storage:k0=123"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS storage:k0"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> - expected { {"STORAGE", "k0", "INT64", "IMMUTABLE", "0"} }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // set and get config after declaration - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS storage:k1=123"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS storage:k1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> - expected { {"STORAGE", "k1", "INT64", "MUTABLE", "123"} }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS meta:k1=3.14"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS meta:k1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> - expected { {"META", "k1", "DOUBLE", "MUTABLE", "3.140000"} }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS storage:k2=True"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS storage:k2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> expected { - {"STORAGE", "k2", "BOOL", "MUTABLE", "True"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS meta:k2=abc"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS meta:k2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> expected { - {"META", "k2", "STRING", "MUTABLE", "abc"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // list configs in a specified module - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CONFIGS storage"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(5, resp.get_rows()->size()); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CONFIGS meta"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(3, resp.get_rows()->size()); - } - // set and get a config of all module - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS k3=vesoft"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS k3"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> expected { - {"GRAPH", "k3", "STRING", "MUTABLE", "vesoft"}, - {"META", "k3", "STRING", "MUTABLE", "vesoft"}, - {"STORAGE", "k3", "STRING", "MUTABLE", "vesoft"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS graph:k3=abc"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - query = "UPDATE CONFIGS meta:k3=bcd"; - code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - query = "UPDATE CONFIGS storage:k3=cde"; - code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GET CONFIGS k3"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 5>> expected { - {"GRAPH", "k3", "STRING", "MUTABLE", "abc"}, - {"META", "k3", "STRING", "MUTABLE", "bcd"}, - {"STORAGE", "k3", "STRING", "MUTABLE", "cde"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "UPDATE CONFIGS storage:k4 = {" - "disable_auto_compactions = true," - "level0_file_num_compaction_trigger=4" - "}"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/DataTest.cpp b/src/executor/test/DataTest.cpp deleted file mode 100644 index e9aeeafada6959f01e15ec412050722869e8cf40..0000000000000000000000000000000000000000 --- a/src/executor/test/DataTest.cpp +++ /dev/null @@ -1,962 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class DataTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } - - static void SetUpTestCase() { - client_ = gEnv->getClient(); - - ASSERT_NE(nullptr, client_); - - ASSERT_TRUE(prepareSchema()); - } - - static void TearDownTestCase() { - ASSERT_TRUE(removeData()); - client_.reset(); - } - -protected: - static AssertionResult prepareSchema(); - - static AssertionResult removeData(); - - static std::unique_ptr<GraphClient> client_; -}; - -std::unique_ptr<GraphClient> DataTest::client_{nullptr}; - -AssertionResult DataTest::prepareSchema() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE mySpace(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE mySpace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG person(name string, age int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - // create tag with default value - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG personWithDefault(name string default \"\", " - "age int default 18, " - "isMarried bool default false, " - "BMI double default 18.5, " - "department string default \"engineering\")"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG student(grade string, number int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG studentWithDefault" - "(grade string default \"one\", number int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE schoolmate(likeness int, nickname string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - // create edge with default value - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE schoolmateWithDefault(likeness int default 80)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - // Test same propName diff tyep in diff tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG employee(name int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - // Test same propName same type in diff tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG interest(name string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - // Insert timestamp - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG school(name string, create_time timestamp)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE study(start_time timestamp, end_time timestamp)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd - << " failed, error code "<< static_cast<int32_t>(code); - } - } - sleep(FLAGS_load_data_interval_secs + 3); - return TestOK(); -} - -AssertionResult DataTest::removeData() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE mySpace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - return TestOK(); -} - -TEST_F(DataTest, InsertTest) { - // Insert wrong type value - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES hash(\"Tom\"):(\"Tom\", \"2\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Insert wrong num of value - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name) VALUES hash(\"Tom\"):(\"Tom\", 2)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Insert wrong field - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(Name, age) VALUES hash(\"Tom\"):(\"Tom\", 3)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Insert vertex succeeded - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES hash(\"Tom\"):(\"Tom\", 22)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert unordered order prop vertex succeeded - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(age, name) VALUES hash(\"Conan\"):(10, \"Conan\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - cmd = "FETCH PROP ON person hash(\"Conan\")"; - code = client_->execute(cmd, resp); - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Conan", 10}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES uuid(\"Tom\"):(\"Tom\", 22)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // One vertex multi tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),student(grade, number) " - "VALUES hash(\"Lucy\"):(\"Lucy\", 8, \"three\", 20190901001)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),student(grade, number) " - "VALUES uuid(\"Lucy\"):(\"Lucy\", 8, \"three\", 20190901001)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert unordered order prop vertex succeeded - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(age, name),student(number, grade) " - "VALUES hash(\"Bob\"):(9, \"Bob\", 20191106001, \"four\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - cmd = "FETCH PROP ON person hash(\"Bob\")"; - code = client_->execute(cmd, resp); - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Bob", 9}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - cmd = "FETCH PROP ON student hash(\"Bob\")"; - code = client_->execute(cmd, resp); - std::vector<std::tuple<std::string, int64_t>> expected2 = { - {"four", 20191106001}, - }; - ASSERT_TRUE(verifyResult(resp, expected2)); - } - // Multi vertices multi tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),student(grade, number) " - "VALUES hash(\"Laura\"):(\"Laura\", 8, \"three\", 20190901008)," - "hash(\"Amber\"):(\"Amber\", 9, \"four\", 20180901003)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),student(grade, number) " - "VALUES uuid(\"Laura\"):(\"Laura\", 8, \"three\", 20190901008)," - "uuid(\"Amber\"):(\"Amber\", 9, \"four\", 20180901003)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Multi vertices one tag - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) " - "VALUES hash(\"Kitty\"):(\"Kitty\", 8), hash(\"Peter\"):(\"Peter\", 9)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) " - "VALUES uuid(\"Kitty\"):(\"Kitty\", 8), uuid(\"Peter\"):(\"Peter\", 9)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Tom\")->hash(\"Lucy\"):(85, \"Lily\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Tom\")->uuid(\"Lucy\"):(85, \"Lucy\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert unordered order prop edge succeeded - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(nickname, likeness) VALUES " - "hash(\"Tom\")->hash(\"Bob\"):(\"Superman\", 87)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - cmd = "FETCH PROP ON schoolmate hash(\"Tom\")->hash(\"Bob\")"; - code = client_->execute(cmd, resp); - std::vector<std::tuple<int64_t, std::string>> expected = { - {87, "Superman"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Insert multi edges - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Tom\")->hash(\"Kitty\"):(81, \"Kitty\")," - "hash(\"Tom\")->hash(\"Peter\"):(83, \"Kitty\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Tom\")->uuid(\"Kitty\"):(81, \"Kitty\")," - "uuid(\"Tom\")->uuid(\"Peter\"):(83, \"Petter\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Get result - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Tom\") OVER schoolmate YIELD $^.person.name," - "schoolmate.likeness, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Tom", 85, "Lucy"}, - {"Tom", 81, "Kitty"}, - {"Tom", 83, "Peter"}, - {"Tom", 87, "Bob"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Tom\") OVER schoolmate YIELD $^.person.name," - "schoolmate.likeness, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Tom", 85, "Lucy"}, - {"Tom", 81, "Kitty"}, - {"Tom", 83, "Peter"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Get multi tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Lucy\")->hash(\"Laura\"):(90, \"Laura\")," - "hash(\"Lucy\")->hash(\"Amber\"):(95, \"Amber\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Lucy\")->uuid(\"Laura\"):(90, \"Laura\")," - "uuid(\"Lucy\")->uuid(\"Amber\"):(95, \"Amber\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Lucy\") OVER schoolmate YIELD " - "schoolmate.likeness, $$.person.name," - "$$.student.grade, $$.student.number"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<int64_t, std::string, std::string, int64_t>; - std::vector<valueType> expected = { - {90, "Laura", "three", 20190901008}, - {95, "Amber", "four", 20180901003}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Lucy\") OVER schoolmate YIELD " - "schoolmate.likeness, $$.person.name," - "$$.student.grade, $$.student.number"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<int64_t, std::string, std::string, int64_t>; - std::vector<valueType> expected = { - {90, "Laura", "three", 20190901008}, - {95, "Amber", "four", 20180901003}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Multi sentences to insert multi tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) " - "VALUES hash(\"Aero\"):(\"Aero\", 8);" - "INSERT VERTEX student(grade, number) " - "VALUES hash(\"Aero\"):(\"four\", 20190901003)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age)" - "VALUES uuid(\"Aero\"):(\"Aero\", 8);" - "INSERT VERTEX student(grade, number) " - "VALUES uuid(\"Aero\"):(\"four\", 20190901003)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Laura\")->hash(\"Aero\"):(90, \"Aero\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Laura\")->uuid(\"Aero\"):(90, \"Aero\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Get result - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Laura\") OVER schoolmate " - "YIELD $$.student.number, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<int64_t, std::string>; - std::vector<valueType> expected{ - {20190901003, "Aero"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Laura\") OVER schoolmate " - "YIELD $$.student.number, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<int64_t, std::string>; - std::vector<valueType> expected{ - {20190901003, "Aero"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test same prop name diff type in diff tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),employee(name) " - "VALUES hash(\"Joy\"):(\"Joy\", 18, 123)," - "hash(\"Petter\"):(\"Petter\", 19, 456)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),employee(name) " - "VALUES uuid(\"Joy\"):(\"Joy\", 18, 123)," - "uuid(\"Petter\"):(\"Petter\", 19, 456)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Joy\")->hash(\"Petter\"):(90, \"Petter\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Joy\")->uuid(\"Petter\"):(90, \"Petter\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Joy\") OVER schoolmate YIELD $^.person.name," - "schoolmate.likeness, $$.person.name, $$.person.age,$$.employee.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string, int64_t, int64_t>> expected = { - {"Joy", 90, "Petter", 19, 456}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Joy\") OVER schoolmate YIELD $^.person.name," - "schoolmate.likeness, $$.person.name, $$.person.age,$$.employee.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string, int64_t, int64_t>> expected = { - {"Joy", 90, "Petter", 19, 456}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test same prop name same type in diff tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),interest(name) " - "VALUES hash(\"Bob\"):(\"Bob\", 19, \"basketball\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age),interest(name) " - "VALUES uuid(\"Bob\"):(\"Bob\", 19, \"basketball\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Petter\")->hash(\"Bob\"):(90, \"Bob\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Petter\")->uuid(\"Bob\"):(90, \"Bob\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Petter\") OVER schoolmate " - "YIELD $^.person.name, $^.employee.name, " - "schoolmate.likeness, $$.person.name," - "$$.interest.name, $$.person.age"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using type = std::tuple<std::string, int64_t, int64_t, std::string, std::string, int64_t>; - std::vector<type> expected = { - {"Petter", 456, 90, "Bob", "basketball", 19}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Petter\") OVER schoolmate " - "YIELD $^.person.name, $^.employee.name, " - "schoolmate.likeness, $$.person.name," - "$$.interest.name, $$.person.age"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using type = std::tuple<std::string, int64_t, int64_t, std::string, std::string, int64_t>; - std::vector<type> expected = { - {"Petter", 456, 90, "Bob", "basketball", 19}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Insert wrong type - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Laura\")->hash(\"Amber\"):(\"87\", "")"; - auto code = client_->execute(cmd, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert wrong num of value - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) " - "VALUES hash(\"Laura\")->hash(\"Amber\"):(\"hello\", \"87\", "")"; - auto code = client_->execute(cmd, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert wrong num of prop - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness) VALUES " - "hash(\"Laura\")->hash(\"Amber\"):(87)"; - auto code = client_->execute(cmd, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert wrong field name - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(like, HH) VALUES " - "hash(\"Laura\")->hash(\"Amber\"):(88)"; - auto code = client_->execute(cmd, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert invalid timestamp - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE study(start_time, end_time) " - "VALUES hash(\"Laura\")->hash(\"sun_school\"):" - "(\"2300-01-01 10:00:00\", now()+3600*24*365*3)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Insert timestamp succeeded - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX school(name, create_time) VALUES " - "hash(\"sun_school\"):(\"sun_school\", \"2010-01-01 10:00:00\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX school(name, create_time) VALUES " - "uuid(\"sun_school\"):(\"sun_school\", \"2010-01-01 10:00:00\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE study(start_time, end_time) " - "VALUES hash(\"Laura\")->hash(\"sun_school\"):" - "(\"2019-01-01 10:00:00\", now()+3600*24*365*3)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE study(start_time, end_time) " - "VALUES uuid(\"Laura\")->uuid(\"sun_school\"):" - "(\"2019-01-01 10:00:00\", now()+3600*24*365*3)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Laura\") OVER study " - "YIELD $$.school.name, study._dst, " - "$$.school.create_time, (string)study.start_time"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, int64_t, std::string>> expected = { - {"sun_school", std::hash<std::string>()("sun_school"), 1262311200, "1546308000"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Laura\") OVER study " - "YIELD $$.school.name," - "$$.school.create_time, (string)study.start_time"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"sun_school", 1262311200, "1546308000"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "FETCH PROP ON school hash(\"sun_school\") ";; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {"sun_school", 1262311200}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "FETCH PROP ON school uuid(\"sun_school\") ";; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {"sun_school", 1262311200}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // TODO: Test insert multi tags, and delete one of them then check other existent -} - -TEST_F(DataTest, InsertWithDefaultValueTest) { - // Insert vertex using default value - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault() " - "VALUES hash(\"\"):()"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault" - "(name, age, isMarried, BMI, department, redundant)" - "VALUES hash(\"Tom\"):(\"Tom\", 18, false, 18.5, \"dev\", 0)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault(name) " - "VALUES hash(\"Tom\"):(\"Tom\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault(name, age) " - "VALUES hash(\"Tom\"):(\"Tom\", 20)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault(name, BMI) " - "VALUES hash(\"Tom\"):(\"Tom\", 20.5)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert vertices multi tags - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault(name, BMI)," - "studentWithDefault(number) VALUES " - "hash(\"Laura\"):(\"Laura\", 21.5, 20190901008)," - "hash(\"Amber\"):(\"Amber\", 22.5, 20180901003)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Multi vertices one tag - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX personWithDefault(name) VALUES " - "hash(\"Kitty\"):(\"Kitty\"), " - "hash(\"Peter\"):(\"Peter\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmateWithDefault() VALUES " - "hash(\"Tom\")->hash(\"Lucy\"):()"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmateWithDefault(likeness, redundant) VALUES " - "hash(\"Tom\")->hash(\"Lucy\"):(90, 0)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Insert multi edges with default value - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmateWithDefault() VALUES " - "hash(\"Tom\")->hash(\"Kitty\"):()," - "hash(\"Tom\")->hash(\"Peter\"):()," - "hash(\"Lucy\")->hash(\"Laura\"):()," - "hash(\"Lucy\")->hash(\"Amber\"):()"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Get result - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Tom\") OVER schoolmateWithDefault YIELD $^.person.name," - "schoolmateWithDefault.likeness, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Tom", 80, "Lucy"}, - {"Tom", 80, "Kitty"}, - {"Tom", 80, "Peter"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Lucy\") OVER schoolmateWithDefault YIELD " - "schoolmateWithDefault.likeness, $$.personWithDefault.name," - "$$.studentWithDefault.grade, $$.studentWithDefault.number"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<int64_t, std::string, std::string, int64_t>; - std::vector<valueType> expected = { - {80, "Laura", "one", 20190901008}, - {80, "Amber", "one", 20180901003}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(DataTest, InsertMultiVersionTest) { - // Insert multi version vertex - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "hash(\"Tony\"):(\"Tony\", 18), " - "hash(\"Mack\"):(\"Mack\", 19)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "hash(\"Mack\"):(\"Mack\", 20)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "hash(\"Mack\"):(\"Mack\", 21)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert multi version edge - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Tony\")->hash(\"Mack\")@1:(1, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Tony\")->hash(\"Mack\")@1:(2, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "hash(\"Tony\")->hash(\"Mack\")@1:(3, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Get result - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM hash(\"Tony\") OVER schoolmate " - "YIELD $$.person.name, $$.person.age, schoolmate.likeness"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, int64_t>; - // Get the latest result - std::vector<valueType> expected{ - {"Mack", 21, 3}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(DataTest, InsertMultiVersionWithUUIDTest) { - // Insert multi version vertex - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "uuid(\"Tony\"):(\"Tony\", 18), " - "uuid(\"Mack\"):(\"Mack\", 19)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "uuid(\"Mack\"):(\"Mack\", 20)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "uuid(\"Mack\"):(\"Mack\", 21)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Insert multi version edge - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Tony\")->uuid(\"Mack\")@1:(1, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Tony\")->uuid(\"Mack\")@1:(2, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness, nickname) VALUES " - "uuid(\"Tony\")->uuid(\"Mack\")@1:(3, \"\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Get result - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Tony\") OVER schoolmate " - "YIELD $$.person.name, $$.person.age, schoolmate.likeness"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, int64_t>; - // Get the latest result - std::vector<valueType> expected{ - {"Mack", 21, 3}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(DataTest, FindTest) { - { - cpp2::ExecutionResponse resp; - std::string cmd = "FIND name FROM person"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} - -TEST_F(DataTest, MatchTest) { - { - cpp2::ExecutionResponse resp; - std::string cmd = "MATCH"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/DeleteEdgesTest.cpp b/src/executor/test/DeleteEdgesTest.cpp deleted file mode 100644 index eb0db7e6e2f692d0ba450dd27a10b9dc8081fded..0000000000000000000000000000000000000000 --- a/src/executor/test/DeleteEdgesTest.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class DeleteEdgesTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } - - static void SetUpTestCase() { - client_ = gEnv->getClient(); - - ASSERT_NE(nullptr, client_); - - ASSERT_TRUE(prepareSchema()); - } - - static void TearDownTestCase() { - ASSERT_TRUE(removeData()); - client_.reset(); - } - -protected: - static AssertionResult prepareSchema(); - - static AssertionResult removeData(); - - static std::unique_ptr<GraphClient> client_; -}; - -std::unique_ptr<GraphClient> DeleteEdgesTest::client_{nullptr}; - -AssertionResult DeleteEdgesTest::prepareSchema() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE mySpace(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - sleep(FLAGS_load_data_interval_secs + 1); - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE mySpace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG person(name string, age int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE friend(intimacy int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE schoolmate(likeness int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE transfer(money int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - sleep(FLAGS_load_data_interval_secs + 1); - return TestOK(); -} - -AssertionResult DeleteEdgesTest::removeData() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE mySpace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed, code:" << static_cast<int>(code); - } - } - - return TestOK(); -} - -TEST_F(DeleteEdgesTest, DeleteEdges) { - // Insert vertices and edges - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT VERTEX person(name, age) VALUES " - "uuid(\"Zhangsan\"):(\"Zhangsan\", 22), uuid(\"Lisi\"):(\"Lisi\", 23)," - "uuid(\"Jack\"):(\"Jack\", 18), uuid(\"Rose\"):(\"Rose\", 19)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE friend(intimacy) VALUES " - "uuid(\"Zhangsan\")->uuid(\"Lisi\")@15:(90), " - "uuid(\"Zhangsan\")->uuid(\"Jack\")@12:(50)," - "uuid(\"Jack\")->uuid(\"Rose\")@13:(100)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE schoolmate(likeness) VALUES " - "uuid(\"Zhangsan\")->uuid(\"Jack\"):(60)," - "uuid(\"Lisi\")->uuid(\"Rose\"):(70)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "INSERT EDGE transfer(money) VALUES " - "uuid(\"Zhangsan\")->uuid(\"Lisi\")@1561013236:(33)," - "uuid(\"Zhangsan\")->uuid(\"Lisi\")@1561013237:(77)"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Traverse - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"),uuid(\"Jack\") OVER friend " - "YIELD $^.person.name, friend.intimacy, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 90, "Lisi"}, - {"Zhangsan", 50, "Jack"}, - {"Jack", 100, "Rose"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"), uuid(\"Lisi\") OVER schoolmate " - "YIELD $^.person.name, schoolmate.likeness, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 60, "Jack"}, - {"Lisi", 70, "Rose"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\") OVER transfer YIELD $^.person.name," - "transfer._rank, transfer.money, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 1561013236, 33, "Lisi"}, - {"Zhangsan", 1561013237, 77, "Lisi"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Delete edges - { - cpp2::ExecutionResponse resp; - std::string cmd ="DELETE EDGE friend uuid(\"Zhangsan\")->uuid(\"Lisi\")@15," - "uuid(\"Jack\")->uuid(\"Rose\")@13"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd ="DELETE EDGE schoolmate uuid(\"Lisi\")->uuid(\"Rose\")"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd ="DELETE EDGE transfer uuid(\"Zhangsan\")->uuid(\"Lisi\")@1561013237"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Traverse again - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"),uuid(\"Jack\") OVER friend " - "YIELD $^.person.name, friend.intimacy, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 50, "Jack"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"), uuid(\"Lisi\") OVER schoolmate " - "YIELD $^.person.name, schoolmate.likeness, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 60, "Jack"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"), uuid(\"Jack\") OVER transfer " - "YIELD $^.person.name, transfer._rank, transfer.money, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 1561013236, 33, "Lisi"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Delete non-existing edges and a same edge - { - cpp2::ExecutionResponse resp; - std::string cmd ="DELETE EDGE friend uuid(\"Zhangsan\")->uuid(\"Rose\"), 1008->1009@17," - "uuid(\"Zhangsan\")->uuid(\"Lisi\")@15"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Traverse again - { - cpp2::ExecutionResponse resp; - std::string cmd = "GO FROM uuid(\"Zhangsan\"),uuid(\"Jack\") OVER friend " - "YIELD $^.person.name, friend.intimacy, $$.person.name"; - auto code = client_->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - using valueType = std::tuple<std::string, int64_t, std::string>; - std::vector<valueType> expected = { - {"Zhangsan", 50, "Jack"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/DeleteVertexTest.cpp b/src/executor/test/DeleteVertexTest.cpp deleted file mode 100644 index f2cdd9202ad72efd285bdd6cb8444a24abebec77..0000000000000000000000000000000000000000 --- a/src/executor/test/DeleteVertexTest.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - - -namespace nebula { -namespace graph { - -class DeleteVertexTest : public TraverseTestBase { - protected: - void SetUp() override { - TraverseTestBase::SetUp(); - } - - void TearDown() override { - TraverseTestBase::TearDown(); - } -}; - -TEST_F(DeleteVertexTest, Base) { - // Check - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like"; - auto query = folly::stringPrintf(fmt, players_["Boris Diaw"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {players_["Tony Parker"].vid()}, - {players_["Tim Duncan"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto *fmt = "FETCH PROP ON player %ld YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld " - "YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Delete vertex - { - cpp2::ExecutionResponse resp; - auto *fmt = "DELETE VERTEX %ld"; - auto query = folly::stringPrintf(fmt, players_["Tony Parker"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Check again - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like"; - auto query = folly::stringPrintf(fmt, players_["Boris Diaw"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {players_["Tim Duncan"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto *fmt = "FETCH PROP ON player %ld YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld " - "YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto query = "FETCH PROP ON player uuid(\"Tony Parker\") " - "YIELD player.name, player.age"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tony Parker"]; - auto &serve = player.serves()[0]; - auto query = "FETCH PROP ON serve uuid(\"Tony Parker\")->uuid(\"Spurs\") " - "YIELD serve.start_year, serve.end_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Delete vertex - { - cpp2::ExecutionResponse resp; - auto query = "DELETE VERTEX uuid(\"Tony Parker\")"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON player uuid(\"Tony Parker\") " - "YIELD player.name, player.age"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve uuid(\"Tony Parker\")->uuid(\"Spurs\") " - "YIELD serve.start_year, serve.end_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Delete non-existing vertex - { - cpp2::ExecutionResponse resp; - auto query = "DELETE VERTEX uuid(\"Non-existing Vertex\")"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - - // Delete a vertex without edges - { - // Insert a vertex without edges - cpp2::ExecutionResponse resp; - auto query = "INSERT VERTEX player(name, age) " - "VALUES uuid(\"A Loner\"): (\"A Loner\", 0)"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "DELETE VERTEX uuid(\"A Loner\")"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON player uuid(\"A Loner\") " - "YIELD player.name, player.age"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/test/FetchEdgesTest.cpp b/src/executor/test/FetchEdgesTest.cpp deleted file mode 100644 index d5d396b746f9ad1ebbb03b8f06b86e62d9bcc715..0000000000000000000000000000000000000000 --- a/src/executor/test/FetchEdgesTest.cpp +++ /dev/null @@ -1,437 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - - -namespace nebula { -namespace graph { -class FetchEdgesTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - } - - void TearDown() override { - TraverseTestBase::TearDown(); - } -}; - -TEST_F(FetchEdgesTest, Base) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld" - " YIELD serve.start_year > 2001, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"(serve.start_year>2001)"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<bool, int64_t>> expected = { - {std::get<1>(serve) > 2001, std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld@0" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve0 = player.serves()[0]; - auto &team0 = teams_[std::get<0>(serve0)]; - auto &serve1 = player.serves()[1]; - auto &team1 = teams_[std::get<0>(serve1)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld,%ld->%ld" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf( - fmt, player.vid(), team0.vid(), player.vid(), team1.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve0), std::get<2>(serve0)}, - {std::get<1>(serve1), std::get<2>(serve1)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER serve YIELD serve._src AS src, serve._dst AS dst" - "| FETCH PROP ON serve $-.src->$-.dst" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected; - for (auto &serve : player.serves()) { - std::tuple<int64_t, int64_t> result(std::get<1>(serve), std::get<2>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "$var = GO FROM %ld OVER serve" - " YIELD serve._src AS src, serve._dst AS dst;" - "FETCH PROP ON serve $var.src->$var.dst" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected; - for (auto &serve : player.serves()) { - std::tuple<int64_t, int64_t> result(std::get<1>(serve), std::get<2>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve hash(\"%s\")->hash(\"%s\") " - "YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.name().c_str(), team.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve uuid(\"%s\")->uuid(\"%s\") " - "YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.name().c_str(), team.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchEdgesTest, NoYield) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld@0"; - auto query = folly::stringPrintf(fmt, player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve hash(\"%s\")->hash(\"%s\")"; - auto query = folly::stringPrintf(fmt, player.name().c_str(), team.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve uuid(\"%s\")->uuid(\"%s\")"; - auto query = folly::stringPrintf(fmt, player.name().c_str(), team.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchEdgesTest, Distinct) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto &serve = player.serves()[0]; - auto &team = teams_[std::get<0>(serve)]; - auto *fmt = "FETCH PROP ON serve %ld->%ld,%ld->%ld" - " YIELD DISTINCT serve.start_year, serve.end_year"; - auto query = folly::stringPrintf( - fmt, player.vid(), team.vid(), player.vid(), team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected = { - {std::get<1>(serve), std::get<2>(serve)}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld,%ld OVER serve YIELD serve._src AS src, serve._dst AS dst" - "| FETCH PROP ON serve $-.src->$-.dst" - " YIELD DISTINCT serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected; - for (auto &serve : player.serves()) { - std::tuple<int64_t, int64_t> result(std::get<1>(serve), std::get<2>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "$var = GO FROM %ld,%ld OVER serve" - " YIELD serve._src AS src, serve._dst AS dst;" - "FETCH PROP ON serve $var.src->$var.dst" - " YIELD DISTINCT serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, player.vid(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, int64_t>> expected; - for (auto &serve : player.serves()) { - std::tuple<int64_t, int64_t> result(std::get<1>(serve), std::get<2>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto *fmt = "GO FROM %ld,%ld OVER serve YIELD serve._src AS src, serve._dst AS dst" - "| FETCH PROP ON serve $-.src->$-.dst" - " YIELD DISTINCT serve._dst"; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchEdgesTest, EmptyInput) { - { - cpp2::ExecutionResponse resp; - auto &nobody = players_["Nobody"]; - auto *fmt = "GO FROM %ld OVER serve YIELD serve._src AS src, serve._dst AS dst" - "| FETCH PROP ON serve $-.src->$-.dst" - " YIELD serve.start_year, serve.end_year"; - auto query = folly::stringPrintf(fmt, nobody.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"serve.end_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } -} - -TEST_F(FetchEdgesTest, SyntaxError) { - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve hash(\"Boris Diaw\")->hash(\"Spurs\") " - "YIELD $^.serve.start_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve hash(\"Boris Diaw\")->hash(\"Spurs\") " - "YIELD $$.serve.start_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve hash(\"Boris Diaw\")->hash(\"Spurs\") " - "YIELD abc.start_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(FetchEdgesTest, NonExistEdge) { - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve hash(\"Zion Williamson\")->hash(\"Spurs\") " - "YIELD serve.start_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto query = "FETCH PROP ON serve uuid(\"Zion Williamson\")->uuid(\"Spurs\") " - "YIELD serve.start_year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/FetchVerticesTest.cpp b/src/executor/test/FetchVerticesTest.cpp deleted file mode 100644 index 612af0a8a39cc32cbf5481c803d7b192419445be..0000000000000000000000000000000000000000 --- a/src/executor/test/FetchVerticesTest.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - - -namespace nebula { -namespace graph { - -class FetchVerticesTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - } - - void TearDown() override { - TraverseTestBase::TearDown(); - } -}; - -TEST_F(FetchVerticesTest, Base) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld " - "YIELD player.name, player.age, player.age > 30"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"}, {"(player.age>30)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, bool>> expected = { - {player.name(), player.age(), player.age() > 30}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld over like YIELD like._dst as id" - "| FETCH PROP ON player $-.id YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Tony Parker", players_["Tony Parker"].age()}, - {"Tim Duncan", players_["Tim Duncan"].age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "$var = GO FROM %ld over like YIELD like._dst as id;" - "FETCH PROP ON player $var.id YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Tony Parker", players_["Tony Parker"].age()}, - {"Tim Duncan", players_["Tim Duncan"].age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "$var = GO FROM %ld over like YIELD like._dst as id;" - "FETCH PROP ON player $var.id YIELD player.name as name, player.age" - " | ORDER BY name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Tim Duncan", players_["Tim Duncan"].age()}, - {"Tony Parker", players_["Tony Parker"].age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player hash(\"%s\") " - "YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player uuid(\"%s\") " - "YIELD player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchVerticesTest, NoYield) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player hash(\"%s\")"; - auto query = folly::stringPrintf(fmt, player.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player uuid(\"%s\")"; - auto query = folly::stringPrintf(fmt, player.name().c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchVerticesTest, Distinct) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld,%ld" - " YIELD DISTINCT player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.name"}, {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {player.name(), player.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &tony = players_["Tony Parker"]; - auto *fmt = "FETCH PROP ON player %ld,%ld" - " YIELD DISTINCT player.age"; - auto query = folly::stringPrintf(fmt, boris.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"player.age"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {boris.age()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(FetchVerticesTest, SyntaxError) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld YIELD $^.player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld YIELD $$.player.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON player %ld YIELD abc.name, player.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(FetchVerticesTest, ExecutionError) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "FETCH PROP ON abc %ld"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} - -TEST_F(FetchVerticesTest, NonExistVertex) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FETCH PROP ON player %ld"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve" - " | FETCH PROP ON team $-"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/FindPathTest.cpp b/src/executor/test/FindPathTest.cpp deleted file mode 100644 index 9419fa8d24b9b724ef1c8cb63017c79521fc0ff5..0000000000000000000000000000000000000000 --- a/src/executor/test/FindPathTest.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - -namespace nebula { -namespace graph { - -class FindPathTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - } - - void TearDown() override { - TraverseTestBase::TearDown(); - } -}; - -TEST_F(FindPathTest, SingleEdgeShortest) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), manu.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tim.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld,%ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), manu.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tiago = players_["Tiago Splitter"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tiago.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "-8160811731890648949<like,0>5662213458193308137<like,0>-7579316172763586624" - "<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - // we only find the shortest path to the dest, - // so -8160811731890648949 to -1782445125509592239 is not in result - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld,%ld TO %ld,%ld,%ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tiago = players_["Tiago Splitter"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tiago.vid(), - tony.vid(), manu.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like yield like._src AS src, like._dst AS dst | " - "FIND SHORTEST PATH FROM $-.src TO $-.dst OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$var = GO FROM %ld OVER like yield like._src AS src, like._dst AS dst;" - "FIND SHORTEST PATH FROM $var.src TO $var.dst OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$var = GO FROM %ld OVER like yield like._src AS src;" - "GO FROM %ld OVER like yield like._src AS src, like._dst AS dst | " - "FIND SHORTEST PATH FROM $var.src TO $-.dst OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } -} - -TEST_F(FindPathTest, SingleEdgeAll) { - /* - * TODO: There might exist loops when find all path, - * we should provide users with an option on whether or not a loop is required. - */ - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 3 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<like,0>-7579316172763586624" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld,%ld OVER like UPTO 3 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), manu.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<like,0>3394245602834314645", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<like,0>3394245602834314645" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 3 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tim.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 3 STEPS"; - auto &tiago = players_["Tiago Splitter"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tiago.vid(), al.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "-8160811731890648949<like,0>5662213458193308137<like,0>-7579316172763586624" - "<like,0>-1782445125509592239" - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } -} - -TEST_F(FindPathTest, MultiEdgesShortest) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like,serve UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld OVER like,serve UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld,%ld,%ld " - "OVER like,serve UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, - tim.vid(), - tony.vid(), manu.vid(), al.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239", - "5662213458193308137<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld OVER like,serve UPTO 5 STEPS"; - auto &tiago = players_["Tiago Splitter"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tiago.vid(), al.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "-8160811731890648949<like,0>5662213458193308137<like,0>-7579316172763586624" - "<like,0>-1782445125509592239", - "-8160811731890648949<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER * UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld OVER * UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld,%ld,%ld " - "OVER * UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, - tim.vid(), - tony.vid(), manu.vid(), al.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>3394245602834314645", - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239", - "5662213458193308137<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld,%ld OVER * UPTO 5 STEPS"; - auto &tiago = players_["Tiago Splitter"]; - auto &al = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, tiago.vid(), al.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "-8160811731890648949<like,0>5662213458193308137<like,0>-7579316172763586624" - "<like,0>-1782445125509592239", - "-8160811731890648949<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } -} - -TEST_F(FindPathTest, MultiEdgesAll) { - /* - * TODO: There might exist loops when find all path, - * we should provide users with an option on whether or not a loop is required. - */ - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld,%ld OVER like,serve UPTO 3 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<serve,0>7193291116733635180", - "5662213458193308137<like,0>3394245602834314645<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>3394245602834314645" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld,%ld OVER * UPTO 3 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), teams_["Spurs"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected = { - "5662213458193308137<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<like,0>-7579316172763586624", - "5662213458193308137<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<serve,0>7193291116733635180", - "5662213458193308137<like,0>3394245602834314645<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>-1782445125509592239" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>3394245602834314645" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>-7579316172763586624<like,0>5662213458193308137" - "<serve,0>7193291116733635180", - "5662213458193308137<like,0>3394245602834314645<like,0>5662213458193308137" - "<serve,0>7193291116733635180", - }; - ASSERT_TRUE(verifyPath(resp, expected)); - } -} - -TEST_F(FindPathTest, VertexNotExist) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto query = folly::stringPrintf(fmt, - std::hash<std::string>()("Nobody1"), std::hash<std::string>()("Nobody2")); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, tim.vid(), std::hash<std::string>()("Nobody")); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND SHORTEST PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, std::hash<std::string>()("Nobody"), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto query = folly::stringPrintf(fmt, - std::hash<std::string>()("Nobody1"), std::hash<std::string>()("Nobody2")); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, tim.vid(), std::hash<std::string>()("Nobody")); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "FIND ALL PATH FROM %ld TO %ld OVER like UPTO 5 STEPS"; - auto &tim = players_["Tim Duncan"]; - auto query = folly::stringPrintf(fmt, std::hash<std::string>()("Nobody"), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *(resp.get_error_msg()); - std::vector<std::string> expected; - ASSERT_TRUE(verifyPath(resp, expected)); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/GeoTest.cpp b/src/executor/test/GeoTest.cpp deleted file mode 100644 index eedfce496e835436aca977c4f790cc80f0c03d9b..0000000000000000000000000000000000000000 --- a/src/executor/test/GeoTest.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" -#include "filter/geo/GeoIndex.h" -#include "filter/geo/GeoParams.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class GeoTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } - - static void SetUpTestCase() { - client_ = gEnv->getClient(); - storagePort_ = gEnv->storageServerPort(); - - ASSERT_NE(nullptr, client_); - - ASSERT_TRUE(prepareSchema()); - - ASSERT_TRUE(prepareData()); - } - - static void TearDownTestCase() { - ASSERT_TRUE(removeData()); - client_.reset(); - } - - static AssertionResult prepareSchema(); - - static AssertionResult prepareData(); - - static AssertionResult removeData(); - - class Merchant final { - public: - Merchant(std::string name, std::string coordinate, double rate) { - name_ = std::move(name); - coordinate_ = std::move(coordinate); - rate_ = rate; - } - - std::string name() const { - return name_; - } - - std::string coordinate() const { - return coordinate_; - } - - double rate() const { - return rate_; - } - - private: - std::string name_; - std::string coordinate_; - double rate_; - }; - -protected: - static uint16_t storagePort_; - static std::unique_ptr<GraphClient> client_; - static std::vector<Merchant> merchants_; -}; - -uint16_t GeoTest::storagePort_; -std::unique_ptr<GraphClient> GeoTest::client_; -std::vector<GeoTest::Merchant> GeoTest::merchants_ = { - Merchant{"HCYQJ Convenience", "(30.28522 120.01338)", 4.1}, - Merchant{"LYJ Convenience", "(30.28115 120.01438)", 3.7} -}; - -// static -AssertionResult GeoTest::prepareSchema() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE geo(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE myspace(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE myspace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG merchant(name string, coordinate string, rate double)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE geo"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE locate(name string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - - sleep(10 + 3); - return TestOK(); -} - -AssertionResult GeoTest::prepareData() { - { - cpp2::ExecutionResponse resp; - std::string query = "INSERT EDGE locate(name) VALUES "; - geo::Point loc; - geo::GeoIndex geoIndex; - std::vector<S2CellId> cells; - for (decltype(merchants_.size()) index = 0; index < merchants_.size(); ++index) { - auto &merchant = merchants_[index]; - std::string locStr = geo::kWktPointPrefix; - locStr += merchant.coordinate(); - boost::geometry::read_wkt(locStr, loc); - geoIndex.indexCellsForPoint(loc, cells); - for (auto &cell : cells) { - query += folly::to<std::string>(cell.id()); - query += " -> "; - query += folly::to<std::string>(index); - query += ": (\""; - query += merchant.name(); - query += "\"),\n\t"; - } - cells.clear(); - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `locate' failed: " - << static_cast<int32_t>(code) - << " errmsg:" << *resp.get_error_msg(); - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE myspace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string query = "INSERT VERTEX merchant(name, coordinate, rate) VALUES "; - for (decltype(merchants_.size()) index = 0; index < merchants_.size(); ++index) { - auto &merchant = merchants_[index]; - query += folly::to<std::string>(index); - query += ": (\""; - query += merchant.name(); - query += "\",\""; - query += merchant.coordinate(); - query += "\","; - query += folly::to<std::string>(merchant.rate()); - query += "),\n\t"; - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `merchant' failed: " - << static_cast<int32_t>(code); - } - } - - return TestOK(); -} - -AssertionResult GeoTest::removeData() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE geo"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE myspace"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - return TestOK(); -} - -TEST_F(GeoTest, Near) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "USE geo;" - "GO FROM near(%s, 5000) OVER locate"; - std::string vesoftLoc = "\"(30.28243 120.01198)\""; - std::string query = folly::stringPrintf(fmt, vesoftLoc.c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"locate._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {0}, - {1} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "USE geo;" - "$locate = GO FROM near(%s, 5000) OVER locate YIELD locate._dst as id;" - "USE myspace;" - "FETCH PROP on merchant $locate.id;"; - std::string vesoftLoc = "\"(30.28243 120.01198)\""; - std::string query = folly::stringPrintf(fmt, vesoftLoc.c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"merchant.name"}, {"merchant.coordinate"}, {"merchant.rate"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, double>> expected = { - {merchants_[0].name(), merchants_[0].coordinate(), merchants_[0].rate()}, - {merchants_[1].name(), merchants_[1].coordinate(), merchants_[1].rate()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "USE geo;" - "$locate = GO FROM near(%s, 5000) OVER locate YIELD locate._dst as id;" - "USE myspace;" - "FETCH PROP on merchant $locate.id" - " YIELD merchant.name AS name, merchant.rate AS rate" - " | ORDER BY $-.rate;"; - std::string vesoftLoc = "\"(30.28243 120.01198)\""; - std::string query = folly::stringPrintf(fmt, vesoftLoc.c_str()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"rate"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, double>> expected = { - {merchants_[1].name(), merchants_[1].rate()}, - {merchants_[0].name(), merchants_[0].rate()}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/GoTest.cpp b/src/executor/test/GoTest.cpp deleted file mode 100644 index 2dbee267e98334259710876b2c17053b3def92dd..0000000000000000000000000000000000000000 --- a/src/executor/test/GoTest.cpp +++ /dev/null @@ -1,1085 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - - -namespace nebula { -namespace graph { - -class GoTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TraverseTestBase::TearDown(); - } -}; - -TEST_F(GoTest, OneStepOutBound) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve"; - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name, serve.start_year, serve.end_year, $$.team.name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"serve.end_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, int64_t, std::string>> expected = { - {player.name(), 2003, 2005, "Hawks"}, - {player.name(), 2005, 2008, "Suns"}, - {player.name(), 2008, 2012, "Hornets"}, - {player.name(), 2012, 2016, "Spurs"}, - {player.name(), 2016, 2017, "Jazz"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Rajon Rondo"]; - auto *fmt = "GO FROM %ld OVER serve WHERE " - "serve.start_year >= 2013 && serve.end_year <= 2018 YIELD " - "$^.player.name, serve.start_year, serve.end_year, $$.team.name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"serve.end_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, int64_t, std::string>> expected = { - {player.name(), 2014, 2015, "Mavericks"}, - {player.name(), 2015, 2016, "Kings"}, - {player.name(), 2016, 2017, "Bulls"}, - {player.name(), 2017, 2018, "Pelicans"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst as id" - "| GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - {teams_["Trail Blazers"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = - "GO FROM %ld OVER like YIELD like._dst as id" - "| ( GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve )"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - {teams_["Trail Blazers"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, AssignmentSimple) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tracy McGrady"]; - auto *fmt = "$var = GO FROM %ld OVER like YIELD like._dst as id; " - "GO FROM $var.id OVER like"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"like._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<uint64_t>> expected = { - {players_["Tracy McGrady"].vid()}, - {players_["LaMarcus Aldridge"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, AssignmentPipe) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Tracy McGrady"]; - auto *fmt = - "$var = (GO FROM %ld OVER like YIELD like._dst as id | GO FROM $-.id OVER like YIELD " - "like._dst as id);" - "GO FROM $var.id OVER like"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"like._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<uint64_t>> expected = { - {players_["Kobe Bryant"].vid()}, - {players_["Grant Hill"].vid()}, - {players_["Rudy Gay"].vid()}, - {players_["Tony Parker"].vid()}, - {players_["Tim Duncan"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, VariableUndefined) { - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM $var OVER like"; - auto code = client_->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } -} - - -TEST_F(GoTest, AssignmentEmptyResult) { - { - cpp2::ExecutionResponse resp; - auto query = "$var = GO FROM -1 OVER like YIELD like._dst as id; " - "GO FROM $var.id OVER like"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<uint64_t>> expected = { - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -// REVERSELY not supported yet -TEST_F(GoTest, DISABLED_OneStepInBound) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve REVERSELY"; - auto &team = teams_["Thunders"]; - auto query = folly::stringPrintf(fmt, team.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {players_["Russell Westbrook"].vid()}, - {players_["Kevin Durant"].vid()}, - {players_["James Harden"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -// REVERSELY not supported yet -TEST_F(GoTest, DISABLED_OneStepInOutBound) { - // Ever served in the same team - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve | GO FROM $-.serve_id OVER serve REVERSELY"; - auto &player = players_["Kobe Bryant"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {players_["LeBron James"].vid()}, - {players_["Rajon Rondo"].vid()}, - {players_["Kobe Bryant"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Ever been teammates - { - } -} - -TEST_F(GoTest, Distinct) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Nobody"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD DISTINCT $^.player.name as name, $$.team.name as name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst as id" - "| GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve " - "YIELD DISTINCT serve._dst, $$.team.name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t, std::string>> expected = { - {teams_["Spurs"].vid(), "Spurs"}, - {teams_["Hornets"].vid(), "Hornets"}, - {teams_["Trail Blazers"].vid(), "Trail Blazers"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, VertexNotExist) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name, serve.start_year, serve.end_year, $$.team.name"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD DISTINCT " - "$^.player.name, serve.start_year, serve.end_year, $$.team.name"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve | GO FROM $-.serve_id OVER serve"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst as id" - "| GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst as id" - "| (GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve)"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } -} - -TEST_F(GoTest, MULTI_EDGES) { - // Ever served in the same team - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve, like"; - auto &player = players_["Russell Westbrook"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {teams_["Thunders"].vid(), 0}, - {0, players_["Paul George"].vid()}, - {0, players_["James Harden"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve, like yield serve.start_year, like.likeness"; - auto &player = players_["Russell Westbrook"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {2008, 0}, - {0, 90}, - {0, 90}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve, like"; - auto &player = players_["Shaquile O'Neal"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {teams_["Magic"].vid(), 0}, - {teams_["Lakers"].vid(), 0}, - {teams_["Heat"].vid(), 0}, - {teams_["Suns"].vid(), 0}, - {teams_["Cavaliers"].vid(), 0}, - {teams_["Celtics"].vid(), 0}, - {0, players_["JaVale McGee"].vid()}, - {0, players_["Tim Duncan"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER * YIELD serve._dst, like._dst"; - auto &player = players_["Dirk Nowitzki"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {teams_["Mavericks"].vid(), 0}, - {0, players_["Steve Nash"].vid()}, - {0, players_["Jason Kidd"].vid()}, - {0, players_["Dwyane Wade"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER *"; - auto &player = players_["Paul Gasol"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {0, teams_["Grizzlies"].vid()}, {0, teams_["Lakers"].vid()}, - {0, teams_["Bulls"].vid()}, {0, teams_["Spurs"].vid()}, - {0, teams_["Bucks"].vid()}, {players_["Kobe Bryant"].vid(), 0}, - {players_["Marc Gasol"].vid(), 0}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER * YIELD $$.team.name, $$.player.name"; - auto &player = players_["LaMarcus Aldridge"]; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, std::string>> expected = { - {"Trail Blazers", ""}, - {"", "Tim Duncan"}, - {"", "Tony Parker"}, - {"Spurs", ""}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = - "GO FROM %ld OVER like, serve YIELD like._dst as id" - "| ( GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve )"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - {teams_["Trail Blazers"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = - "GO FROM %ld OVER * YIELD like._dst as id" - "| ( GO FROM $-.id OVER like YIELD like._dst as id | GO FROM $-.id OVER serve )"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - {teams_["Trail Blazers"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(GoTest, ReferencePipeInYieldAndWhere) { - { - cpp2::ExecutionResponse resp; - std::string query = "GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id " - "| GO FROM $-.id OVER like " - "YIELD $-.name, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$-.name"}, {"$^.player.name"}, {"$$.player.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<uniform_tuple_t<std::string, 3>> expected = { - {"Tim Duncan", "Manu Ginobili", "Tim Duncan"}, - {"Tim Duncan", "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", "Tony Parker", "Manu Ginobili"}, - {"Tim Duncan", "Tony Parker", "Tim Duncan"}, - {"Chris Paul", "LeBron James", "Ray Allen"}, - {"Chris Paul", "Carmelo Anthony", "Chris Paul"}, - {"Chris Paul", "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", "Dwyane Wade", "Chris Paul"}, - {"Chris Paul", "Dwyane Wade", "LeBron James"}, - {"Chris Paul", "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id " - "| GO FROM $-.id OVER like " - "WHERE $-.name != $$.player.name " - "YIELD $-.name, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$-.name"}, {"$^.player.name"}, {"$$.player.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<uniform_tuple_t<std::string, 3>> expected = { - {"Tim Duncan", "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", "Tony Parker", "Manu Ginobili"}, - {"Chris Paul", "LeBron James", "Ray Allen"}, - {"Chris Paul", "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", "Dwyane Wade", "LeBron James"}, - {"Chris Paul", "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id " - "| GO FROM $-.id OVER like " - "YIELD $-.*, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - auto &manu = players_["Manu Ginobili"]; - auto &tony = players_["Tony Parker"]; - auto &lebron = players_["LeBron James"]; - auto &melo = players_["Carmelo Anthony"]; - auto &wade = players_["Dwyane Wade"]; - std::vector<std::tuple<std::string, uint64_t, std::string, std::string>> expected = { - {"Tim Duncan", manu.vid(), "Manu Ginobili", "Tim Duncan"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "Manu Ginobili"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "Tim Duncan"}, - {"Chris Paul", lebron.vid(), "LeBron James", "Ray Allen"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "Chris Paul"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "Chris Paul"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "LeBron James"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, ReferenceVariableInYieldAndWhere) { - { - cpp2::ExecutionResponse resp; - std::string query = "$var = GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id; " - "GO FROM $var.id OVER like " - "YIELD $var.name, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$var.name"}, {"$^.player.name"}, {"$$.player.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<uniform_tuple_t<std::string, 3>> expected = { - {"Tim Duncan", "Manu Ginobili", "Tim Duncan"}, - {"Tim Duncan", "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", "Tony Parker", "Manu Ginobili"}, - {"Tim Duncan", "Tony Parker", "Tim Duncan"}, - {"Chris Paul", "LeBron James", "Ray Allen"}, - {"Chris Paul", "Carmelo Anthony", "Chris Paul"}, - {"Chris Paul", "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", "Dwyane Wade", "Chris Paul"}, - {"Chris Paul", "Dwyane Wade", "LeBron James"}, - {"Chris Paul", "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "$var = GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id; " - "GO FROM $var.id OVER like " - "WHERE $var.name != $$.player.name " - "YIELD $var.name, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$var.name"}, {"$^.player.name"}, {"$$.player.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<uniform_tuple_t<std::string, 3>> expected = { - {"Tim Duncan", "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", "Tony Parker", "Manu Ginobili"}, - {"Chris Paul", "LeBron James", "Ray Allen"}, - {"Chris Paul", "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", "Dwyane Wade", "LeBron James"}, - {"Chris Paul", "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "$var = GO FROM hash('Tim Duncan'),hash('Chris Paul') OVER like " - "YIELD $^.player.name AS name, like._dst AS id; " - "GO FROM $var.id OVER like " - "YIELD $var.*, $^.player.name, $$.player.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - auto &manu = players_["Manu Ginobili"]; - auto &tony = players_["Tony Parker"]; - auto &lebron = players_["LeBron James"]; - auto &melo = players_["Carmelo Anthony"]; - auto &wade = players_["Dwyane Wade"]; - std::vector<std::tuple<std::string, uint64_t, std::string, std::string>> expected = { - {"Tim Duncan", manu.vid(), "Manu Ginobili", "Tim Duncan"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "LaMarcus Aldridge"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "Manu Ginobili"}, - {"Tim Duncan", tony.vid(), "Tony Parker", "Tim Duncan"}, - {"Chris Paul", lebron.vid(), "LeBron James", "Ray Allen"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "Chris Paul"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "LeBron James"}, - {"Chris Paul", melo.vid(), "Carmelo Anthony", "Dwyane Wade"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "Chris Paul"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "LeBron James"}, - {"Chris Paul", wade.vid(), "Dwyane Wade", "Carmelo Anthony"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(GoTest, NotExistTagProp) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve yield $^.test"; - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve yield serve.test"; - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } -} - -TEST_F(GoTest, is_inCall) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER serve " - "WHERE udf_is_in($$.team.name, \"Hawks\", \"Suns\") " - "YIELD $^.player.name, serve.start_year, serve.end_year, $$.team.name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *resp.get_error_msg(); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"serve.end_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, int64_t, std::string>> expected = { - {player.name(), 2003, 2005, "Hawks"}, - {player.name(), 2005, 2008, "Suns"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst AS id" - "| GO FROM $-.id OVER serve WHERE udf_is_in($-.id, %ld, 123)"; - auto query = folly::stringPrintf(fmt, - players_["Tim Duncan"].vid(), players_["Tony Parker"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like YIELD like._dst AS id" - "| GO FROM $-.id OVER serve WHERE udf_is_in($-.id, %ld, 123) && 1 == 1"; - auto query = folly::stringPrintf(fmt, - players_["Tim Duncan"].vid(), players_["Tony Parker"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(GoTest, returnTest) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE $A.dst == 123;" - "RETURN $rA IF $rA IS NOT NULL;" /* will not return */ - "GO FROM $A.dst OVER serve"; /* 2nd hop */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Hornets"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE 1 == 1;" - "RETURN $rA IF $rA IS NOT NULL;" /* will return */ - "GO FROM $A.dst OVER serve"; /* 2nd hop */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$A.dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {players_["Tony Parker"].vid()}, - {players_["Manu Ginobili"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dstA;" /* 1st hop */ - "$rA = YIELD $A.* WHERE $A.dstA == 123;" - "RETURN $rA IF $rA IS NOT NULL;" /* will not return */ - "$B = GO FROM $A.dstA OVER like YIELD like._dst AS dstB;" /* 2nd hop */ - "$rB = YIELD $B.* WHERE $B.dstB == 456;" - "RETURN $rB IF $rB IS NOT NULL;" /* will not return */ - "GO FROM $B.dstB OVER serve"; /* 3rd hop */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Trail Blazers"].vid()}, - {teams_["Spurs"].vid()}, - {teams_["Spurs"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE $A.dst == 123;" - "RETURN $rA IF $rA IS NOT NULL;"; /* will return nothing */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$A.dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE 1 == 1;" - "RETURN $rA IF $rA IS NOT NULL;"; /* will return */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$A.dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - {players_["Tony Parker"].vid()}, - {players_["Manu Ginobili"].vid()}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE 1 == 1;" - "RETURN $B IF $B IS NOT NULL;"; /* will return error */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "$A = GO FROM %ld OVER like YIELD like._dst AS dst;" /* 1st hop */ - "$rA = YIELD $A.* WHERE 1 == 1;" - "RETURN $B IF $A IS NOT NULL;"; /* will return error */ - auto query = folly::stringPrintf(fmt, players_["Tim Duncan"].vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "RETURN $rA IF $rA IS NOT NULL;"; /* will return error */ - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} - - -TEST_F(GoTest, ReverselyOneStep) { - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY " - "YIELD like._src"; - client_->execute(query, resp); - std::vector<std::tuple<int64_t>> expected = { - { players_["Tony Parker"].vid() }, - { players_["Manu Ginobili"].vid() }, - { players_["LaMarcus Aldridge"].vid() }, - { players_["Marco Belinelli"].vid() }, - { players_["Danny Green"].vid() }, - { players_["Aron Baynes"].vid() }, - { players_["Boris Diaw"].vid() }, - { players_["Tiago Splitter"].vid() }, - { players_["Dejounte Murray"].vid() }, - { players_["Shaquile O'Neal"].vid() }, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY " - "YIELD $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string>> expected = { - { "Tony Parker" }, - { "Manu Ginobili" }, - { "LaMarcus Aldridge" }, - { "Marco Belinelli" }, - { "Danny Green" }, - { "Aron Baynes" }, - { "Boris Diaw" }, - { "Tiago Splitter" }, - { "Dejounte Murray" }, - { "Shaquile O'Neal" }, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('Tim Duncan') OVER like REVERSELY " - "WHERE $$.player.age < 35 " - "YIELD $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string>> expected = { - { "LaMarcus Aldridge" }, - { "Marco Belinelli" }, - { "Danny Green" }, - { "Aron Baynes" }, - { "Tiago Splitter" }, - { "Dejounte Murray" }, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, ReverselyTwoStep) { - { - cpp2::ExecutionResponse resp; - auto query = "GO 2 STEPS FROM hash('Kobe Bryant') OVER like REVERSELY " - "YIELD $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string>> expected = { - { "Marc Gasol" }, - { "Vince Carter" }, - { "Yao Ming" }, - { "Grant Hill" }, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GoTest, ReverselyWithPipe) { - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('LeBron James') OVER serve YIELD serve._dst AS id |" - "GO FROM $-.id OVER serve REVERSELY YIELD $^.team.name, $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string, std::string>> expected = { - { "Cavaliers", "Kyrie Irving" }, - { "Cavaliers", "Dwyane Wade" }, - { "Cavaliers", "Shaquile O'Neal" }, - { "Cavaliers", "Danny Green" }, - { "Cavaliers", "LeBron James" }, - { "Heat", "Dwyane Wade" }, - { "Heat", "LeBron James" }, - { "Heat", "Ray Allen" }, - { "Heat", "Shaquile O'Neal" }, - { "Heat", "Amar'e Stoudemire" }, - { "Lakers", "Kobe Bryant" }, - { "Lakers", "LeBron James" }, - { "Lakers", "Rajon Rondo" }, - { "Lakers", "Steve Nash" }, - { "Lakers", "Paul Gasol" }, - { "Lakers", "Shaquile O'Neal" }, - { "Lakers", "JaVale McGee" }, - { "Lakers", "Dwight Howard" }, - }; - - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('LeBron James') OVER serve " - "YIELD serve._dst AS id |" - "GO FROM $-.id OVER serve REVERSELY " - "WHERE $$.player.name != 'LeBron James' " - "YIELD $^.team.name, $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string, std::string>> expected = { - { "Cavaliers", "Kyrie Irving" }, - { "Cavaliers", "Dwyane Wade" }, - { "Cavaliers", "Shaquile O'Neal" }, - { "Cavaliers", "Danny Green" }, - { "Heat", "Dwyane Wade" }, - { "Heat", "Ray Allen" }, - { "Heat", "Shaquile O'Neal" }, - { "Heat", "Amar'e Stoudemire" }, - { "Lakers", "Kobe Bryant" }, - { "Lakers", "Rajon Rondo" }, - { "Lakers", "Steve Nash" }, - { "Lakers", "Paul Gasol" }, - { "Lakers", "Shaquile O'Neal" }, - { "Lakers", "JaVale McGee" }, - { "Lakers", "Dwight Howard" }, - }; - - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('Manu Ginobili') OVER like REVERSELY " - "YIELD like._src AS id |" - "GO FROM $-.id OVER serve"; - client_->execute(query, resp); - std::vector<std::tuple<int64_t>> expected = { - { teams_["Spurs"].vid() }, - { teams_["Spurs"].vid() }, - { teams_["Hornets"].vid() }, - { teams_["Spurs"].vid() }, - { teams_["Hawks"].vid() }, - { teams_["76ers"].vid() }, - { teams_["Spurs"].vid() }, - }; - - ASSERT_TRUE(verifyResult(resp, expected)); - } - /** - * TODO(dutor) - * For the time being, reference to the pipe inputs is faulty. - * Because there might be multiple associated records with the same column value, - * which is used as the source id by the right statement. - * - * So the following case is disabled temporarily. - */ - /* - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM hash('LeBron James') OVER serve " - "YIELD serve._dst AS id, serve.start_year AS start, " - "serve.end_year AS end |" - "GO FROM $-.id OVER serve REVERSELY " - "WHERE $$.player.name != 'LeBron James' && " - "serve.start_year <= $-.end && serve.end_year >= $-.end " - "YIELD $^.team.name, $$.player.name"; - client_->execute(query, resp); - std::vector<std::tuple<std::string, std::string>> expected = { - { "Cavaliers", "Kyrie Irving" }, - { "Cavaliers", "Shaquile O'Neal" }, - { "Cavaliers", "Danny Green" }, - { "Cavaliers", "Dwyane Wade" }, - { "Heat", "Dwyane Wade" }, - { "Heat", "Ray Allen" }, - { "Lakers", "Rajon Rondo" }, - { "Lakers", "JaVale McGee" }, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - */ -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/GraphHttpHandlerTest.cpp b/src/executor/test/GraphHttpHandlerTest.cpp deleted file mode 100644 index 9346560ccfb290ded082eacfa52c11ed97821418..0000000000000000000000000000000000000000 --- a/src/executor/test/GraphHttpHandlerTest.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include <gtest/gtest.h> -#include "http/HttpClient.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include <folly/json.h> -#include "graph/GraphHttpHandler.h" -#include "webservice/WebService.h" - -namespace nebula { -namespace graph { - -using nebula::WebService; - -class GraphHttpHandlerTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - - FLAGS_ws_http_port = 0; - FLAGS_ws_h2_port = 0; - VLOG(1) << "Starting web service..."; - WebService::registerHandler("/status", [] { - return new graph::GraphHttpHandler(); - }); - - auto status = WebService::start(); - ASSERT_TRUE(status.ok()) << status; - } - - void TearDown() override { - WebService::stop(); - VLOG(1) << "Web service stopped"; - - TestBase::TearDown(); - } -}; - - -TEST_F(GraphHttpHandlerTest, GraphStatusTest) { - { - auto url = "/status"; - auto request = folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), - FLAGS_ws_http_port, url); - auto resp = http::HttpClient::get(request); - ASSERT_TRUE(resp.ok()); - ASSERT_EQ("status=running\n", resp.value()); - } - { - auto url = ""; - auto request = folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), - FLAGS_ws_http_port, url); - auto resp = http::HttpClient::get(request); - ASSERT_TRUE(resp.ok()); - ASSERT_EQ("status=running\n", resp.value()); - } - { - auto url = "/status?daemon=status"; - auto request = folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), - FLAGS_ws_http_port, url); - auto resp = http::HttpClient::get(request); - ASSERT_TRUE(resp.ok()); - ASSERT_EQ("status=running\n", resp.value()); - } - { - auto url = "/status?daemon=status&returnjson"; - auto request = folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), - FLAGS_ws_http_port, url); - auto resp = http::HttpClient::get(request); - ASSERT_TRUE(resp.ok()); - - auto json = folly::parseJson(resp.value()); - ASSERT_TRUE(json.isArray()); - ASSERT_EQ(1UL, json.size()); - ASSERT_TRUE(json[0].isObject()); - ASSERT_EQ(2UL, json[0].size()); - - auto it = json[0].find("name"); - ASSERT_NE(json[0].items().end(), it); - ASSERT_TRUE(it->second.isString()); - ASSERT_EQ("status", it->second.getString()); - - it = json[0].find("value"); - ASSERT_NE(json[0].items().end(), it); - ASSERT_TRUE(it->second.isString()); - ASSERT_EQ("running", it->second.getString()); - } - { - auto url = "/status123?daemon=status"; - auto request = folly::stringPrintf("http://%s:%d%s", FLAGS_ws_ip.c_str(), - FLAGS_ws_http_port, url); - auto resp = http::HttpClient::get(request); - ASSERT_TRUE(resp.ok()); - ASSERT_TRUE(resp.value().empty()); - } -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/test/GroupByLimitTest.cpp b/src/executor/test/GroupByLimitTest.cpp deleted file mode 100644 index 7464193a0eb34110b890ecf770079a2740208484..0000000000000000000000000000000000000000 --- a/src/executor/test/GroupByLimitTest.cpp +++ /dev/null @@ -1,574 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class GroupByLimitTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TraverseTestBase::TearDown(); - } -}; - -TEST_F(GroupByLimitTest, SyntaxError) { - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM 1 OVER server | LIMIT -1, 2"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "GO FROM 1 OVER server | LIMIT 1, -2"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Use groupby without input - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name" - "| GROUP BY 1+1 " - "YIELD COUNT(1), 1+1"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - LOG(INFO) << "ERROR " << *resp.get_error_msg(); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Use var - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve.end_year AS end_year " - "| GROUP BY $-.start_year " - "YIELD COUNT($var)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Use dst - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve.end_year AS end_year " - "| GROUP BY $-.start_year " - "YIELD COUNT($$.team.name)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Group input nonexistent - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY $-.start_year " - "YIELD COUNT($-.id)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Group alias nonexistent - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY team " - "YIELD COUNT($-.id), " - "$-.name AS teamName"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Field nonexistent - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY $-.name " - "YIELD COUNT($-.start_year)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Use SUM(*) - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY $-.name " - "YIELD SUM(*)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Use cal fun has more than two inputs - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY $-.name " - "YIELD COUNT($-.name, $-.id)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Group col has cal fun - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id" - "| GROUP BY $-.name, SUM($-.id) " - "YIELD $-.name, SUM($-.id)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Yield without group by - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "COUNT(serve._dst) AS id"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(GroupByLimitTest, LimitTest) { - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve YIELD $$.team.name AS name" - " | ORDER BY $-.name | LIMIT 5"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string>> expected = { - {"76ers"}, - {"Bulls"}, - {"Hawks"}, - {"Hornets"}, - {"Kings"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - // Test limit skip,count - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve YIELD $$.team.name AS name | " - "ORDER BY $-.name | LIMIT 2,2"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string>> expected = { - {"Hawks"}, - {"Hornets"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - - // use OFFSET - auto *fmt1 = "GO FROM %ld OVER serve YIELD $$.team.name AS name | " - "ORDER BY $-.name | LIMIT 2 OFFSET 2"; - query = folly::stringPrintf(fmt1, player.vid()); - code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - // test pipe output - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER like YIELD $$.player.name AS name, like._dst AS id " - "| ORDER BY $-.name | LIMIT 1 " - "| GO FROM $-.id OVER like YIELD $$.player.name AS name " - "| ORDER BY $-.name | LIMIT 2"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string>> expected = { - {"LeBron James"}, - {"Marco Belinelli"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - // Test count is 0 - { - cpp2::ExecutionResponse resp; - auto &player = players_["Danny Green"]; - auto *fmt = "GO FROM %ld OVER serve YIELD $$.team.name AS name | LIMIT 1 OFFSET 0"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - std::vector<std::string> expectedColNames{ - {"name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - } - // Test less limit - { - cpp2::ExecutionResponse resp; - auto &player = players_["Danny Green"]; - auto *fmt = "GO FROM %ld OVER serve YIELD $$.team.name AS name | LIMIT 5"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(3, resp.get_rows()->size()); - } - // Test empty result - { - cpp2::ExecutionResponse resp; - auto &player = players_["Danny Green"]; - auto *fmt = "GO FROM %ld OVER serve YIELD $$.team.name AS name | LIMIT 3, 2"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string>> expected = {}; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(GroupByLimitTest, GroupByTest) { - // Group one col - { - cpp2::ExecutionResponse resp; - auto &player = players_["Marco Belinelli"]; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id, " - "serve.start_year AS start_year, " - "serve.end_year AS end_year" - "| GROUP BY $-.start_year " - "YIELD COUNT($-.id), " - "$-.start_year AS start_year, " - "AVG($-.end_year) as avg"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<uint64_t, uint64_t, double >> expected = { - {2, 2018, 2018.5, }, - {1, 2017, 2018.0}, - {1, 2016, 2017.0}, - {1, 2009, 2010.0}, - {1, 2007, 2009.0}, - {1, 2012, 2013.0}, - {1, 2015, 2016.0}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Has alias col - { - cpp2::ExecutionResponse resp; - auto &player1 = players_["Aron Baynes"]; - auto &player2 = players_["Tracy McGrady"]; - auto *fmt = "GO FROM %ld,%ld OVER serve " - "YIELD $$.team.name AS name, " - "serve._dst AS id, " - "serve.start_year AS start, " - "serve.end_year AS end" - "| GROUP BY teamName, start_year " - "YIELD $-.name AS teamName, " - "$-.start AS start_year, " - "MAX($-.start), " - "MIN($-.end), " - "AVG($-.end) AS avg_end_year, " - "STD($-.end) AS std_end_year, " - "COUNT($-.id)"; - auto query = folly::stringPrintf(fmt, player1.vid(), player2.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"teamName"}, {"start_year"}, {"MAX($-.start)"}, {"MIN($-.end)"}, - {"avg_end_year"}, {"std_end_year"}, {"COUNT($-.id)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, // teamName - uint64_t, // start_year - uint64_t, // MAX($-.start_year) - uint64_t, // MIN($-.end_year) - double , // avg_end_year - double , // std_end_year - uint64_t> // COUNT($-.id) - > expected = { - {"Celtics", 2017, 2017, 2019, 2019.0, 0, 1}, - {"Magic", 2000, 2000, 2004, 2004.0, 0, 1}, - {"Pistons", 2015, 2015, 2017, 2017.0, 0, 1}, - {"Raptors", 1997, 1997, 2000, 2000.0, 0, 1}, - {"Rockets", 2004, 2004, 2010, 2010.0, 0, 1}, - {"Spurs", 2013, 2013, 2013, 2014.0, 1, 2}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Group has all cal fun - { - cpp2::ExecutionResponse resp; - auto &player1 = players_["Carmelo Anthony"]; - auto &player2 = players_["Dwyane Wade"]; - auto *fmt = "GO FROM %ld,%ld OVER like " - "YIELD $$.player.name AS name, " - "$$.player.age AS dst_age, " - "$$.player.age AS src_age, " - "like.likeness AS likeness" - "| GROUP BY $-.name " - "YIELD $-.name AS name, " - "SUM($-.dst_age) AS sum_dst_age, " - "AVG($-.dst_age) AS avg_dst_age, " - "MAX($-.src_age) AS max_src_age, " - "MIN($-.src_age) AS min_src_age, " - "BIT_AND(1) AS bit_and, " - "BIT_OR(2) AS bit_or, " - "BIT_XOR(3) AS bit_xor, " - "COUNT($-.likeness), " - "COUNT_DISTINCT($-.likeness)"; - auto query = folly::stringPrintf(fmt, player1.vid(), player2.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, - {"sum_dst_age"}, - {"avg_dst_age"}, - {"max_src_age"}, - {"min_src_age"}, - {"bit_and"}, - {"bit_or"}, - {"bit_xor"}, - {"COUNT($-.likeness)"}, - {"COUNT_DISTINCT($-.likeness)"}, - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, // name - int64_t, // sum_dst_age - double , // avg_dst_age - uint64_t, // max_src_age - uint64_t, // min_src_age - uint64_t, // bit_and - uint64_t, // bit_or - uint64_t, // bit_xor - uint64_t, // COUNT($-.likeness) - uint64_t> // COUNT_DISTINCT($-.likeness) - > expected = { - {"LeBron James", 68, 34.0, 34, 34, 1, 2, 0, 2, 1}, - {"Chris Paul", 66, 33.0, 33, 33, 1, 2, 0, 2, 1}, - {"Dwyane Wade", 37, 37.0, 37, 37, 1, 2, 3, 1, 1}, - {"Carmelo Anthony", 34, 34.0, 34, 34, 1, 2, 3, 1, 1}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Group has fun col - { - cpp2::ExecutionResponse resp; - auto &player1 = players_["Carmelo Anthony"]; - auto &player2 = players_["Dwyane Wade"]; - auto *fmt = "GO FROM %ld,%ld OVER like " - "YIELD $$.player.name AS name" - "| GROUP BY $-.name, abs(5) " - "YIELD $-.name AS name, " - "SUM(1.5) AS sum, " - "COUNT(*) AS count," - "1+1 AS cal"; - auto query = folly::stringPrintf(fmt, player1.vid(), player2.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"sum"}, {"count"}, {"cal"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, double, uint64_t, uint64_t>> expected = { - {"LeBron James", 3.0, 2, 2}, - {"Chris Paul", 3.0, 2, 2}, - {"Dwyane Wade", 1.5, 1, 2}, - {"Carmelo Anthony", 1.5, 1, 2}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Output next - { - cpp2::ExecutionResponse resp; - auto &player = players_["Paul Gasol"]; - auto *fmt = "GO FROM %ld OVER like " - "YIELD $$.player.age AS age, " - "like._dst AS id " - "| GROUP BY $-.id " - "YIELD $-.id AS id, " - "SUM($-.age) AS age " - "| GO FROM $-.id OVER serve " - "YIELD $$.team.name AS name, " - "$-.age AS sumAge"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"sumAge"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t>> expected = { - {"Grizzlies", 34}, - {"Raptors", 34}, - {"Lakers", 40}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(GroupByLimitTest, GroupByOrderByLimitTest) { - // Test with OrderBy - { - cpp2::ExecutionResponse resp; - auto &player1 = players_["Carmelo Anthony"]; - auto &player2 = players_["Dwyane Wade"]; - auto *fmt = "GO FROM %ld,%ld OVER like " - "YIELD $$.player.name AS name" - "| GROUP BY $-.name, abs(5) " - "YIELD $-.name AS name, " - "SUM(1.5) AS sum, " - "COUNT(*) AS count " - "| ORDER BY $-.sum"; - auto query = folly::stringPrintf(fmt, player1.vid(), player2.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"sum"}, {"count"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, double, uint64_t>> expected = { - {"Dwyane Wade", 1.5, 1}, - {"Carmelo Anthony", 1.5, 1}, - {"Chris Paul", 3.0, 2}, - {"LeBron James", 3.0, 2}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - // Test with Limit - { - cpp2::ExecutionResponse resp; - auto &player1 = players_["Carmelo Anthony"]; - auto &player2 = players_["Dwyane Wade"]; - auto *fmt = "GO FROM %ld,%ld OVER like " - "YIELD $$.player.name AS name" - "| GROUP BY $-.name, abs(5) " - "YIELD $-.name AS name, " - "SUM(1.5) AS sum, " - "COUNT(*) AS count " - "| ORDER BY $-.sum | LIMIT 2"; - auto query = folly::stringPrintf(fmt, player1.vid(), player2.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"sum"}, {"count"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, double, uint64_t>> expected = { - {"Dwyane Wade", 1.5, 1}, - {"Carmelo Anthony", 1.5, 1}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } -} - -TEST_F(GroupByLimitTest, EmptyInput) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as name" - "| GROUP BY $-.name YIELD $-.name AS name"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER like " - "YIELD $$.player.name AS name" - "| GROUP BY $-.name, abs(5) " - "YIELD $-.name AS name, " - "SUM(1.5) AS sum, " - "COUNT(*) AS count " - "| ORDER BY $-.sum | LIMIT 2"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"sum"}, {"count"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } -} - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/test/OrderByTest.cpp b/src/executor/test/OrderByTest.cpp deleted file mode 100644 index 6714eb116397c76fb0722b601645212ebbdfa1ec..0000000000000000000000000000000000000000 --- a/src/executor/test/OrderByTest.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - -namespace nebula { -namespace graph { - -class OrderByTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TraverseTestBase::TearDown(); - } -}; - -TEST_F(OrderByTest, SyntaxError) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "ORDER BY "; - auto query = fmt; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto *fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name" - "| ORDER BY $-.$$.team.name"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(OrderByTest, EmptyInput) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "ORDER BY $-.xx"; - auto query = fmt; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(nullptr, resp.get_rows()); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team" - "| ORDER BY $-.name"; - auto query = folly::stringPrintf(fmt, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"start"}, {"team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } -} - -TEST_F(OrderByTest, WrongFactor) { - std::string go = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team"; - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| ORDER BY $-.abc"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} - -TEST_F(OrderByTest, SingleFactor) { - std::string go = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team"; - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| ORDER BY $-.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"start"}, {"team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {player.name(), 2003, "Hawks"}, - {player.name(), 2008, "Hornets"}, - {player.name(), 2016, "Jazz"}, - {player.name(), 2012, "Spurs"}, - {player.name(), 2005, "Suns"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| ORDER BY $-.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"start"}, {"team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {player.name(), 2008, "Hornets"}, - {player.name(), 2003, "Hawks"}, - {player.name(), 2016, "Jazz"}, - {player.name(), 2012, "Spurs"}, - {player.name(), 2005, "Suns"}, - }; - ASSERT_FALSE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| ORDER BY $-.team ASC"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"start"}, {"team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {player.name(), 2003, "Hawks"}, - {player.name(), 2008, "Hornets"}, - {player.name(), 2016, "Jazz"}, - {player.name(), 2012, "Spurs"}, - {player.name(), 2005, "Suns"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| ORDER BY $-.team DESC"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"start"}, {"team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {player.name(), 2005, "Suns"}, - {player.name(), 2012, "Spurs"}, - {player.name(), 2016, "Jazz"}, - {player.name(), 2008, "Hornets"}, - {player.name(), 2003, "Hawks"}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } -} - -TEST_F(OrderByTest, MultiFactors) { - std::string go = "GO FROM %ld,%ld OVER serve WHERE serve.start_year >= 2012 YIELD " - "$$.team.name as team, $^.player.name as player, " - "$^.player.age as age, serve.start_year as start"; - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - auto fmt = go + "| ORDER BY $-.team, $-.age"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"team"}, {"player"}, {"age"}, {"start"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Jazz", boris.name(), 36, 2016}, - {"Spurs", aldridge.name(), 33, 2015}, - {"Spurs", boris.name(), 36, 2012}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - auto fmt = go + "| ORDER BY $-.team ASC, $-.age ASC"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Jazz", boris.name(), 36, 2016}, - {"Spurs", aldridge.name(), 33, 2015}, - {"Spurs", boris.name(), 36, 2012}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - auto fmt = go + "| ORDER BY $-.team ASC, $-.age DESC"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"team"}, {"player"}, {"age"}, {"start"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Jazz", boris.name(), 36, 2016}, - {"Spurs", boris.name(), 36, 2012}, - {"Spurs", aldridge.name(), 33, 2015}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - auto fmt = go + "| ORDER BY $-.team DESC, $-.age ASC"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"team"}, {"player"}, {"age"}, {"start"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Spurs", aldridge.name(), 33, 2015}, - {"Spurs", boris.name(), 36, 2012}, - {"Jazz", boris.name(), 36, 2016}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - auto fmt = go + "| ORDER BY $-.team DESC, $-.age DESC"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"team"}, {"player"}, {"age"}, {"start"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Spurs", boris.name(), 36, 2012}, - {"Spurs", aldridge.name(), 33, 2015}, - {"Jazz", boris.name(), 36, 2016}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto &aldridge = players_["LaMarcus Aldridge"]; - // test syntax sugar - auto fmt = go + "| ORDER BY team DESC, age DESC"; - auto query = folly::stringPrintf(fmt.c_str(), boris.vid(), aldridge.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"team"}, {"player"}, {"age"}, {"start"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string, int64_t, int64_t>> expected = { - {"Spurs", boris.name(), 36, 2012}, - {"Spurs", aldridge.name(), 33, 2015}, - {"Jazz", boris.name(), 36, 2016}, - }; - ASSERT_TRUE(verifyResult(resp, expected, false)); - } -} - -TEST_F(OrderByTest, InterimResult) { - { - cpp2::ExecutionResponse resp; - auto &boris = players_["Boris Diaw"]; - auto *fmt = - "GO FROM %ld OVER like YIELD like._dst as id | ORDER BY $-.id | GO FROM $-.id over " - "serve"; - auto query = folly::stringPrintf(fmt, boris.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve._dst"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected = { - teams_["Spurs"].vid(), - teams_["Spurs"].vid(), - teams_["Hornets"].vid(), - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/SchemaTest.cpp b/src/executor/test/SchemaTest.cpp deleted file mode 100644 index 28cfab89a67cd7ffe081301561eea42c9a86315e..0000000000000000000000000000000000000000 --- a/src/executor/test/SchemaTest.cpp +++ /dev/null @@ -1,1276 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" -#include "storage/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class SchemaTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } -}; - -TEST_F(SchemaTest, TestComment) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - // Test command is comment - { - cpp2::ExecutionResponse resp; - std::string cmd = "# CREATE TAG TAG1"; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::E_STATEMENT_EMTPY, code); - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "SHOW SPACES # show all spaces"; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } -} - -TEST_F(SchemaTest, metaCommunication) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW HOSTS"; - client->execute(query, resp); - std::vector<std::tuple<std::string, std::string, std::string, - int, std::string, std::string>> expected { - {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0, - "No valid partition", "No valid partition"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Test space not exist - { - cpp2::ExecutionResponse resp; - std::string query = "USE not_exist_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test create space succeeded - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE SPACE default_space(partition_num=9, replica_factor=1)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE SPACE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int, std::string, int, int>> expected{ - {1, "default_space", 9, 1}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test desc space command - { - cpp2::ExecutionResponse resp; - std::string query = "DESC SPACE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int, std::string, int, int>> expected{ - {1, "default_space", 9, 1}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE SPACE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createSpaceStr = "CREATE SPACE default_space (" - "partition_num = 9, " - "replica_factor = 1)"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"default_space", createSpaceStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE SPACE space_with_default_options"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE SPACE space_with_default_options"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int, std::string, int, int>> expected{ - {2, "space_with_default_options", 100, 1}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DROP SPACE space_with_default_options"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "USE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - std::string query = "CREATE SPACE IF NOT EXISTS default_space"; - cpp2::ExecutionResponse resp; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // show parts of default_space - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW PARTS; # before leader election"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(9, (*(resp.get_rows())).size()); - std::string host = "127.0.0.1:" + std::to_string(gEnv->storageServerPort()); - std::vector<std::tuple<int, std::string, std::string, std::string>> expected; - for (int32_t partId = 1; partId <= 9; partId++) { - expected.emplace_back(std::make_tuple(partId, "", host, "")); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test same prop name - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG samePropTag(name string, name int)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test same prop name - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE samePropEdge(name string, name int)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test create tag without prop - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG tag1()"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG IF NOT EXISTS tag1()"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG tag1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 1>> expected{}; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG tag1 ADD (id int, name string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG tag1"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"id", "int"}, - {"name", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test create tag succeeded - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person(name string, email string, " - "age int, gender string, row_timestamp timestamp)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Create Tag with default value - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person_with_default(name string, age int default 18)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person_type_mismatch" - "(name string, age int default \"hello\")"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"email", "string"}, - {"age", "int"}, - {"gender", "string"}, - {"row_timestamp", "timestamp"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test desc tag command - { - cpp2::ExecutionResponse resp; - std::string query = "DESC TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"email", "string"}, - {"age", "int"}, - {"gender", "string"}, - {"row_timestamp", "timestamp"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG person (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"person", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - // Test tag not exist - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG not_exist"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test unreserved keyword - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG upper(name string, EMAIL string, " - "age int, gender string, row_timestamp timestamp)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG upper"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"email", "string"}, - {"age", "int"}, - {"gender", "string"}, - {"row_timestamp", "timestamp"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test existent tag - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person(id int)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test nonexistent tag - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG not_exist"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test alter tag - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG person " - "ADD (col1 int, col2 string), " - "CHANGE (age string), " - "DROP (gender)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG person DROP (gender)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG person"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"email", "string"}, - {"age", "string"}, - {"row_timestamp", "timestamp"}, - {"col1", "int"}, - {"col2", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG person (\n" - " name string,\n" - " email string,\n" - " age string,\n" - " row_timestamp timestamp,\n" - " col1 int,\n" - " col2 string\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"person", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW TAGS"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int32_t, std::string>> expected{ - {3, "tag1"}, - {4, "person"}, - {5, "person_with_default"}, - {6, "upper"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test create edge without prop - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE edge1()"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE IF NOT EXISTS edge1()"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE edge1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE edge1 ADD (id int, name string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE edge1"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"id", "int"}, - {"name", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test create edge succeeded - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE buy(id int, time string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE buy_with_default(id int, time string default \"\")"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE buy_type_mismatch(id int, time string default 0)"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - // Test existent edge - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE buy(id int, time string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE buy"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"id", "int"}, - {"time", "string"}, - }; - EXPECT_TRUE(verifyResult(resp, expected)); - } - // Test nonexistent edge - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE not_exist"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test desc edge - { - cpp2::ExecutionResponse resp; - std::string query = "DESC EDGE buy"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"id", "int"}, - {"time", "string"}, - }; - EXPECT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE buy"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE buy (\n" - " id int,\n" - " time string\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"buy", createEdgeStr}, - }; - EXPECT_TRUE(verifyResult(resp, expected)); - } - { - // Test edge not exist - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE not_exist"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - // Test create edge succeeded - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE education(id int, time timestamp, school string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE education"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"id", "int"}, - {"time", "timestamp"}, - {"school", "string"}, - }; - EXPECT_TRUE(verifyResult(resp, expected)); - } - // Test show edges - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW EDGES"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int32_t, std::string>> expected{ - {7, "edge1"}, - {8, "buy"}, - {9, "buy_with_default"}, - {10, "education"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test alter edge - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE education " - "ADD (col1 int, col2 string), " - "CHANGE (school int), " - "DROP (id, time)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE education DROP (id, time)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE education"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"school", "int"}, - {"col1", "int"}, - {"col2", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test multi sentences - { - cpp2::ExecutionResponse resp; - std::string query; - for (auto i = 0u; i < 1000; i++) { - query += "CREATE TAG tag10" + std::to_string(i) + "(name string);"; - } - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query; - for (auto i = 0u; i < 1000; i++) { - query = "DESCRIBE TAG tag10" + std::to_string(i); - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - } - // Test drop tag - { - cpp2::ExecutionResponse resp; - std::string query = "DROP TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Test drop edge - { - cpp2::ExecutionResponse resp; - std::string query = "DROP EDGE buy"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE education"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE education (\n" - " school int,\n" - " col1 int,\n" - " col2 string\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"education", createEdgeStr}, - }; - EXPECT_TRUE(verifyResult(resp, expected)); - } - // show parts of default_space - { - auto kvstore = gEnv->storageServer()->kvStore_.get(); - GraphSpaceID spaceId = 1; // default_space id is 1 - nebula::storage::TestUtils::waitUntilAllElected(kvstore, spaceId, 9); - - cpp2::ExecutionResponse resp; - std::string query = "SHOW PARTS; # after leader election"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_EQ(9, (*(resp.get_rows())).size()); - std::string host = "127.0.0.1:" + std::to_string(gEnv->storageServerPort()); - std::vector<std::tuple<int, std::string, std::string, std::string>> expected; - for (int32_t partId = 1; partId <= 9; partId++) { - expected.emplace_back(std::make_tuple(partId, host, host, "")); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test different tag and edge in different space - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE SPACE my_space(partition_num=9, replica_factor=1)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "USE my_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG animal(name string, kind string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG animal"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"kind", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test the same tag in diff space - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person(name string, interest string)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW TAGS"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int32_t, std::string>> expected{ - {1012, "animal"}, - {1013, "person"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Test multi sentence - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE SPACE test_multi"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - query = "USE test_multi; CREATE Tag test_tag(); SHOW TAGS;"; - code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int32_t, std::string>> expected1{ - {1015, "test_tag"}, - }; - ASSERT_TRUE(verifyResult(resp, expected1)); - - query = "USE test_multi; CREATE TAG test_tag1(); USE my_space; SHOW TAGS;"; - code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int32_t, std::string>> expected2{ - {1012, "animal"}, - {1013, "person"}, - }; - ASSERT_TRUE(verifyResult(resp, expected2)); - - query = "DROP SPACE test_multi"; - code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - // Test drop space - { - cpp2::ExecutionResponse resp; - std::string query = "DROP SPACE my_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW SPACES"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 1>> expected{ - {"default_space"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DROP SPACE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW SPACES"; - client->execute(query, resp); - ASSERT_EQ(0, (*(resp.get_rows())).size()); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW HOSTS"; - client->execute(query, resp); - ASSERT_EQ(1, (*(resp.get_rows())).size()); - } - - sleep(FLAGS_load_data_interval_secs + 1); - int retry = 60; - while (retry-- > 0) { - auto spaceResult = gEnv->metaClient()->getSpaceIdByNameFromCache("default_space"); - if (!spaceResult.ok()) { - return; - } - sleep(1); - } - LOG(FATAL) << "Space still exists after sleep " << retry << " seconds"; -} - - -TEST_F(SchemaTest, TTLtest) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW HOSTS"; - client->execute(query, resp); - std::vector<std::tuple<std::string, std::string, std::string, - int, std::string, std::string>> expected { - {"127.0.0.1", std::to_string(gEnv->storageServerPort()), "online", 0, - "No valid partition", "No valid partition"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE SPACE default_space(partition_num=9, replica_factor=1)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "USE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - - // Tag with TTL test - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG person(name string, email string, " - "age int, gender string, row_timestamp timestamp)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"name", "string"}, - {"email", "string"}, - {"age", "int"}, - {"gender", "string"}, - {"row_timestamp", "timestamp"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG person"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG person (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"person", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG man(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_duration = 100, ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG man"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG man (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 100, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"man", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Abnormal test - { - // Disable implicit ttl mode - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG woman(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_duration = 100"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - // Disable when ttl_col is not an integer column or a timestamp column - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG woman(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_col = name"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG woman(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_duration = -100, ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG woman"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG woman (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 0, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"woman", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE TAG only_ttl_col(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG only_ttl_col"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG only_ttl_col (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 0, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"only_ttl_col", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "ttl_duration = 50, ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG woman"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG woman (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 50, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"woman", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - // Failed when alter tag to set ttl_col on not integer and timestamp column - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "ttl_col = name"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "Drop (name) ttl_duration = 200"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG woman"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG woman (\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 200, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"woman", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - // When the column is as TTL column, droping column failed - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "Drop (row_timestamp)"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - // First remove TTL property, then drop column - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "ttl_col = age"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG woman"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::string createTagStr = "CREATE TAG woman (\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 200, ttl_col = age"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"woman", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER TAG woman " - "Drop (row_timestamp)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE TAG woman"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createTagStr = "CREATE TAG woman (\n" - " email string,\n" - " age int,\n" - " gender string\n" - ") ttl_duration = 200, ttl_col = age"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"woman", createTagStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Edge with TTL test - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE work(number string, start_time timestamp)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE work"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"number", "string"}, - {"start_time", "timestamp"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work (\n" - " number string,\n" - " start_time timestamp\n" - ") ttl_duration = 0, ttl_col = \"\""; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE work1(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_duration = 100, ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work1 (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 100, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work1", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - // Abnormal test - { - // Disable implicit ttl mode - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE work2(number string, start_time timestamp)" - "ttl_duration = 100"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - // Disable when ttl_col is not an integer column or a timestamp column - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE work2(number string, start_time timestamp)" - "ttl_col = name"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE work2(name string, email string, " - "age int, gender string, start_time timestamp)" - "ttl_duration = -100, ttl_col = start_time"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work2 (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " start_time timestamp\n" - ") ttl_duration = 0, ttl_col = start_time"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work2", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "CREATE EDGE edge_only_ttl_col(name string, email string, " - "age int, gender string, row_timestamp timestamp)" - "ttl_col = row_timestamp"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE edge_only_ttl_col"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE edge_only_ttl_col (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " row_timestamp timestamp\n" - ") ttl_duration = 0, ttl_col = row_timestamp"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"edge_only_ttl_col", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "ttl_duration = 50, ttl_col = start_time"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - - std::string query = "SHOW CREATE EDGE work2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work2 (\n" - " name string,\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " start_time timestamp\n" - ") ttl_duration = 50, ttl_col = start_time"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work2", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - // Failed when alter edge to set ttl_col on not integer and timestamp column - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "ttl_col = name"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "Drop (name) ttl_duration = 200"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work2 (\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " start_time timestamp\n" - ") ttl_duration = 200, ttl_col = start_time"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work2", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - // When the column is as TTL column, droping column failed - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "Drop (start_time)"; - auto code = client->execute(query, resp); - ASSERT_NE(cpp2::ErrorCode::SUCCEEDED, code); - } - { - // First remove TTL property, then drop column - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "ttl_col = age"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work2 (\n" - " email string,\n" - " age int,\n" - " gender string,\n" - " start_time timestamp\n" - ") ttl_duration = 200, ttl_col = age"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work2", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "ALTER EDGE work2 " - "Drop (start_time)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "DESCRIBE EDGE work2"; - client->execute(query, resp); - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"email", "string"}, - {"age", "int"}, - {"gender", "string"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "SHOW CREATE EDGE work2"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::string createEdgeStr = "CREATE EDGE work2 (\n" - " email string,\n" - " age int,\n" - " gender string\n" - ") ttl_duration = 200, ttl_col = age"; - std::vector<uniform_tuple_t<std::string, 2>> expected{ - {"work2", createEdgeStr}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - - { - cpp2::ExecutionResponse resp; - std::string query = "DROP SPACE default_space"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/SetTest.cpp b/src/executor/test/SetTest.cpp deleted file mode 100644 index 16ad1a48a32b03fb52608598aee184d292508f65..0000000000000000000000000000000000000000 --- a/src/executor/test/SetTest.cpp +++ /dev/null @@ -1,576 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" -#include "meta/test/TestUtils.h" - -namespace nebula { -namespace graph { - -class SetTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TraverseTestBase::TearDown(); - } -}; - -TEST_F(SetTest, UnionAllTest) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : tim.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tim.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), manu.vid()); - auto code = client_->execute(query, resp); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : tim.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tim.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - for (auto &serve : manu.serves()) { - std::tuple<std::string, int64_t, std::string> record( - manu.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id| " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tony.vid(), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION ALL " - "GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tony.vid(), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id UNION ALL GO FROM %ld OVER like YIELD " - "like._dst as id)" - " | GO FROM $-.id OVER serve" - " YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tony.vid(), tim.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - for (auto &like : tony.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - } - { - cpp2::ExecutionResponse resp; - // Although the corresponding column name and type not match, - // we still do the union via implicit type casting for the query . - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name as name, $$.team.name as player" - " UNION ALL " - "GO FROM %ld OVER serve " - "YIELD $^.player.name as name, serve.start_year"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"name"}, {"player"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, std::string>> expected; - for (auto &serve : tim.serves()) { - std::tuple<std::string, std::string> record( - tim.name(), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - for (auto &serve : tony.serves()) { - std::tuple<std::string, std::string> record( - tony.name(), - folly::to<std::string>(std::get<1>(serve))); - expected.emplace_back(std::move(record)); - } - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve " - "YIELD $^.player.name as player, serve.start_year as start" - " UNION ALL " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year"; - auto &nobody = players_["Nobody"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, nobody.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t>> expected; - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t> record( - tony.name(), std::get<1>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - - std::vector<std::string> colsExpect = {"player", "start"}; - auto *cols = resp.get_column_names(); - ASSERT_EQ(cols->size(), colsExpect.size()); - for (decltype(colsExpect.size()) i = 0; i < colsExpect.size(); ++i) { - ASSERT_EQ((*cols)[i], colsExpect[i]); - } - } -} - -TEST_F(SetTest, UnionDistinct) { - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), manu.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " UNION DISTINCT " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(SetTest, Minus) { - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " MINUS " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &like : tim.likes()) { - auto &player = players_[std::get<0>(like)]; - if (player.name() == tony.name()) { - continue; - } - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> record( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(SetTest, Intersect) { - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " INTERSECT " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : tony.serves()) { - std::tuple<std::string, int64_t, std::string> record( - tony.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(SetTest, Mix) { - { - cpp2::ExecutionResponse resp; - auto *fmt = - "(GO FROM %ld OVER like YIELD like._dst as id | " - "GO FROM $-.id OVER serve YIELD $^.player.name, serve.start_year, $$.team.name)" - " MINUS " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " INTERSECT " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto &manu = players_["Manu Ginobili"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid(), tim.vid(), manu.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"$^.player.name"}, {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : manu.serves()) { - std::tuple<std::string, int64_t, std::string> record( - manu.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(record)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(SetTest, EmptyInput) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD serve.start_year, $$.team.name" - " UNION " - "GO FROM %ld OVER serve YIELD serve.start_year, $$.team.name" - " MINUS " - "GO FROM %ld OVER serve YIELD serve.start_year, $$.team.name" - " INTERSECT " - "GO FROM %ld OVER serve YIELD serve.start_year, $$.team.name"; - auto query = folly::stringPrintf( - fmt, nonExistPlayerID, nonExistPlayerID, nonExistPlayerID, nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"serve.start_year"}, {"$$.team.name"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - ASSERT_EQ(nullptr, resp.get_rows()); - } -} - -TEST_F(SetTest, SyntaxError) { - { - cpp2::ExecutionResponse resp; - // This is an act of reservation. - // For now, we treat it as an syntax error. - auto query = "GO FROM 123 OVER like" - " YIELD like._src as src, like._dst as dst" - " | (GO FROM $-.src OVER serve" - " UNION GO FROM $-.dst OVER serve)"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(SetTest, ExecutionError) { - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name1, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto *fmt = "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year" - " UNION " - "GO FROM %ld OVER serve YIELD $^.player.name, serve.start_year, $$.team.name"; - auto &tim = players_["Tim Duncan"]; - auto &tony = players_["Tony Parker"]; - auto query = folly::stringPrintf(fmt, tim.vid(), tony.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } -} -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/SnapshotCommandTest.cpp b/src/executor/test/SnapshotCommandTest.cpp deleted file mode 100644 index 7929150152de1322747c776fd367e860f6849cce..0000000000000000000000000000000000000000 --- a/src/executor/test/SnapshotCommandTest.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class SnapshotCommandTest : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } -}; - -TEST_F(SnapshotCommandTest, TestSnapshot) { - auto client = gEnv->getClient(); - - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE mySpace(partition_num=1, replica_factor=1)"; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - sleep(FLAGS_load_data_interval_secs + 1); - - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SNAPSHOT"; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - std::string sname; - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string cmd = "SHOW SNAPSHOTS"; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - const auto& snapshots = resp.get_rows(); - ASSERT_EQ(1, snapshots->size()); - sname.append(snapshots[0].data()->get_columns().data()->get_str()); - } - - { - std::vector<std::string> checkpoints; - checkpoints.emplace_back(folly::stringPrintf("%s/disk1/nebula/1/checkpoints/%s/data", - gEnv->getStorageRootPath().data(), - sname.data())); - checkpoints.emplace_back(folly::stringPrintf("%s/disk2/nebula/1/checkpoints/%s/data", - gEnv->getStorageRootPath().data(), - sname.data())); - checkpoints.emplace_back(folly::stringPrintf("%s/disk1/nebula/0/checkpoints/%s/data", - gEnv->getMetaRootPath().data(), - sname.data())); - for (auto& cp : checkpoints) { - ASSERT_TRUE(fs::FileUtils::exist(cp)); - auto files = fs::FileUtils::listAllFilesInDir(cp.data()); - ASSERT_LE(3, files.size()); - } - } - - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SNAPSHOT " + sname; - auto code = client->execute(cmd, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - - { - std::vector<std::string> checkpoints; - checkpoints.emplace_back(folly::stringPrintf("%s/disk1/nebula/1/checkpoints/%s", - gEnv->getStorageRootPath().data(), - sname.data())); - checkpoints.emplace_back(folly::stringPrintf("%s/disk2/nebula/1/checkpoints/%s", - gEnv->getStorageRootPath().data(), - sname.data())); - checkpoints.emplace_back(folly::stringPrintf("%s/disk1/nebula/0/checkpoints/%s", - gEnv->getMetaRootPath().data(), - sname.data())); - for (auto& cp : checkpoints) { - ASSERT_FALSE(fs::FileUtils::exist(cp)); - } - } -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/TestBase.cpp b/src/executor/test/TestBase.cpp deleted file mode 100644 index 070bc07efc30ab2403a380cda08eb509b7dadc31..0000000000000000000000000000000000000000 --- a/src/executor/test/TestBase.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestBase.h" - -namespace nebula { -namespace graph { - -void TestBase::SetUp() { -} - - -void TestBase::TearDown() { -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/TestBase.h b/src/executor/test/TestBase.h deleted file mode 100644 index 171a0efd91175b51d816aca492c4602a53f9987d..0000000000000000000000000000000000000000 --- a/src/executor/test/TestBase.h +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_TEST_TESTBASE_H_ -#define GRAPH_TEST_TESTBASE_H_ - -#include "base/Base.h" -#include <gtest/gtest.h> -#include "gen-cpp2/GraphService.h" - -/** - * According to the ADL(Argument-dependent Lookup) rules, - * we have to define operator<< for `std::tuple<...>' in the global scope or `std' - */ -namespace std { - -template <typename Tuple, size_t...Is> -void printTupleImpl(std::ostream &os, const Tuple &tuple, std::index_sequence<Is...>) { - auto flags = os.flags(); - os << std::boolalpha; - - using DumyType = int[]; - (void)DumyType{(void(os << (Is == 0 ? "" : ", ") << std::get<Is>(tuple)), 0)...}; - - os.flags(flags); -} - - -template <typename Tuple> -void printTuple(std::ostream &os, const Tuple &tuple) { - printTupleImpl(os, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>()); -} - - -template <typename...Args> -std::ostream& operator<<(std::ostream &os, const std::tuple<Args...> &tuple) { - os << "["; - printTuple(os, tuple); - os << "]"; - return os; -} - -} // namespace std - - -namespace nebula { -namespace graph { - -using AssertionResult = ::testing::AssertionResult; -class TestBase : public ::testing::Test { -protected: - void SetUp() override; - - void TearDown() override; - - using ColumnType = cpp2::ColumnValue::Type; - using Row = std::vector<cpp2::ColumnValue>; - using Rows = std::vector<Row>; - - static AssertionResult TestOK() { - return ::testing::AssertionSuccess(); - } - - static AssertionResult TestError() { - return ::testing::AssertionFailure(); - } - - template <typename, typename> - struct uniform_tuple_impl; - template <typename T, size_t...Is> - struct uniform_tuple_impl<T, std::index_sequence<Is...>> { - template <size_t> - using IndexedType = T; - using type = std::tuple<IndexedType<Is>...>; - }; - - template <typename T, size_t N> - struct uniform_tuple { - using type = typename uniform_tuple_impl<T, std::make_index_sequence<N>>::type; - }; - - template <typename T, size_t N> - using uniform_tuple_t = typename uniform_tuple<T, N>::type; - - Rows respToRecords(const cpp2::ExecutionResponse &resp) { - CHECK(resp.get_rows() != nullptr); - Rows result; - for (auto &row : *resp.get_rows()) { - auto &columns = row.get_columns(); - result.emplace_back(); - result.back().assign(columns.begin(), columns.end()); - } - return result; - } - - /** - * Convert `ColumnValue' to its cooresponding type - */ - template <typename T> - std::enable_if_t<std::is_integral<T>::value, T> - convert(const cpp2::ColumnValue &v) { - switch (v.getType()) { - case ColumnType::integer: - return v.get_integer(); - case ColumnType::timestamp: - return v.get_timestamp(); - case ColumnType::id: - return v.get_id(); - case ColumnType::bool_val: - return v.get_bool_val(); - default: - throw TestError() << "Cannot convert unknown dynamic column type to integer: " - << static_cast<int32_t>(v.getType()); - } - return T(); // suppress the no-return waring - } - - template <typename T> - std::enable_if_t<std::is_same<T, std::string>::value, T> - convert(const cpp2::ColumnValue &v) { - switch (v.getType()) { - case ColumnType::str: - return v.get_str(); - default: - throw TestError() << "Cannot convert unknown dynamic column type to string: " - << static_cast<int32_t>(v.getType()); - } - return T(); // suppress the no-return warning - } - - template <typename T> - std::enable_if_t<std::is_floating_point<T>::value, T> - convert(const cpp2::ColumnValue &v) { - switch (v.getType()) { - case ColumnType::single_precision: - return v.get_single_precision(); - case ColumnType::double_precision: - return v.get_double_precision(); - default: - throw TestError() << "Cannot convert unknown dynamic column type to " - << "floating point type: " - << static_cast<int32_t>(v.getType()); - } - return T(); // suppress the no-return warning - } - - /** - * Transform rows of dynamic type to tuples of static type - */ - template <typename Tuple, size_t...Is> - auto rowToTupleImpl(const Row &row, std::index_sequence<Is...>) { - return std::make_tuple(convert<std::tuple_element_t<Is, Tuple>>(row[Is])...); - } - - template <typename Tuple> - auto rowToTuple(const Row &row) { - constexpr auto tupleSize = std::tuple_size<Tuple>::value; - return rowToTupleImpl<Tuple>(row, std::make_index_sequence<tupleSize>()); - } - - template <typename Tuple> - auto rowsToTuples(const Rows &rows) { - std::vector<Tuple> result; - if (rows.empty()) { - return result; - } - if (rows.back().size() != std::tuple_size<Tuple>::value) { - throw TestError() << "Column count not match: " - << rows.back().size() << " vs. " - << std::tuple_size<Tuple>::value; - } - for (auto &row : rows) { - result.emplace_back(rowToTuple<Tuple>(row)); - } - return result; - } - - template <typename Tuple> - AssertionResult verifyResult(const cpp2::ExecutionResponse &resp, - std::vector<Tuple> &expected, bool sortEnable = true) { - if (resp.get_error_code() != cpp2::ErrorCode::SUCCEEDED) { - auto *errmsg = resp.get_error_msg(); - return TestError() << "Query failed with `" - << static_cast<int32_t>(resp.get_error_code()) - << (errmsg == nullptr ? "'" : "': " + *errmsg); - } - - if (resp.get_rows() == nullptr && expected.empty()) { - return TestOK(); - } - - std::vector<Tuple> rows; - try { - rows = rowsToTuples<Tuple>(respToRecords(resp)); - } catch (const AssertionResult &e) { - return e; - } catch (const std::exception &e) { - return TestError() << "Unknown exception thrown: " << e.what(); - } - - if (expected.size() != rows.size()) { - return TestError() << "Rows' count not match: " - << rows.size() << " vs. " << expected.size(); - } - - if (expected.empty()) { - return TestOK(); - } - - if (sortEnable) { - std::sort(rows.begin(), rows.end()); - std::sort(expected.begin(), expected.end()); - } - for (decltype(rows.size()) i = 0; i < rows.size(); ++i) { - if (rows[i] != expected[i]) { - return TestError() << rows[i] << " vs. " << expected[i]; - } - } - return TestOK(); - } - - AssertionResult verifyColNames(const cpp2::ExecutionResponse &resp, - std::vector<std::string> &expectedColNames) { - if (resp.get_error_code() != cpp2::ErrorCode::SUCCEEDED) { - auto *errmsg = resp.get_error_msg(); - return TestError() << "Query failed with `" - << static_cast<int32_t>(resp.get_error_code()) - << (errmsg == nullptr ? "'" : "': " + *errmsg); - } - - if (resp.get_column_names() == nullptr && expectedColNames.empty()) { - return TestOK(); - } - - if (resp.get_column_names() != nullptr) { - auto colNames = *(resp.get_column_names()); - if (colNames.size() != expectedColNames.size()) { - return TestError() << "Column size not match: " - << colNames.size() << " vs. " << expectedColNames.size(); - } - for (decltype(colNames.size()) i = 0; i < colNames.size(); ++i) { - if (colNames[i] != expectedColNames[i]) { - return TestError() << colNames[i] << " vs. " << expectedColNames[i] - << ", index: " << i; - } - } - } else { - return TestError() << "Response has no column names."; - } - - return TestOK(); - } - - -protected: -}; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_TEST_TESTBASE_H_ diff --git a/src/executor/test/TestEnv.cpp b/src/executor/test/TestEnv.cpp deleted file mode 100644 index 39fde9caa608b5710d94d77d5a628f59ab0b42ee..0000000000000000000000000000000000000000 --- a/src/executor/test/TestEnv.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "meta/test/TestUtils.h" -#include "storage/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); -DECLARE_string(meta_server_addrs); - -namespace nebula { -namespace graph { - - -TestEnv *gEnv = nullptr; - -TestEnv::TestEnv() { -} - - -TestEnv::~TestEnv() { -} - - -void TestEnv::SetUp() { - FLAGS_load_data_interval_secs = 1; - const nebula::ClusterID kClusterId = 10; - // Create metaServer - metaServer_ = nebula::meta::TestUtils::mockMetaServer( - network::NetworkUtils::getAvailablePort(), - metaRootPath_.path(), - kClusterId); - FLAGS_meta_server_addrs = folly::stringPrintf("127.0.0.1:%d", metaServerPort()); - - // Create storageServer - auto threadPool = std::make_shared<folly::IOThreadPoolExecutor>(1); - auto addrsRet - = network::NetworkUtils::toHosts(folly::stringPrintf("127.0.0.1:%d", metaServerPort())); - CHECK(addrsRet.ok()) << addrsRet.status(); - auto storagePort = network::NetworkUtils::getAvailablePort(); - auto hostRet = nebula::network::NetworkUtils::toHostAddr("127.0.0.1", storagePort); - if (!hostRet.ok()) { - LOG(ERROR) << "Bad local host addr, status:" << hostRet.status(); - } - auto& localhost = hostRet.value(); - - mClient_ = std::make_unique<meta::MetaClient>(threadPool, - std::move(addrsRet.value()), - localhost, - kClusterId, - true); - mClient_->waitForMetadReady(); - gflagsManager_ = std::make_unique<meta::ClientBasedGflagsManager>(mClient_.get()); - - IPv4 localIp; - nebula::network::NetworkUtils::ipv4ToInt("127.0.0.1", localIp); - storageServer_ = nebula::storage::TestUtils::mockStorageServer( - mClient_.get(), - storageRootPath_.path(), - localIp, - storagePort, - true); - - // Create graphServer - graphServer_ = TestUtils::mockGraphServer(0); -} - - -void TestEnv::TearDown() { - // TO make sure the drop space be invoked on storage server - sleep(FLAGS_load_data_interval_secs + 1); - mClient_.reset(); - graphServer_.reset(); - storageServer_.reset(); - metaServer_.reset(); -} - -uint16_t TestEnv::graphServerPort() const { - return graphServer_->port_; -} - -uint16_t TestEnv::metaServerPort() const { - return metaServer_->port_; -} - -uint16_t TestEnv::storageServerPort() const { - return storageServer_->port_; -} - -std::unique_ptr<GraphClient> TestEnv::getClient() const { - auto client = std::make_unique<GraphClient>("127.0.0.1", graphServerPort()); - if (cpp2::ErrorCode::SUCCEEDED != client->connect("user", "password")) { - return nullptr; - } - return client; -} - -meta::ClientBasedGflagsManager* TestEnv::gflagsManager() { - return gflagsManager_.get(); -} - -test::ServerContext* TestEnv::storageServer() { - return storageServer_.get(); -} - -meta::MetaClient* TestEnv::metaClient() { - return mClient_.get(); -} - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/TestEnv.h b/src/executor/test/TestEnv.h deleted file mode 100644 index c28ec6216c2bfa0eb56277b7d859fed866fc17ec..0000000000000000000000000000000000000000 --- a/src/executor/test/TestEnv.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_TEST_TESTENV_H_ -#define GRAPH_TEST_TESTENV_H_ - -#include "base/Base.h" -#include "fs/TempDir.h" -#include "client/cpp/GraphClient.h" -#include "test/ServerContext.h" -#include <gtest/gtest.h> -#include "TestUtils.h" - -namespace nebula { -namespace graph { - -class GraphClient; -class TestEnv : public ::testing::Environment { -public: - TestEnv(); - virtual ~TestEnv(); - - void SetUp() override; - - void TearDown() override; - // Obtain the system assigned listening port - uint16_t graphServerPort() const; - uint16_t metaServerPort() const; - uint16_t storageServerPort() const; - - std::unique_ptr<GraphClient> getClient() const; - - meta::ClientBasedGflagsManager* gflagsManager(); - - test::ServerContext* storageServer(); - - meta::MetaClient* metaClient(); - - const std::string getMetaRootPath() { - return metaRootPath_.path(); - } - - const std::string getStorageRootPath() { - return storageRootPath_.path(); - } - -private: - nebula::fs::TempDir metaRootPath_{"/tmp/MetaTest.XXXXXX"}; - nebula::fs::TempDir storageRootPath_{"/tmp/StorageTest.XXXXXX"}; - std::unique_ptr<test::ServerContext> metaServer_{nullptr}; - std::unique_ptr<test::ServerContext> storageServer_{nullptr}; - std::unique_ptr<test::ServerContext> graphServer_{nullptr}; - std::unique_ptr<meta::MetaClient> mClient_{nullptr}; - std::unique_ptr<meta::ClientBasedGflagsManager> gflagsManager_{nullptr}; -}; - - -extern TestEnv *gEnv; - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_TEST_TESTENV_H_ diff --git a/src/executor/test/TestMain.cpp b/src/executor/test/TestMain.cpp deleted file mode 100644 index 9edfedaca8363e1e001e149a4868133423218a50..0000000000000000000000000000000000000000 --- a/src/executor/test/TestMain.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include <gtest/gtest.h> -#include "graph/test/TestEnv.h" -#include "fs/TempDir.h" -#include "meta/test/TestUtils.h" - -using nebula::graph::TestEnv; -using nebula::graph::gEnv; -using nebula::meta::TestUtils; -using nebula::fs::TempDir; - -DECLARE_string(meta_server_addrs); - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - folly::init(&argc, &argv, true); - google::SetStderrLogging(google::INFO); - - gEnv = new TestEnv(); // gtest will delete this env object for us - ::testing::AddGlobalTestEnvironment(gEnv); - - return RUN_ALL_TESTS(); -} diff --git a/src/executor/test/TestUtils.h b/src/executor/test/TestUtils.h deleted file mode 100644 index c78f53b901121d6a55e7f18123b4f44f1092adc2..0000000000000000000000000000000000000000 --- a/src/executor/test/TestUtils.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "test/ServerContext.h" -#include "graph/GraphService.h" -#include <thrift/lib/cpp2/server/ThriftServer.h> - - -namespace nebula { -namespace graph { - -class TestUtils { -public: - static std::unique_ptr<test::ServerContext> mockGraphServer(uint32_t port) { - auto sc = std::make_unique<test::ServerContext>(); - auto threadPool = std::make_shared<folly::IOThreadPoolExecutor>(1); - auto interface = std::make_shared<GraphService>(); - auto status = interface->init(threadPool); - CHECK(status.ok()) << status; - sc->mockCommon("graph", port, interface); - LOG(INFO) << "Starting the graph Daemon on port " << sc->port_; - return sc; - } -}; - -} // namespace graph -} // namespace nebula - diff --git a/src/executor/test/TraverseTestBase.h b/src/executor/test/TraverseTestBase.h deleted file mode 100644 index e5a5c13e745d02bcf3838d5aa340c3cdd61762c9..0000000000000000000000000000000000000000 --- a/src/executor/test/TraverseTestBase.h +++ /dev/null @@ -1,937 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_TEST_TRAVERSETESTBASE_H_ -#define GRAPH_TEST_TRAVERSETESTBASE_H_ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" -#include "storage/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { -class TraverseTestBase : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } - - static void SetUpTestCase() { - client_ = gEnv->getClient(); - storagePort_ = gEnv->storageServerPort(); - - ASSERT_NE(nullptr, client_); - - ASSERT_TRUE(prepareSchema()); - - ASSERT_TRUE(prepareData()); - } - - static void TearDownTestCase() { - ASSERT_TRUE(removeData()); - client_.reset(); - } - - AssertionResult verifyPath(const cpp2::ExecutionResponse &resp, - std::vector<std::string> &expected) { - if (resp.get_error_code() != cpp2::ErrorCode::SUCCEEDED) { - auto *errmsg = resp.get_error_msg(); - return TestError() << "Query failed with `" - << static_cast<int32_t>(resp.get_error_code()) - << (errmsg == nullptr ? "'" : "': " + *errmsg); - } - - if (resp.get_rows() == nullptr && expected.empty()) { - return TestOK(); - } - - auto rows = buildPathString(*resp.get_rows()); - - if (expected.size() != rows.size()) { - return TestError() << "Rows' count not match: " - << rows.size() << " vs. " << expected.size(); - } - - std::sort(rows.begin(), rows.end()); - std::sort(expected.begin(), expected.end()); - - for (decltype(rows.size()) i = 0; i < rows.size(); ++i) { - if (rows[i] != expected[i]) { - return TestError() << rows[i] << " vs. " << expected[i]; - } - } - return TestOK(); - } - - static std::vector<std::string> buildPathString(std::vector<cpp2::RowValue> rows) { - std::vector<std::string> paths; - for (auto &row : rows) { - auto &pathValue = row.get_columns().back().get_path(); - auto &cols = pathValue.get_entry_list(); - std::string pathStr; - auto iter = cols.begin(); - while (iter < (cols.end() - 1)) { - pathStr += folly::stringPrintf("%ld<%s,%ld>", - iter->get_vertex().get_id(), - (iter + 1)->get_edge().get_type().c_str(), - (iter + 1)->get_edge().get_ranking()); - iter = iter + 2; - } - pathStr += folly::to<std::string>(iter->get_vertex().get_id()); - paths.emplace_back(std::move(pathStr)); - } - - return paths; - } - - - static AssertionResult prepareSchema(); - - static AssertionResult prepareData(); - - static AssertionResult removeData(); - - class Player final { - public: - Player(std::string name, int64_t age) { - name_ = std::move(name); - age_ = age; - vid_ = std::hash<std::string>()(name_); - } - - Player(const Player&) = default; - Player(Player&&) = default; - Player& operator=(const Player&) = default; - Player& operator=(Player&&) = default; - - const std::string& name() const { - return name_; - } - - int64_t vid() const { - return vid_; - } - - int64_t age() const { - return age_; - } - - Player& serve(std::string team, int64_t startYear, int64_t endYear) { - serves_.emplace_back(std::move(team), startYear, endYear); - return *this; - } - - Player& like(std::string player, int64_t likeness) { - likes_.emplace_back(std::move(player), likeness); - return *this; - } - - const auto& serves() const { - return serves_; - } - - const auto& likes() const { - return likes_; - } - - private: - using Serve = std::tuple<std::string, int64_t, int64_t>; - using Like = std::tuple<std::string, int64_t>; - std::string name_; - int64_t vid_{0}; - int64_t age_{0}; - std::vector<Serve> serves_; - std::vector<Like> likes_; - }; - - template <typename Vertex, typename Key = std::string> - class VertexHolder final { - public: - using KeyGetter = std::function<Key(const Vertex&)>; - using Container = std::unordered_map<Key, Vertex>; - using InternalIterator = typename Container::iterator; - VertexHolder(KeyGetter getter, std::initializer_list<Vertex> vertices) { - getter_ = std::move(getter); - for (auto &vertex : vertices) { - vertices_.emplace(getter_(vertex), std::move(vertex)); - } - } - - const Vertex& operator[](const Key &key) const { - auto iter = vertices_.find(key); - CHECK(iter != vertices_.end()) << "Vertex not exist, key: " << key;; - return iter->second; - } - - Vertex& operator[](const Key &key) { - auto iter = vertices_.find(key); - CHECK(iter != vertices_.end()) << "Vertex not exist, key: " << key; - return iter->second; - } - - class Iterator final { - public: - explicit Iterator(InternalIterator iter) { - iter_ = iter; - } - - Iterator& operator++() { - ++iter_; - return *this; - } - - Vertex& operator*() { - return iter_->second; - } - - Vertex* operator->() { - return &iter_->second; - } - - bool operator==(const Iterator &rhs) const { - return iter_ == rhs.iter_; - } - - bool operator!=(const Iterator &rhs) const { - return !(*this == rhs); - } - - private: - InternalIterator iter_; - }; - - Iterator begin() { - return Iterator(vertices_.begin()); - } - - Iterator end() { - return Iterator(vertices_.end()); - } - - private: - KeyGetter getter_; - Container vertices_; - }; - - - class Team final { - public: - explicit Team(std::string name) { - name_ = std::move(name); - vid_ = std::hash<std::string>()(name_); - } - - const std::string& name() const { - return name_; - } - - int64_t vid() const { - return vid_; - } - - private: - std::string name_; - int64_t vid_{0}; - }; - -protected: - static uint16_t storagePort_; - static std::unique_ptr<GraphClient> client_; - static VertexHolder<Player> players_; - static VertexHolder<Team> teams_; -}; - -uint16_t TraverseTestBase::storagePort_ = 0; - -std::unique_ptr<GraphClient> TraverseTestBase::client_; - -TraverseTestBase::VertexHolder<TraverseTestBase::Player> TraverseTestBase::players_ = { - [] (const auto &player) { return player.name(); }, { - Player{"Tim Duncan", 42/*, 1997*/}, - Player{"Tony Parker", 36}, - Player{"LaMarcus Aldridge", 33}, - Player{"Rudy Gay", 32}, - Player{"Marco Belinelli", 32}, - Player{"Danny Green", 31}, - Player{"Kyle Anderson", 25}, - Player{"Aron Baynes", 32}, - Player{"Boris Diaw", 36}, - Player{"Tiago Splitter", 34}, - Player{"Cory Joseph", 27}, - Player{"David West", 38}, - Player{"Jonathon Simmons", 29}, - Player{"Dejounte Murray", 29}, - Player{"Tracy McGrady", 39}, - Player{"Kobe Bryant", 40}, - Player{"LeBron James", 34}, - Player{"Stephen Curry", 31}, - Player{"Russell Westbrook", 30}, - Player{"Kevin Durant", 30}, - Player{"James Harden", 29}, - Player{"Chris Paul", 33}, - Player{"DeAndre Jordan", 30}, - Player{"Ricky Rubio", 28}, - - Player{"Rajon Rondo", 33}, - Player{"Manu Ginobili", 41}, - Player{"Kyrie Irving", 26}, - Player{"Vince Carter", 42}, - Player{"Carmelo Anthony", 34}, - Player{"Dwyane Wade", 37}, - Player{"Joel Embiid", 25}, - Player{"Paul George", 28}, - Player{"Giannis Antetokounmpo", 24}, - Player{"Yao Ming", 38}, - Player{"Blake Griffin", 30}, - Player{"Damian Lillard", 28}, - Player{"Steve Nash", 45}, - Player{"Dirk Nowitzki", 40}, - Player{"Paul Gasol", 38}, - Player{"Marc Gasol", 34}, - Player{"Grant Hill", 46}, - Player{"Ray Allen", 43}, - Player{"Klay Thompson", 29}, - Player{"Kristaps Porzingis", 23}, - Player{"Shaquile O'Neal", 47}, - Player{"JaVale McGee", 31}, - Player{"Dwight Howard", 33}, - Player{"Amar'e Stoudemire", 36}, - Player{"Jason Kidd", 45}, - Player{"Ben Simmons", 22}, - Player{"Luka Doncic", 20}, - - Player{"Nobody", 0}, - } -}; - -TraverseTestBase::VertexHolder<TraverseTestBase::Team> TraverseTestBase::teams_ = { - [] (const auto &team) { return team.name(); }, { - Team{"Warriors"}, - Team{"Nuggets"}, - Team{"Rockets"}, - Team{"Trail Blazers"}, - Team{"Spurs"}, - Team{"Thunders"}, - Team{"Jazz"}, - Team{"Clippers"}, - Team{"Kings"}, - Team{"Timberwolves"}, - Team{"Lakers"}, - Team{"Pelicans"}, - Team{"Grizzlies"}, - Team{"Mavericks"}, - Team{"Suns"}, - - Team{"Hornets"}, - Team{"Cavaliers"}, - Team{"Celtics"}, - Team{"Raptors"}, - Team{"76ers"}, - Team{"Pacers"}, - Team{"Bulls"}, - Team{"Hawks"}, - Team{"Knicks"}, - Team{"Pistons"}, - Team{"Bucks"}, - Team{"Magic"}, - Team{"Nets"}, - Team{"Wizards"}, - Team{"Heat"}, - } -}; - - -// static -AssertionResult TraverseTestBase::prepareSchema() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE nba(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - - // fix UTs failed sometimes - auto kvstore = gEnv->storageServer()->kvStore_.get(); - GraphSpaceID spaceId = 1; // default_space id is 1 - nebula::storage::TestUtils::waitUntilAllElected(kvstore, spaceId, 1); - - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE nba"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG player(name string, age int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG team(name string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE serve(start_year int, end_year int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE like(likeness int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - sleep(FLAGS_load_data_interval_secs + 3); - return TestOK(); -} - - -AssertionResult TraverseTestBase::prepareData() { - // TODO(dutor) Maybe we should move these data into some kind of testing resources, later. - players_["Tim Duncan"].serve("Spurs", 1997, 2016) - .like("Tony Parker", 95) - .like("Manu Ginobili", 95); - - players_["Tony Parker"].serve("Spurs", 1999, 2018) - .serve("Hornets", 2018, 2019) - .like("Tim Duncan", 95) - .like("Manu Ginobili", 95) - .like("LaMarcus Aldridge", 90); - - players_["Manu Ginobili"].serve("Spurs", 2002, 2018) - .like("Tim Duncan", 90); - - players_["LaMarcus Aldridge"].serve("Trail Blazers", 2006, 2015) - .serve("Spurs", 2015, 2019) - .like("Tony Parker", 75) - .like("Tim Duncan", 75); - - players_["Rudy Gay"].serve("Grizzlies", 2006, 2013) - .serve("Raptors", 2013, 2013) - .serve("Kings", 2013, 2017) - .serve("Spurs", 2017, 2019) - .like("LaMarcus Aldridge", 70); - - players_["Marco Belinelli"].serve("Warriors", 2007, 2009) - .serve("Raptors", 2009, 2010) - .serve("Hornets", 2010, 2012) - .serve("Bulls", 2012, 2013) - .serve("Spurs", 2013, 2015) - .serve("Kings", 2015, 2016) - .serve("Hornets", 2016, 2017) - .serve("Hawks", 2017, 2018) - .serve("76ers", 2018, 2018) - .serve("Spurs", 2018, 2019) - .like("Tony Parker", 50) - .like("Tim Duncan", 55) - .like("Danny Green", 60); - - players_["Danny Green"].serve("Cavaliers", 2009, 2010) - .serve("Spurs", 2010, 2018) - .serve("Raptors", 2018, 2019) - .like("Marco Belinelli", 83) - .like("Tim Duncan", 70) - .like("LeBron James", 80); - - players_["Kyle Anderson"].serve("Spurs", 2014, 2018) - .serve("Grizzlies", 2018, 2019); - - players_["Aron Baynes"].serve("Spurs", 2013, 2015) - .serve("Pistons", 2015, 2017) - .serve("Celtics", 2017, 2019) - .like("Tim Duncan", 80); - - players_["Boris Diaw"].serve("Hawks", 2003, 2005) - .serve("Suns", 2005, 2008) - .serve("Hornets", 2008, 2012) - .serve("Spurs", 2012, 2016) - .serve("Jazz", 2016, 2017) - .like("Tony Parker", 80) - .like("Tim Duncan", 80); - - players_["Tiago Splitter"].serve("Spurs", 2010, 2015) - .serve("Hawks", 2015, 2017) - .serve("76ers", 2017, 2017) - .like("Tim Duncan", 80) - .like("Manu Ginobili", 90); - - players_["Cory Joseph"].serve("Spurs", 2011, 2015) - .serve("Raptors", 2015, 2017) - .serve("Pacers", 2017, 2019); - - players_["David West"].serve("Hornets", 2003, 2011) - .serve("Pacers", 2011, 2015) - .serve("Spurs", 2015, 2016) - .serve("Warriors", 2016, 2018); - - players_["Jonathon Simmons"].serve("Spurs", 2015, 2017) - .serve("Magic", 2017, 2019) - .serve("76ers", 2019, 2019); - - players_["Dejounte Murray"].serve("Spurs", 2016, 2019) - .like("Tim Duncan", 99) - .like("Tony Parker", 99) - .like("Manu Ginobili", 99) - .like("Marco Belinelli", 99) - .like("Danny Green", 99) - .like("LeBron James", 99) - .like("Russell Westbrook", 99) - .like("Chris Paul", 99) - .like("Kyle Anderson", 99) - .like("Kevin Durant", 99) - .like("James Harden", 99) - .like("Tony Parker", 99); - - players_["Tracy McGrady"].serve("Raptors", 1997, 2000) - .serve("Magic", 2000, 2004) - .serve("Rockets", 2004, 2010) - .serve("Spurs", 2013, 2013) - .like("Kobe Bryant", 90) - .like("Grant Hill", 90) - .like("Rudy Gay", 90); - - players_["Kobe Bryant"].serve("Lakers", 1996, 2016); - - players_["LeBron James"].serve("Cavaliers", 2003, 2010) - .serve("Heat", 2010, 2014) - .serve("Cavaliers", 2014, 2018) - .serve("Lakers", 2018, 2019) - .like("Ray Allen", 100); - - players_["Stephen Curry"].serve("Warriors", 2009, 2019); - - players_["Russell Westbrook"].serve("Thunders", 2008, 2019) - .like("Paul George", 90) - .like("James Harden", 90); - - players_["Kevin Durant"].serve("Thunders", 2007, 2016) - .serve("Warriors", 2016, 2019); - - players_["James Harden"].serve("Thunders", 2009, 2012) - .serve("Rockets", 2012, 2019) - .like("Russell Westbrook", 80); - - players_["Chris Paul"].serve("Hornets", 2005, 2011) - .serve("Clippers", 2011, 2017) - .serve("Rockets", 2017, 2021) - .like("LeBron James", 90) - .like("Carmelo Anthony", 90) - .like("Dwyane Wade", 90); - - players_["DeAndre Jordan"].serve("Clippers", 2008, 2018) - .serve("Mavericks", 2018, 2019) - .serve("Knicks", 2019, 2019); - - players_["Ricky Rubio"].serve("Timberwolves", 2011, 2017) - .serve("Jazz", 2017, 2019); - - players_["Rajon Rondo"].serve("Celtics", 2006, 2014) - .serve("Mavericks", 2014, 2015) - .serve("Kings", 2015, 2016) - .serve("Bulls", 2016, 2017) - .serve("Pelicans", 2017, 2018) - .serve("Lakers", 2018, 2019) - .like("Ray Allen", -1); - - players_["Kyrie Irving"].serve("Cavaliers", 2011, 2017) - .serve("Celtics", 2017, 2019) - .like("LeBron James", 13); - - players_["Vince Carter"].serve("Raptors", 1998, 2004) - .serve("Nets", 2004, 2009) - .serve("Magic", 2009, 2010) - .serve("Suns", 2010, 2011) - .serve("Mavericks", 2011, 2014) - .serve("Grizzlies", 2014, 2017) - .serve("Kings", 2017, 2018) - .serve("Hawks", 2018, 2019) - .like("Tracy McGrady", 90) - .like("Jason Kidd", 70); - - players_["Carmelo Anthony"].serve("Nuggets", 2003, 2011) - .serve("Knicks", 2011, 2017) - .serve("Thunders", 2017, 2018) - .serve("Rockets", 2018, 2019) - .like("LeBron James", 90) - .like("Chris Paul", 90) - .like("Dwyane Wade", 90); - - players_["Dwyane Wade"].serve("Heat", 2003, 2016) - .serve("Bulls", 2016, 2017) - .serve("Cavaliers", 2017, 2018) - .serve("Heat", 2018, 2019) - .like("LeBron James", 90) - .like("Chris Paul", 90) - .like("Carmelo Anthony", 90); - - players_["Joel Embiid"].serve("76ers", 2014, 2019) - .like("Ben Simmons", 80); - - players_["Paul George"].serve("Pacers", 2010, 2017) - .serve("Thunders", 2017, 2019) - .like("Russell Westbrook", 95); - - players_["Giannis Antetokounmpo"].serve("Bucks", 2013, 2019); - - players_["Yao Ming"].serve("Rockets", 2002, 2011) - .like("Tracy McGrady", 90) - .like("Shaquile O'Neal", 90); - - players_["Blake Griffin"].serve("Clippers", 2009, 2018) - .serve("Pistons", 2018, 2019) - .like("Chris Paul", -1); - - players_["Damian Lillard"].serve("Trail Blazers", 2012, 2019) - .like("LaMarcus Aldridge", 80); - - players_["Steve Nash"].serve("Suns", 1996, 1998) - .serve("Mavericks", 1998, 2004) - .serve("Suns", 2004, 2012) - .serve("Lakers", 2012, 2015) - .like("Amar'e Stoudemire", 90) - .like("Dirk Nowitzki", 88) - .like("Stephen Curry", 90) - .like("Jason Kidd", 85); - - players_["Dirk Nowitzki"].serve("Mavericks", 1998, 2019) - .like("Steve Nash", 80) - .like("Jason Kidd", 80) - .like("Dwyane Wade", 10); - - players_["Paul Gasol"].serve("Grizzlies", 2001, 2008) - .serve("Lakers", 2008, 2014) - .serve("Bulls", 2014, 2016) - .serve("Spurs", 2016, 2019) - .serve("Bucks", 2019, 2020) - .like("Kobe Bryant", 90) - .like("Marc Gasol", 99); - - players_["Marc Gasol"].serve("Grizzlies", 2008, 2019) - .serve("Raptors", 2019, 2019) - .like("Paul Gasol", 99); - - players_["Grant Hill"].serve("Pistons", 1994, 2000) - .serve("Magic", 2000, 2007) - .serve("Suns", 2007, 2012) - .serve("Clippers", 2012, 2013) - .like("Tracy McGrady", 90); - - players_["Ray Allen"].serve("Bucks", 1996, 2003) - .serve("Thunders", 2003, 2007) - .serve("Celtics", 2007, 2012) - .serve("Heat", 2012, 2014) - .like("Rajon Rondo", 9); - - players_["Klay Thompson"].serve("Warriors", 2011, 2019) - .like("Stephen Curry", 90); - - players_["Kristaps Porzingis"].serve("Knicks", 2015, 2019) - .serve("Mavericks", 2019, 2020) - .like("Luka Doncic", 90); - - players_["Shaquile O'Neal"].serve("Magic", 1992, 1996) - .serve("Lakers", 1996, 2004) - .serve("Heat", 2004, 2008) - .serve("Suns", 2008, 2009) - .serve("Cavaliers", 2009, 2010) - .serve("Celtics", 2010, 2011) - .like("JaVale McGee", 100) - .like("Tim Duncan", 80); - - players_["JaVale McGee"].serve("Wizards", 2008, 2012) - .serve("Nuggets", 2012, 2015) - .serve("Mavericks", 2015, 2016) - .serve("Warriors", 2016, 2018) - .serve("Lakers", 2018, 2019); - - players_["Dwight Howard"].serve("Magic", 2004, 2012) - .serve("Lakers", 2012, 2013) - .serve("Rockets", 2013, 2016) - .serve("Hawks", 2016, 2017) - .serve("Hornets", 2017, 2018) - .serve("Wizards", 2018, 2019); - - players_["Amar'e Stoudemire"].serve("Suns", 2002, 2010) - .serve("Knicks", 2010, 2015) - .serve("Heat", 2015, 2016) - .like("Steve Nash", 90); - - players_["Jason Kidd"].serve("Mavericks", 1994, 1996) - .serve("Suns", 1996, 2001) - .serve("Nets", 2001, 2008) - .serve("Mavericks", 2008, 2012) - .serve("Knicks", 2012, 2013) - .like("Vince Carter", 80) - .like("Steve Nash", 90) - .like("Dirk Nowitzki", 85); - - players_["Ben Simmons"].serve("76ers", 2016, 2019) - .like("Joel Embiid", 80); - - players_["Luka Doncic"].serve("Mavericks", 2018, 2019) - .like("Dirk Nowitzki", 90) - .like("Kristaps Porzingis", 90) - .like("James Harden", 80); - - { - cpp2::ExecutionResponse resp; - std::string query = "USE nba"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "USE nba failed" - << static_cast<int32_t>(code); - } - } - { - // Insert vertices `player' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT VERTEX player(name, age) VALUES "; - for (auto &player : players_) { - query += std::to_string(player.vid()); - query += ": "; - query += "("; - query += "\""; - query += player.name(); - query += "\""; - query += ","; - query += std::to_string(player.age()); - query += "),\n\t"; - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `players' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert vertices `player' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT VERTEX player(name, age) VALUES "; - for (auto &player : players_) { - query += "uuid(\""; - query += player.name(); - query += "\"): "; - query += "("; - query += "\""; - query += player.name(); - query += "\""; - query += ","; - query += std::to_string(player.age()); - query += "),\n\t"; - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `players' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert vertices `team' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT VERTEX team(name) VALUES "; - for (auto &team : teams_) { - query += std::to_string(team.vid()); - query += ": "; - query += "("; - query += "\""; - query += team.name(); - query += "\""; - query += "),\n\t"; - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `teams' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert vertices `team' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT VERTEX team(name) VALUES "; - for (auto &team : teams_) { - query += "uuid(\""; - query += team.name(); - query += "\"): "; - query += "("; - query += "\""; - query += team.name(); - query += "\""; - query += "),\n\t"; - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `teams' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert edges `serve' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT EDGE serve(start_year, end_year) VALUES "; - for (auto &player : players_) { - for (auto &serve : player.serves()) { - auto &team = std::get<0>(serve); - auto startYear = std::get<1>(serve); - auto endYear = std::get<2>(serve); - query += std::to_string(player.vid()); - query += " -> "; - query += std::to_string(teams_[team].vid()); - query += ": "; - query += "("; - query += std::to_string(startYear); - query += ", "; - query += std::to_string(endYear); - query += "),\n\t"; - } - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `serve' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert edges `serve' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT EDGE serve(start_year, end_year) VALUES "; - for (auto &player : players_) { - for (auto &serve : player.serves()) { - auto &team = std::get<0>(serve); - auto startYear = std::get<1>(serve); - auto endYear = std::get<2>(serve); - query += "uuid(\""; - query += player.name(); - query += "\") -> uuid(\""; - query += teams_[team].name(); - query += "\"): "; - query += "("; - query += std::to_string(startYear); - query += ", "; - query += std::to_string(endYear); - query += "),\n\t"; - } - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `serve' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert edges `like' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT EDGE like(likeness) VALUES "; - for (auto &player : players_) { - for (auto &like : player.likes()) { - auto &other = std::get<0>(like); - auto likeness = std::get<1>(like); - query += std::to_string(player.vid()); - query += " -> "; - query += std::to_string(players_[other].vid()); - query += ": "; - query += "("; - query += std::to_string(likeness); - query += "),\n\t"; - } - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `like' failed: " - << static_cast<int32_t>(code); - } - } - { - // Insert edges `like' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query += "INSERT EDGE like(likeness) VALUES "; - for (auto &player : players_) { - for (auto &like : player.likes()) { - auto &other = std::get<0>(like); - auto likeness = std::get<1>(like); - query += "uuid(\""; - query += player.name(); - query += "\") -> uuid(\""; - query += players_[other].name(); - query += "\"): "; - query += "("; - query += std::to_string(likeness); - query += "),\n\t"; - } - } - query.resize(query.size() - 3); - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert `like' failed: " - << static_cast<int32_t>(code); - } - } - return TestOK(); -} - -AssertionResult TraverseTestBase::removeData() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE nba"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - return TestOK(); -} -} // namespace graph -} // namespace nebula - -#endif // GRAPH_TEST_TRAVERSETESTBASE_H diff --git a/src/executor/test/UpdateTest.cpp b/src/executor/test/UpdateTest.cpp deleted file mode 100644 index d7b102843c65240856cfdd1a0add7e3372df10fb..0000000000000000000000000000000000000000 --- a/src/executor/test/UpdateTest.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/UpdateTestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { - -class UpdateTest : public UpdateTestBase { -protected: - void SetUp() override { - UpdateTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - UpdateTestBase::TearDown(); - } -}; - - -TEST_F(UpdateTest, UpdateVertex) { - // INSERT VERTEX course(name, credits), building(name) VALUES 101:("Math", 3, "No5"); - { // OnlySet - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET course.credits = $^.course.credits + 1, building.name = \"No6\" "; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX uuid(\"Math\") " - "SET course.credits = $^.course.credits + 1, building.name = \"No6\" "; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { // SetFilter - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET course.credits = $^.course.credits + 1, building.name = \"No7\" " - "WHEN $^.course.name == \"Math\" && $^.course.credits > 2"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX uuid(\"Math\") " - "SET course.credits = $^.course.credits + 1, building.name = \"No7\" " - "WHEN $^.course.name == \"Math\" && $^.course.credits > 2"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { // SetYield - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET course.credits = $^.course.credits + 1, building.name = \"No8\" " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Math", 6, "No8"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX uuid(\"Math\") " - "SET course.credits = $^.course.credits + 1, building.name = \"No8\" " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Math", 6, "No8"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { // SetFilterYield - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET course.credits = $^.course.credits + 1, building.name = \"No9\" " - "WHEN $^.course.name == \"Math\" && $^.course.credits > 2 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Math", 7, "No9"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX uuid(\"Math\") " - "SET course.credits = $^.course.credits + 1, building.name = \"No9\" " - "WHEN $^.course.name == \"Math\" && $^.course.credits > 2 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"Math", 7, "No9"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { // Insertable: vertex 103 ("CS", 5) --> ("CS", 6, "No10") - cpp2::ExecutionResponse resp; - auto query = "UPSERT VERTEX 103 " - "SET course.credits = $^.course.credits + 1, building.name = \"No10\" " - "WHEN $^.course.name == \"CS\" && $^.course.credits > 2 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"CS", 6, "No10"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPSERT VERTEX uuid(\"CS\") " - "SET course.credits = $^.course.credits + 1, building.name = \"No10\" " - "WHEN $^.course.name == \"CS\" && $^.course.credits > 2 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, std::string>> expected = { - {"CS", 6, "No10"}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(UpdateTest, UpdateEdge) { - // OnlySet, SetFilter, SetYield, SetFilterYield, Insertable - { // OnlySet - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET grade = select.grade + 1, year = 2000"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE uuid(\"Monica\") -> uuid(\"Math\")@0 OF select " - "SET grade = select.grade + 1, year = 2000"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { // SetFilter - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET grade = select.grade + 1, year = 2000 " - "WHEN select.grade > 4 && $^.student.age > 15"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE uuid(\"Monica\") -> uuid(\"Math\")@0 OF select " - "SET grade = select.grade + 1, year = 2000 " - "WHEN select.grade > 4 && $^.student.age > 15"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - } - { // SetYield - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET grade = select.grade + 1, year = 2018 " - "YIELD $^.student.name AS Name, select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, int64_t>> expected = { - {"Monica", 8, 2018}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE uuid(\"Monica\") -> uuid(\"Math\")@0 OF select " - "SET grade = select.grade + 1, year = 2018 " - "YIELD $^.student.name AS Name, select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, int64_t>> expected = { - {"Monica", 8, 2018}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { // SetFilterYield - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET grade = select.grade + 1, year = 2019 " - "WHEN select.grade > 4 && $^.student.age > 15 " - "YIELD $^.student.name AS Name, select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, int64_t>> expected = { - {"Monica", 9, 2019}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE uuid(\"Monica\") -> uuid(\"Math\")@0 OF select " - "SET grade = select.grade + 1, year = 2019 " - "WHEN select.grade > 4 && $^.student.age > 15 " - "YIELD $^.student.name AS Name, select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<std::string, int64_t, int64_t>> expected = { - {"Monica", 9, 2019}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { // Insertable - cpp2::ExecutionResponse resp; - auto query = "UPSERT EDGE 201 -> 101@0 OF select " - "SET grade = 3, year = 2019 " - "WHEN $^.student.age > 15 && $^.student.gender == \"male\" " - "YIELD select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {3, 2019}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto query = "UPSERT EDGE uuid(\"Mike\") -> uuid(\"Math\")@0 OF select " - "SET grade = 3, year = 2019 " - "WHEN $^.student.age > 15 && $^.student.gender == \"male\" " - "YIELD select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected = { - {3, 2019}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - - -TEST_F(UpdateTest, InvalidTest) { - { // update vertex: the item is TagName.PropName = Expression in SET clause - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET credits = $^.course.credits + 1, name = \"No9\""; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { // update edge: the item is PropName = Expression in SET clause - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET select.grade = select.grade + 1, select.year = 2019"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { // the $$.TagName.PropName expressions are not allowed in any update sentence - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET course.credits = $$.course.credits + 1 " - "WHEN $$.course.name == \"Math\" && $^.course.credits > $$.course.credits + 1 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $$.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { // make sure the vertex must exist - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101000000000000 " - "SET course.credits = $^.course.credits + 1, building.name = \"No9\" " - "WHEN $^.course.name == \"Math\" && $^.course.credits > 2 " - "YIELD $^.course.name AS Name, $^.course.credits AS Credits, $^.building.name"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } - { // make sure TagName and PropertyName must exist in all clauses - cpp2::ExecutionResponse resp; - auto query = "UPDATE VERTEX 101 " - "SET nonexistentTag.credits = $^.course.credits + 1, building.name = \"No9\" " - "WHEN $^.course.name == \"Math\" && $^.course.nonexistentProperty > 2 " - "YIELD $^.course.name AS Name, $^.nonexistentTag.nonexistentProperty"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } - { // make sure the edge(src, dst) must exist - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101000000000000@0 OF select " - "SET grade = select.grade + 1, year = 2019 " - "WHEN select.grade > 4 && $^.student.age > 15 " - "YIELD $^.student.name AS Name, select.grade AS Grade, select.year AS Year"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } - { // make sure the edge(src, edge_tyep, dst) must exist - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF nonexistentEdgeTypeName " - "SET grade = select.grade + 1, year = 2019"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } - { // make sure the edge(src, edge_tyep, ranking<default is 0>, dst) must exist - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101 OF select " - "SET grade = select.grade + 1, year = 2019"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - } - { // make sure the edge(src, edge_tyep, ranking, dst) must exist - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@1000000000000 OF select " - "SET grade = select.grade + 1, year = 2019"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } - { // make sure EdgeName and PropertyName must exist in all clauses - cpp2::ExecutionResponse resp; - auto query = "UPDATE EDGE 200 -> 101@0 OF select " - "SET nonexistentProperty = select.grade + 1, year = 2019 " - "WHEN nonexistentEdgeName.grade > 4 && $^.student.nonexistentProperty > 15 " - "YIELD $^.nonexistentTag.name AS Name, select.nonexistentProperty AS Grade"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code) << resp.get_error_msg(); - } -} - - -} // namespace graph -} // namespace nebula diff --git a/src/executor/test/UpdateTestBase.h b/src/executor/test/UpdateTestBase.h deleted file mode 100644 index 7eefc7aed069f61e6a820ba5e09d00b8f2d1ad79..0000000000000000000000000000000000000000 --- a/src/executor/test/UpdateTestBase.h +++ /dev/null @@ -1,266 +0,0 @@ -/* Copyright (c) 2019 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#ifndef GRAPH_TEST_UPDATETESTBASE_H -#define GRAPH_TEST_UPDATETESTBASE_H - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "meta/test/TestUtils.h" - -DECLARE_int32(load_data_interval_secs); - -namespace nebula { -namespace graph { -// https://github.com/vesoft-inc/nebula/blob/master/docs/get-started.md#build-your-own-graph -class UpdateTestBase : public TestBase { -protected: - void SetUp() override { - TestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TestBase::TearDown(); - } - - static void SetUpTestCase() { - client_ = gEnv->getClient(); - storagePort_ = gEnv->storageServerPort(); - - ASSERT_NE(nullptr, client_); - - ASSERT_TRUE(prepareSchema()); - - ASSERT_TRUE(prepareData()); - } - - static void TearDownTestCase() { - ASSERT_TRUE(removeData()); - client_.reset(); - } - - static AssertionResult prepareSchema(); - - static AssertionResult prepareData(); - - static AssertionResult removeData(); - -protected: - static uint16_t storagePort_; - static std::unique_ptr<GraphClient> client_; -}; - -uint16_t UpdateTestBase::storagePort_ = 0; - -std::unique_ptr<GraphClient> UpdateTestBase::client_; - -// static -AssertionResult UpdateTestBase::prepareSchema() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE SPACE myspace_test2(partition_num=1, replica_factor=1)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "USE myspace_test2"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG course(name string, credits int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG building(name string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE TAG student(name string, age int, gender string)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE like(likeness double)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - { - cpp2::ExecutionResponse resp; - std::string cmd = "CREATE EDGE select(grade int, year int)"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - sleep(FLAGS_load_data_interval_secs + 3); - return TestOK(); -} - - -AssertionResult UpdateTestBase::prepareData() { - { - cpp2::ExecutionResponse resp; - std::string query = "USE myspace_test2"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "USE myspace_test2 failed" - << static_cast<int32_t>(code); - } - } - { // Insert vertices 'student' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query = "INSERT VERTEX student(name, age, gender) VALUES " - "200:(\"Monica\", 16, \"female\"), " - "201:(\"Mike\", 18, \"male\"), " - "202:(\"Jane\", 17, \"female\")"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'student' failed: " - << static_cast<int32_t>(code); - } - // Insert vertices 'course' and 'building' - query.clear(); - query = "INSERT VERTEX course(name, credits),building(name) VALUES " - "101:(\"Math\", 3, \"No5\"), " - "102:(\"English\", 6, \"No11\")"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'course' and 'building' failed: " - << static_cast<int32_t>(code); - } - // Insert vertices only 'course'(for update insertable testing) - query.clear(); - query = "INSERT VERTEX course(name, credits) VALUES 103:(\"CS\", 5)"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'course' failed: " - << static_cast<int32_t>(code); - } - } - { // Insert vertices 'student' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query = "INSERT VERTEX student(name, age, gender) VALUES " - "uuid(\"Monica\"):(\"Monica\", 16, \"female\"), " - "uuid(\"Mike\"):(\"Mike\", 18, \"male\"), " - "uuid(\"Jane\"):(\"Jane\", 17, \"female\")"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'student' failed: " - << static_cast<int32_t>(code); - } - query.clear(); - query = "INSERT VERTEX course(name, credits),building(name) VALUES " - "uuid(\"Math\"):(\"Math\", 3, \"No5\"), " - "uuid(\"English\"):(\"English\", 6, \"No11\")"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'course' and 'building' failed: " - << static_cast<int32_t>(code); - } - query.clear(); - query = "INSERT VERTEX course(name, credits) VALUES uuid(\"CS\"):(\"CS\", 5)"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'course' failed: " - << static_cast<int32_t>(code); - } - } - { // Insert edges 'select' and 'like' - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query = "INSERT EDGE select(grade, year) VALUES " - "200 -> 101@0:(5, 2018), " - "200 -> 102@0:(3, 2018), " - "201 -> 102@0:(3, 2019), " - "202 -> 102@0:(3, 2019)"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'select' failed: " - << static_cast<int32_t>(code); - } - query.clear(); - query = "INSERT EDGE like(likeness) VALUES " - "200 -> 201@0:(92.5), " - "201 -> 200@0:(85.6), " - "201 -> 202@0:(93.2)"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'like' failed: " - << static_cast<int32_t>(code); - } - } - { // Insert edges 'select' and 'like' with uuid - cpp2::ExecutionResponse resp; - std::string query; - query.reserve(1024); - query = "INSERT EDGE select(grade, year) VALUES " - "uuid(\"Monica\") -> uuid(\"Math\")@0:(5, 2018), " - "uuid(\"Monica\") -> uuid(\"English\")@0:(3, 2018), " - "uuid(\"Mike\") -> uuid(\"English\")@0:(3, 2019), " - "uuid(\"Jane\") -> uuid(\"English\")@0:(3, 2019)"; - auto code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'select' failed: " - << static_cast<int32_t>(code); - } - query.clear(); - query = "INSERT EDGE like(likeness) VALUES " - "uuid(\"Monica\") -> uuid(\"Mike\")@0:(92.5), " - "uuid(\"Mike\") -> uuid(\"Monica\")@0:(85.6), " - "uuid(\"Mike\") -> uuid(\"Jane\")@0:(93.2)"; - code = client_->execute(query, resp); - if (code != cpp2::ErrorCode::SUCCEEDED) { - return TestError() << "Insert 'like' failed: " - << static_cast<int32_t>(code); - } - } - return TestOK(); -} - -AssertionResult UpdateTestBase::removeData() { - { - cpp2::ExecutionResponse resp; - std::string cmd = "DROP SPACE myspace_test2"; - auto code = client_->execute(cmd, resp); - if (cpp2::ErrorCode::SUCCEEDED != code) { - return TestError() << "Do cmd:" << cmd << " failed"; - } - } - return TestOK(); -} - -} // namespace graph -} // namespace nebula - -#endif // GRAPH_TEST_UPDATETESTBASE_H diff --git a/src/executor/test/YieldTest.cpp b/src/executor/test/YieldTest.cpp deleted file mode 100644 index 80db4a1f0ae315936ff55c544b2d9ca78aee3c8e..0000000000000000000000000000000000000000 --- a/src/executor/test/YieldTest.cpp +++ /dev/null @@ -1,655 +0,0 @@ -/* Copyright (c) 2018 vesoft inc. All rights reserved. - * - * This source code is licensed under Apache 2.0 License, - * attached with Common Clause Condition 1.0, found in the LICENSES directory. - */ - -#include "base/Base.h" -#include "graph/test/TestEnv.h" -#include "graph/test/TestBase.h" -#include "graph/test/TraverseTestBase.h" - -namespace nebula { -namespace graph { - -class YieldTest : public TraverseTestBase { -protected: - void SetUp() override { - TraverseTestBase::SetUp(); - // ... - } - - void TearDown() override { - // ... - TraverseTestBase::TearDown(); - } -}; - - -TEST_F(YieldTest, Base) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD 1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - - std::vector<std::string> expectedColNames{ - {"1"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<int64_t>> expected{ - {1} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD 1+1, '1+1', (int)3.14, (string)(1+1), (string)true"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"(1+1)"}, {"1+1"}, {"(int)3.140000"}, {"(string)(1+1)"}, {"(string)true"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<int64_t, std::string, int64_t, std::string, std::string>> expected{ - {2, "1+1", 3, "2", "true"} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD \"Hello\", hash(\"Hello\")"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"Hello"}, {"hash(Hello)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<std::string, int64_t>> expected{ - {"Hello", std::hash<std::string>()("Hello")} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, HashCall) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD hash(\"Boris\")"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"hash(Boris)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<int64_t>> expected{ - std::hash<std::string>{}("Boris") - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD hash(123)"; - auto code = client->execute(query, resp); - std::vector<std::string> expectedColNames{ - {"hash(123)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected{ - std::hash<int64_t>{}(123) - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD hash(123 + 456)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"hash((123+456))"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<int64_t>> expected{ - std::hash<int64_t>{}(123 + 456) - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD hash(123.0)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"hash(123.000000)"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<int64_t>> expected{ - std::hash<double>{}(123.0) - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD hash(!0)"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::string> expectedColNames{ - {"hash(!(0))"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<int64_t>> expected{ - std::hash<bool>{}(!0) - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, Logic) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD NOT 0 || 0 AND 0 XOR 0"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected{ - 1 - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD !0 OR 0 && 0 XOR 1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected{ - 0 - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD (NOT 0 || 0) AND 0 XOR 1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected{ - 1 - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD 2.5 % 1.2 ^ 1.6"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<double>> expected{ - 2.5 - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD (5 % 3) ^ 1"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected{ - 3 - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, InCall) { - auto client = gEnv->getClient(); - ASSERT_NE(nullptr, client); - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD udf_is_in(1,0,1,2), 123"; - auto code = client->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << *resp.get_error_msg(); - std::vector<std::string> expectedColNames{ - {"udf_is_in(1,0,1,2)"}, {"123"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - std::vector<std::tuple<bool, uint64_t>> expected{ - {true, 123} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, YieldPipe) { - std::string go = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team"; - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.team WHERE 1 == 1"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.team WHERE $-.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.*"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> result( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.* WHERE $-.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string, int64_t, std::string> result( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = go + "| YIELD $-.*,hash(123) as hash WHERE $-.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string, int64_t>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string, int64_t, std::string, int64_t> result( - player.name(), std::get<1>(serve), - std::get<0>(serve), std::hash<int32_t>{}(123)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, YieldVar) { - std::string var = " $var = GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team;"; - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.team WHERE 1 == 1"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.team WHERE $var.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string> result(std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.*"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : player.serves()) { - std::tuple<std::string, int64_t, std::string> result( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.* WHERE $var.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string, int64_t, std::string> result( - player.name(), std::get<1>(serve), std::get<0>(serve)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $var.*, hash(123) as hash WHERE $var.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - std::vector<std::tuple<std::string, int64_t, std::string, int64_t>> expected; - for (auto &serve : player.serves()) { - if (std::get<1>(serve) <= 2005) { - continue; - } - std::tuple<std::string, int64_t, std::string, int64_t> result( - player.name(), std::get<1>(serve), - std::get<0>(serve), std::hash<int32_t>{}(123)); - expected.emplace_back(std::move(result)); - } - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, Error) { - { - cpp2::ExecutionResponse resp; - // Reference input in a single yield sentence is meaningless. - auto query = "yield $-"; - auto code = client_->execute(query, resp); - UNUSED(code); - } - std::string var = " $var = GO FROM %ld OVER serve YIELD " - "$^.player.name AS name, serve.start_year AS start, $$.team.name AS team;"; - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - // Not support reference input and variable - auto fmt = var + "YIELD $var.team WHERE $-.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - // Not support reference two diffrent variable - auto fmt = var + "YIELD $var.team WHERE $var1.start > 2005"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - // Reference a non-existed prop is meaningless. - auto fmt = var + "YIELD $var.abc"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - // Reference a non-existed prop is meaningless. - std::string fmt = "GO FROM %ld OVER like | YIELD $-.abc;"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - // Reference properties in single yield sentence is meaningless. - auto fmt = var + "YIELD $$.a.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD $^.a.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Boris Diaw"]; - auto fmt = var + "YIELD a.team"; - auto query = folly::stringPrintf(fmt.c_str(), player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } -} - -TEST_F(YieldTest, AggCall) { - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD COUNT(1), $-.name"; - auto code = client_->execute(query, resp); - // Error would be reported when no input - ASSERT_EQ(cpp2::ErrorCode::E_EXECUTION_ERROR, code); - } - { - cpp2::ExecutionResponse resp; - std::string query = "YIELD COUNT(*), 1+1"; - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t, int64_t>> expected{ - {1, 2} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - auto &player = players_["Carmelo Anthony"]; - auto *fmt = "GO FROM %ld OVER like " - "YIELD $$.player.age AS age, " - "like.likeness AS like" - "| YIELD COUNT(*), $-.age"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::E_SYNTAX_ERROR, code); - } - // Test input - { - cpp2::ExecutionResponse resp; - auto &player = players_["Carmelo Anthony"]; - auto *fmt = "GO FROM %ld OVER like " - "YIELD $$.player.age AS age, " - "like.likeness AS like" - "| YIELD AVG($-.age), SUM($-.like), COUNT(*), 1+1"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<double, uint64_t, uint64_t, int64_t>> expected = { - {34.666666666666664, 270, 3, 2}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Yield field has not input - { - cpp2::ExecutionResponse resp; - auto &player = players_["Carmelo Anthony"]; - auto *fmt = "GO FROM %ld OVER like " - "| YIELD COUNT(*)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {3}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // Yield field has not input - { - cpp2::ExecutionResponse resp; - auto &player = players_["Carmelo Anthony"]; - auto *fmt = "GO FROM %ld OVER like " - "| YIELD 1"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<int64_t>> expected = { - {1}, {1}, {1} - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } - // input is empty - { - cpp2::ExecutionResponse resp; - auto &player = players_["Nobody"]; - auto *fmt = "GO FROM %ld OVER like " - "| YIELD 1"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - ASSERT_TRUE(resp.get_rows() == nullptr); - } - // Test var - { - cpp2::ExecutionResponse resp; - auto &player = players_["Carmelo Anthony"]; - auto *fmt = "$var = GO FROM %ld OVER like " - "YIELD $$.player.age AS age, " - "like.likeness AS like;" - "YIELD AVG($var.age), SUM($var.like), COUNT(*)"; - auto query = folly::stringPrintf(fmt, player.vid()); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code); - std::vector<std::tuple<double, uint64_t, uint64_t>> expected = { - {34.666666666666664, 270, 3}, - }; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} - -TEST_F(YieldTest, EmptyInput) { - std::string name = "NON EXIST VERTEX ID"; - int64_t nonExistPlayerID = std::hash<std::string>()(name); - auto iter = players_.begin(); - while (iter != players_.end()) { - if (iter->vid() == nonExistPlayerID) { - ++nonExistPlayerID; - iter = players_.begin(); - continue; - } - ++iter; - } - - { - cpp2::ExecutionResponse resp; - std::string fmt = "GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team" - "| YIELD $-.team"; - auto query = folly::stringPrintf(fmt.c_str(), nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - - std::vector<std::string> expectedColNames{ - {"$-.team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string>> expected; - ASSERT_TRUE(verifyResult(resp, expected)); - } - { - cpp2::ExecutionResponse resp; - std::string fmt = " $var = GO FROM %ld OVER serve YIELD " - "$^.player.name as name, serve.start_year as start, $$.team.name as team;" - "YIELD $var.team"; - auto query = folly::stringPrintf(fmt.c_str(), nonExistPlayerID); - auto code = client_->execute(query, resp); - ASSERT_EQ(cpp2::ErrorCode::SUCCEEDED, code) << resp.get_error_msg(); - - std::vector<std::string> expectedColNames{ - {"$var.team"} - }; - ASSERT_TRUE(verifyColNames(resp, expectedColNames)); - - std::vector<std::tuple<std::string>> expected; - ASSERT_TRUE(verifyResult(resp, expected)); - } -} -} // namespace graph -} // namespace nebula