Skip to content

Commit bb2e684

Browse files
Sophie-Xieczpmangonevermore3liwenhui-soulcritical27
authored
Cherry pick 3.2.1 (#4626)
* fix lookup (#4552) fix Co-authored-by: jimingquan <mingquan.ji@vesoft.com> Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com> * fix split brain in raft (#4479) Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com> * fix invalid filter in GetProp make storage crashed (#4568) Co-authored-by: haowen <19355821+wenhaocs@users.noreply.github.com> * fix scan vertex/edge do not handle ttl (#4578) * fix scan vertex/edge do not handle ttl * use ErrorCode to unify community version and end version * Fix #1212. Return FoldConstantExprVisitor, if status_ already failed due to found syantax errors. (#4607) Co-authored-by: jie.wang <38901892+jievince@users.noreply.github.com> * Avoid fatal when expression illegal. (#4618) * Fix concurrent exception related to multi-match statement (#4605) * fix filter executor * Fix concurrency exception of multi-match statements fix iterator fix small delete small delete skip iterator type handle for concurrency small delete fix scan edges small delete small delete fix small delete small change small change fix ut small fix Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com> * Prune properties(#4523) * fix conflict * extract attribute from properties function (#4604) * extract attribute from properties function * fix error * fix subscript error * add test case * process scanEdges * fix test error * add unwind & check vidType when executing not validate (#4456) * Update AppendVerticesExecutor.cpp fix conflict * Update AppendVerticesExecutor.cpp * Replace obsolete RocksDB API (#4395) Co-authored-by: Sophie <84560950+Sophie-Xie@users.noreply.github.com> * Update PrunePropertiesRule.feature * remove useless dc (#4533) * Update PrunePropertiesRule.feature * fix test error Co-authored-by: kyle.cao <kyle.cao@vesoft.com> Co-authored-by: jimingquan <mingquan.ji@vesoft.com> Co-authored-by: liwenhui-soul <38217397+liwenhui-soul@users.noreply.github.com> Co-authored-by: Doodle <13706157+critical27@users.noreply.github.com> Co-authored-by: haowen <19355821+wenhaocs@users.noreply.github.com> Co-authored-by: Cheng Xuntao <7731943+xtcyclist@users.noreply.github.com> Co-authored-by: jie.wang <38901892+jievince@users.noreply.github.com> Co-authored-by: shylock <33566796+Shylock-Hg@users.noreply.github.com> Co-authored-by: Qiaolin Yu <90088090+Qiaolin-Yu@users.noreply.github.com>
1 parent ef6d6a0 commit bb2e684

File tree

79 files changed

+1632
-722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1632
-722
lines changed

src/common/expression/LabelAttributeExpression.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class LabelAttributeExpression final : public Expression {
3434
}
3535

3636
const Value& eval(ExpressionContext&) override {
37-
LOG(FATAL) << "LabelAttributeExpression has to be rewritten";
37+
DLOG(FATAL) << "LabelAttributeExpression has to be rewritten";
3838
return Value::kNullBadData;
3939
}
4040

src/graph/context/Iterator.cpp

+11-9
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ Value GetNeighborsIter::getVertex(const std::string& name) const {
440440
return Value::kNullValue;
441441
}
442442

443-
auto vidVal = getColumn(nebula::kVid);
443+
auto vidVal = getColumn(0);
444444
if (UNLIKELY(!SchemaUtil::isValidVid(vidVal))) {
445445
return Value::kNullBadType;
446446
}
@@ -502,12 +502,13 @@ Value GetNeighborsIter::getEdge() const {
502502
edge.name = edgeName;
503503

504504
auto type = getEdgeProp(edgeName, kType);
505-
if (!type.isInt()) {
506-
return Value::kNullBadType;
505+
if (type.isInt()) {
506+
edge.type = type.getInt();
507+
} else {
508+
edge.type = 0;
507509
}
508-
edge.type = type.getInt();
509510

510-
auto& srcVal = getColumn(kVid);
511+
auto& srcVal = getColumn(0);
511512
if (!SchemaUtil::isValidVid(srcVal)) {
512513
return Value::kNullBadType;
513514
}
@@ -520,10 +521,11 @@ Value GetNeighborsIter::getEdge() const {
520521
edge.dst = dstVal;
521522

522523
auto& rank = getEdgeProp(edgeName, kRank);
523-
if (!rank.isInt()) {
524-
return Value::kNullBadType;
524+
if (rank.isInt()) {
525+
edge.ranking = rank.getInt();
526+
} else {
527+
edge.ranking = 0;
525528
}
526-
edge.ranking = rank.getInt();
527529

528530
auto& edgePropMap = currentDs_->edgePropsMap;
529531
auto edgeProp = edgePropMap.find(currentEdgeName());
@@ -535,7 +537,7 @@ Value GetNeighborsIter::getEdge() const {
535537
DCHECK_EQ(edgeNamePropList.size(), propList.size());
536538
for (size_t i = 0; i < propList.size(); ++i) {
537539
auto propName = edgeNamePropList[i];
538-
if (propName == kSrc || propName == kDst || propName == kRank || propName == kType) {
540+
if (propName == kDst || propName == kRank || propName == kType || propName == kSrc) {
539541
continue;
540542
}
541543
edge.props.emplace(edgeNamePropList[i], propList[i]);

src/graph/context/Result.h

+9
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ class Result final {
6363
}
6464
}
6565

66+
std::vector<std::string> getColNames() const {
67+
auto& ds = value();
68+
if (ds.isDataSet()) {
69+
return ds.getDataSet().colNames;
70+
}
71+
72+
return {};
73+
}
74+
6675
private:
6776
friend class ResultBuilder;
6877
friend class ExecutionContext;

src/graph/executor/Executor.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,10 @@ bool Executor::movable(const Variable *var) {
695695
return false;
696696
}
697697
if (node()->loopLayers() != 0) {
698+
// Guaranteed forward compatibility of go statement execution behavior
699+
if (node()->kind() == PlanNode::Kind::kFilter) {
700+
return true;
701+
}
698702
// The lifetime of loop body is managed by Loop node
699703
return false;
700704
}

src/graph/executor/StorageAccessExecutor.cpp

+23-13
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ struct Vid<std::string> {
3737
};
3838

3939
template <typename VidType>
40-
DataSet buildRequestDataSet(const SpaceInfo &space,
41-
QueryExpressionContext &exprCtx,
42-
Iterator *iter,
43-
Expression *expr,
44-
bool dedup) {
40+
StatusOr<DataSet> buildRequestDataSet(const SpaceInfo &space,
41+
QueryExpressionContext &exprCtx,
42+
Iterator *iter,
43+
Expression *expr,
44+
bool dedup,
45+
bool isCypher) {
4546
DCHECK(iter && expr) << "iter=" << iter << ", expr=" << expr;
4647
nebula::DataSet vertices({kVid});
4748
auto s = iter->size();
@@ -54,11 +55,19 @@ DataSet buildRequestDataSet(const SpaceInfo &space,
5455

5556
for (; iter->valid(); iter->next()) {
5657
auto vid = expr->eval(exprCtx(iter));
57-
if (!SchemaUtil::isValidVid(vid, vidType)) {
58-
LOG(WARNING) << "Mismatched vid type: " << vid.type()
59-
<< ", space vid type: " << SchemaUtil::typeToString(vidType);
58+
if (vid.empty()) {
6059
continue;
6160
}
61+
if (!SchemaUtil::isValidVid(vid, vidType)) {
62+
if (isCypher) {
63+
continue;
64+
}
65+
std::stringstream ss;
66+
ss << "`" << vid.toString() << "', the srcs should be type of "
67+
<< apache::thrift::util::enumNameSafe(vidType.get_type()) << ", but was`" << vid.type()
68+
<< "'";
69+
return Status::Error(ss.str());
70+
}
6271
if (dedup && !uniqueSet.emplace(Vid<VidType>::value(vid)).second) {
6372
continue;
6473
}
@@ -73,16 +82,17 @@ bool StorageAccessExecutor::isIntVidType(const SpaceInfo &space) const {
7382
return (*space.spaceDesc.vid_type_ref()).type == nebula::cpp2::PropertyType::INT64;
7483
}
7584

76-
DataSet StorageAccessExecutor::buildRequestDataSetByVidType(Iterator *iter,
77-
Expression *expr,
78-
bool dedup) {
85+
StatusOr<DataSet> StorageAccessExecutor::buildRequestDataSetByVidType(Iterator *iter,
86+
Expression *expr,
87+
bool dedup,
88+
bool isCypher) {
7989
const auto &space = qctx()->rctx()->session()->space();
8090
QueryExpressionContext exprCtx(qctx()->ectx());
8191

8292
if (isIntVidType(space)) {
83-
return internal::buildRequestDataSet<int64_t>(space, exprCtx, iter, expr, dedup);
93+
return internal::buildRequestDataSet<int64_t>(space, exprCtx, iter, expr, dedup, isCypher);
8494
}
85-
return internal::buildRequestDataSet<std::string>(space, exprCtx, iter, expr, dedup);
95+
return internal::buildRequestDataSet<std::string>(space, exprCtx, iter, expr, dedup, isCypher);
8696
}
8797

8898
std::string StorageAccessExecutor::getStorageDetail(

src/graph/executor/StorageAccessExecutor.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ class StorageAccessExecutor : public Executor {
158158

159159
bool isIntVidType(const SpaceInfo &space) const;
160160

161-
DataSet buildRequestDataSetByVidType(Iterator *iter, Expression *expr, bool dedup);
161+
StatusOr<DataSet> buildRequestDataSetByVidType(Iterator *iter,
162+
Expression *expr,
163+
bool dedup,
164+
bool isCypher = false);
162165
};
163166

164167
} // namespace graph

src/graph/executor/query/AppendVerticesExecutor.cpp

+43-6
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,32 @@
99
using nebula::storage::StorageClient;
1010
using nebula::storage::StorageRpcResponse;
1111
using nebula::storage::cpp2::GetPropResponse;
12-
12+
DECLARE_bool(optimize_appendvertices);
1313
namespace nebula {
1414
namespace graph {
1515
folly::Future<Status> AppendVerticesExecutor::execute() {
1616
return appendVertices();
1717
}
1818

19-
DataSet AppendVerticesExecutor::buildRequestDataSet(const AppendVertices *av) {
19+
StatusOr<DataSet> AppendVerticesExecutor::buildRequestDataSet(const AppendVertices *av) {
2020
if (av == nullptr) {
2121
return nebula::DataSet({kVid});
2222
}
2323
auto valueIter = ectx_->getResult(av->inputVar()).iter();
24-
return buildRequestDataSetByVidType(valueIter.get(), av->src(), av->dedup());
24+
return buildRequestDataSetByVidType(valueIter.get(), av->src(), av->dedup(), true);
2525
}
2626

2727
folly::Future<Status> AppendVerticesExecutor::appendVertices() {
2828
SCOPED_TIMER(&execTime_);
29-
3029
auto *av = asNode<AppendVertices>(node());
31-
StorageClient *storageClient = qctx()->getStorageClient();
30+
if (FLAGS_optimize_appendvertices && av != nullptr && av->props() == nullptr) {
31+
return handleNullProp(av);
32+
}
3233

33-
DataSet vertices = buildRequestDataSet(av);
34+
StorageClient *storageClient = qctx()->getStorageClient();
35+
auto res = buildRequestDataSet(av);
36+
NG_RETURN_IF_ERROR(res);
37+
auto vertices = std::move(res).value();
3438
if (vertices.rows.empty()) {
3539
return finish(ResultBuilder().value(Value(DataSet(av->colNames()))).build());
3640
}
@@ -67,6 +71,39 @@ folly::Future<Status> AppendVerticesExecutor::appendVertices() {
6771
});
6872
}
6973

74+
Status AppendVerticesExecutor::handleNullProp(const AppendVertices *av) {
75+
auto iter = ectx_->getResult(av->inputVar()).iter();
76+
auto *src = av->src();
77+
78+
auto size = iter->size();
79+
DataSet ds;
80+
ds.colNames = av->colNames();
81+
ds.rows.reserve(size);
82+
83+
QueryExpressionContext ctx(ectx_);
84+
bool canBeMoved = movable(av->inputVars().front());
85+
86+
for (; iter->valid(); iter->next()) {
87+
const auto &vid = src->eval(ctx(iter.get()));
88+
if (vid.empty()) {
89+
continue;
90+
}
91+
Vertex vertex;
92+
vertex.vid = vid;
93+
if (!av->trackPrevPath()) {
94+
Row row;
95+
row.values.emplace_back(std::move(vertex));
96+
ds.rows.emplace_back(std::move(row));
97+
} else {
98+
Row row;
99+
row = canBeMoved ? iter->moveRow() : *iter->row();
100+
row.values.emplace_back(std::move(vertex));
101+
ds.rows.emplace_back(std::move(row));
102+
}
103+
}
104+
return finish(ResultBuilder().value(Value(std::move(ds))).build());
105+
}
106+
70107
Status AppendVerticesExecutor::handleResp(
71108
storage::StorageRpcResponse<storage::cpp2::GetPropResponse> &&rpcResp) {
72109
auto result = handleCompleteness(rpcResp, FLAGS_accept_partial_success);

src/graph/executor/query/AppendVerticesExecutor.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ class AppendVerticesExecutor final : public GetPropExecutor {
2222
folly::Future<Status> execute() override;
2323

2424
private:
25-
DataSet buildRequestDataSet(const AppendVertices *gv);
25+
StatusOr<DataSet> buildRequestDataSet(const AppendVertices *gv);
2626

2727
folly::Future<Status> appendVertices();
2828

2929
Status handleResp(storage::StorageRpcResponse<storage::cpp2::GetPropResponse> &&rpcResp);
3030

31+
Status handleNullProp(const AppendVertices *av);
32+
3133
folly::Future<Status> handleRespMultiJobs(
3234
storage::StorageRpcResponse<storage::cpp2::GetPropResponse> &&rpcResp);
3335

src/graph/executor/query/FilterExecutor.cpp

+43-18
Original file line numberDiff line numberDiff line change
@@ -78,32 +78,57 @@ StatusOr<DataSet> FilterExecutor::handleJob(size_t begin, size_t end, Iterator *
7878

7979
Status FilterExecutor::handleSingleJobFilter() {
8080
auto *filter = asNode<Filter>(node());
81-
Result result = ectx_->getResult(filter->inputVar());
81+
auto inputVar = filter->inputVar();
82+
// Use the userCount of the operator's inputVar at runtime to determine whether concurrent
83+
// read-write conflicts exist, and if so, copy the data
84+
bool canMoveData = movable(inputVar);
85+
Result result = ectx_->getResult(inputVar);
8286
auto *iter = result.iterRef();
83-
87+
// Always reuse getNeighbors's dataset to avoid some go statement execution plan related issues
88+
if (iter->isGetNeighborsIter()) {
89+
canMoveData = true;
90+
}
8491
ResultBuilder builder;
85-
builder.value(result.valuePtr());
8692
QueryExpressionContext ctx(ectx_);
8793
auto condition = filter->condition();
88-
while (iter->valid()) {
89-
auto val = condition->eval(ctx(iter));
90-
if (val.isBadNull() || (!val.empty() && !val.isImplicitBool() && !val.isNull())) {
91-
return Status::Error("Wrong type result, the type should be NULL, EMPTY, BOOL");
92-
}
93-
if (val.empty() || val.isNull() || (val.isImplicitBool() && !val.implicitBool())) {
94-
if (UNLIKELY(filter->needStableFilter())) {
95-
iter->erase();
94+
if (LIKELY(canMoveData)) {
95+
builder.value(result.valuePtr());
96+
while (iter->valid()) {
97+
auto val = condition->eval(ctx(iter));
98+
if (val.isBadNull() || (!val.empty() && !val.isImplicitBool() && !val.isNull())) {
99+
return Status::Error("Wrong type result, the type should be NULL, EMPTY, BOOL");
100+
}
101+
if (val.empty() || val.isNull() || (val.isImplicitBool() && !val.implicitBool())) {
102+
if (UNLIKELY(filter->needStableFilter())) {
103+
iter->erase();
104+
} else {
105+
iter->unstableErase();
106+
}
96107
} else {
97-
iter->unstableErase();
108+
iter->next();
98109
}
99-
} else {
100-
iter->next();
101110
}
102-
}
103111

104-
iter->reset();
105-
builder.iter(std::move(result).iter());
106-
return finish(builder.build());
112+
iter->reset();
113+
builder.iter(std::move(result).iter());
114+
return finish(builder.build());
115+
} else {
116+
DataSet ds;
117+
ds.colNames = result.getColNames();
118+
ds.rows.reserve(iter->size());
119+
for (; iter->valid(); iter->next()) {
120+
auto val = condition->eval(ctx(iter));
121+
if (val.isBadNull() || (!val.empty() && !val.isImplicitBool() && !val.isNull())) {
122+
return Status::Error("Wrong type result, the type should be NULL, EMPTY, BOOL");
123+
}
124+
if (val.isImplicitBool() && val.implicitBool()) {
125+
Row row;
126+
row = *iter->row();
127+
ds.rows.emplace_back(std::move(row));
128+
}
129+
}
130+
return finish(builder.value(Value(std::move(ds))).iter(Iterator::Kind::kProp).build());
131+
}
107132
}
108133

109134
} // namespace graph

src/graph/executor/query/GetEdgesExecutor.cpp

+22-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "graph/executor/query/GetEdgesExecutor.h"
66

77
#include "graph/planner/plan/Query.h"
8+
#include "graph/util/SchemaUtil.h"
89

910
using nebula::storage::StorageClient;
1011
using nebula::storage::StorageRpcResponse;
@@ -17,19 +18,36 @@ folly::Future<Status> GetEdgesExecutor::execute() {
1718
return getEdges();
1819
}
1920

20-
DataSet GetEdgesExecutor::buildRequestDataSet(const GetEdges *ge) {
21+
StatusOr<DataSet> GetEdgesExecutor::buildRequestDataSet(const GetEdges *ge) {
2122
auto valueIter = ectx_->getResult(ge->inputVar()).iter();
2223
QueryExpressionContext exprCtx(qctx()->ectx());
2324

2425
nebula::DataSet edges({kSrc, kType, kRank, kDst});
2526
edges.rows.reserve(valueIter->size());
2627
std::unordered_set<std::tuple<Value, Value, Value, Value>> uniqueEdges;
2728
uniqueEdges.reserve(valueIter->size());
29+
30+
const auto &space = qctx()->rctx()->session()->space();
31+
const auto &vidType = *(space.spaceDesc.vid_type_ref());
2832
for (; valueIter->valid(); valueIter->next()) {
2933
auto type = ge->type()->eval(exprCtx(valueIter.get()));
3034
auto src = ge->src()->eval(exprCtx(valueIter.get()));
3135
auto dst = ge->dst()->eval(exprCtx(valueIter.get()));
3236
auto rank = ge->ranking()->eval(exprCtx(valueIter.get()));
37+
if (!SchemaUtil::isValidVid(src, vidType)) {
38+
std::stringstream ss;
39+
ss << "`" << src.toString() << "', the src should be type of "
40+
<< apache::thrift::util::enumNameSafe(vidType.get_type()) << ", but was`" << src.type()
41+
<< "'";
42+
return Status::Error(ss.str());
43+
}
44+
if (!SchemaUtil::isValidVid(dst, vidType)) {
45+
std::stringstream ss;
46+
ss << "`" << dst.toString() << "', the dst should be type of "
47+
<< apache::thrift::util::enumNameSafe(vidType.get_type()) << ", but was`" << dst.type()
48+
<< "'";
49+
return Status::Error(ss.str());
50+
}
3351
type = type < 0 ? -type : type;
3452
auto edgeKey = std::make_tuple(src, type, rank, dst);
3553
if (ge->dedup() && !uniqueEdges.emplace(std::move(edgeKey)).second) {
@@ -52,7 +70,9 @@ folly::Future<Status> GetEdgesExecutor::getEdges() {
5270
return Status::Error("ptr is nullptr");
5371
}
5472

55-
auto edges = buildRequestDataSet(ge);
73+
auto res = buildRequestDataSet(ge);
74+
NG_RETURN_IF_ERROR(res);
75+
auto edges = std::move(res).value();
5676

5777
if (edges.rows.empty()) {
5878
// TODO: add test for empty input.

src/graph/executor/query/GetEdgesExecutor.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class GetEdgesExecutor final : public GetPropExecutor {
1919
folly::Future<Status> execute() override;
2020

2121
private:
22-
DataSet buildRequestDataSet(const GetEdges *ge);
22+
StatusOr<DataSet> buildRequestDataSet(const GetEdges *ge);
2323

2424
folly::Future<Status> getEdges();
2525
};

0 commit comments

Comments
 (0)