Skip to content

Commit

Permalink
delete tag (vesoft-inc#14)
Browse files Browse the repository at this point in the history
* delete tag

* fix missing parser.yy, address @yixinglu's coments

Co-authored-by: Doodle <[email protected]>
  • Loading branch information
nebula-bots and critical27 authored Sep 2, 2021
1 parent 59a2f23 commit fcf2f42
Show file tree
Hide file tree
Showing 18 changed files with 921 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/graph/executor/Executor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ Executor *Executor::makeExecutor(QueryContext *qctx, const PlanNode *node) {
case PlanNode::Kind::kDeleteVertices: {
return pool->add(new DeleteVerticesExecutor(node, qctx));
}
case PlanNode::Kind::kDeleteTags: {
return pool->add(new DeleteTagsExecutor(node, qctx));
}
case PlanNode::Kind::kDeleteEdges: {
return pool->add(new DeleteEdgesExecutor(node, qctx));
}
Expand Down
53 changes: 53 additions & 0 deletions src/graph/executor/mutate/DeleteExecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,59 @@ folly::Future<Status> DeleteVerticesExecutor::deleteVertices() {
});
}

folly::Future<Status> DeleteTagsExecutor::execute() {
SCOPED_TIMER(&execTime_);
return deleteTags();
}

folly::Future<Status> DeleteTagsExecutor::deleteTags() {
auto* dtNode = asNode<DeleteTags>(node());
const auto& spaceInfo = qctx()->rctx()->session()->space();
auto vidRef = dtNode->getVidRef();
DCHECK(vidRef != nullptr);
auto inputVar = dtNode->inputVar();
DCHECK(!inputVar.empty());
auto& inputResult = ectx_->getResult(inputVar);
auto iter = inputResult.iter();

std::vector<storage::cpp2::DelTags> delTags;
delTags.reserve(iter->size());

QueryExpressionContext ctx(ectx_);
for (; iter->valid(); iter->next()) {
storage::cpp2::DelTags delTag;
DCHECK(!iter->row()->empty());
auto val = Expression::eval(vidRef, ctx(iter.get()));
if (val.isNull() || val.empty()) {
VLOG(3) << "NULL or EMPTY vid";
continue;
}
if (!SchemaUtil::isValidVid(val, *spaceInfo.spaceDesc.vid_type_ref())) {
std::stringstream ss;
ss << "Wrong vid type `" << val.type() << "', value `" << val.toString() << "'";
return Status::Error(ss.str());
}
delTag.set_id(val);
delTag.set_tags(dtNode->tagIds());
delTags.emplace_back(std::move(delTag));
}

auto spaceId = spaceInfo.id;
time::Duration deleteTagTime;
return qctx()
->getStorageClient()
->deleteTags(spaceId, std::move(delTags))
.via(runner())
.ensure([deleteTagTime]() {
VLOG(1) << "Delete vertices time: " << deleteTagTime.elapsedInUSec() << "us";
})
.thenValue([this](storage::StorageRpcResponse<storage::cpp2::ExecResponse> resp) {
SCOPED_TIMER(&execTime_);
NG_RETURN_IF_ERROR(handleCompleteness(resp, false));
return Status::OK();
});
}

folly::Future<Status> DeleteEdgesExecutor::execute() { return deleteEdges(); }

folly::Future<Status> DeleteEdgesExecutor::deleteEdges() {
Expand Down
11 changes: 11 additions & 0 deletions src/graph/executor/mutate/DeleteExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ class DeleteVerticesExecutor final : public StorageAccessExecutor {
folly::Future<Status> deleteVertices();
};

class DeleteTagsExecutor final : public StorageAccessExecutor {
public:
DeleteTagsExecutor(const PlanNode *node, QueryContext *qctx)
: StorageAccessExecutor("DeleteTagsExecutor", node, qctx) {}

folly::Future<Status> execute() override;

private:
folly::Future<Status> deleteTags();
};

class DeleteEdgesExecutor final : public StorageAccessExecutor {
public:
DeleteEdgesExecutor(const PlanNode *node, QueryContext *qctx)
Expand Down
8 changes: 8 additions & 0 deletions src/graph/planner/plan/Mutate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ std::unique_ptr<PlanNodeDescription> DeleteVertices::explain() const {
return desc;
}

std::unique_ptr<PlanNodeDescription> DeleteTags::explain() const {
auto desc = SingleInputNode::explain();
addDescription("space", folly::to<std::string>(space_), desc.get());
addDescription("vidRef", vidRef_ ? vidRef_->toString() : "", desc.get());
addDescription("delTags", folly::toJson(util::toJson(tagIds_)), desc.get());
return desc;
}

std::unique_ptr<PlanNodeDescription> DeleteEdges::explain() const {
auto desc = SingleInputNode::explain();
addDescription("space", folly::to<std::string>(space_), desc.get());
Expand Down
35 changes: 35 additions & 0 deletions src/graph/planner/plan/Mutate.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,41 @@ class DeleteVertices final : public SingleInputNode {
Expression* vidRef_{nullptr};
};

class DeleteTags final : public SingleInputNode {
public:
static DeleteTags* make(QueryContext* qctx,
PlanNode* input,
GraphSpaceID spaceId,
Expression* vidRef,
std::vector<TagID> tagIds) {
return qctx->objPool()->add(new DeleteTags(qctx, input, spaceId, vidRef, tagIds));
}

std::unique_ptr<PlanNodeDescription> explain() const override;

GraphSpaceID getSpace() const { return space_; }

Expression* getVidRef() const { return vidRef_; }

const std::vector<TagID>& tagIds() const { return tagIds_; }

private:
DeleteTags(QueryContext* qctx,
PlanNode* input,
GraphSpaceID spaceId,
Expression* vidRef,
std::vector<TagID> tagIds)
: SingleInputNode(qctx, Kind::kDeleteTags, input),
space_(spaceId),
vidRef_(vidRef),
tagIds_(std::move(tagIds)) {}

private:
GraphSpaceID space_;
Expression* vidRef_{nullptr};
std::vector<TagID> tagIds_;
};

class DeleteEdges final : public SingleInputNode {
public:
static DeleteEdges* make(QueryContext* qctx,
Expand Down
2 changes: 2 additions & 0 deletions src/graph/planner/plan/PlanNode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ const char* PlanNode::toString(PlanNode::Kind kind) {
return "InnerJoin";
case Kind::kDeleteVertices:
return "DeleteVertices";
case Kind::kDeleteTags:
return "DeleteTags";
case Kind::kDeleteEdges:
return "DeleteEdges";
case Kind::kUpdateVertex:
Expand Down
1 change: 1 addition & 0 deletions src/graph/planner/plan/PlanNode.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class PlanNode {
kDeleteVertices,
kDeleteEdges,
kUpdateVertex,
kDeleteTags,
kUpdateEdge,

// Show
Expand Down
1 change: 1 addition & 0 deletions src/graph/service/PermissionCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ Status PermissionCheck::permissionCheck(ClientSession *session,
case Sentence::Kind::kInsertEdges:
case Sentence::Kind::kUpdateEdge:
case Sentence::Kind::kDeleteVertices:
case Sentence::Kind::kDeleteTags:
case Sentence::Kind::kDeleteEdges: {
return PermissionManager::canWriteData(session, vctx);
}
Expand Down
75 changes: 75 additions & 0 deletions src/graph/validator/MutateValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,81 @@ Status DeleteVerticesValidator::toPlan() {
return Status::OK();
}

Status DeleteTagsValidator::validateImpl() {
auto sentence = static_cast<DeleteTagsSentence *>(sentence_);
spaceId_ = vctx_->whichSpace().id;

if (sentence->vertices()->isRef()) {
vidRef_ = sentence->vertices()->ref();
auto type = deduceExprType(vidRef_);
NG_RETURN_IF_ERROR(type);
if (type.value() != vidType_) {
std::stringstream ss;
ss << "The vid `" << vidRef_->toString() << "' should be type of `" << vidType_
<< "', but was`" << type.value() << "'";
return Status::SemanticError(ss.str());
}
} else {
auto vIds = sentence->vertices()->vidList();
for (auto vId : vIds) {
auto idStatus = SchemaUtil::toVertexID(vId, vidType_);
NG_RETURN_IF_ERROR(idStatus);
vertices_.emplace_back(std::move(idStatus).value());
}
}

if (!sentence->isAllTag()) {
auto tags = sentence->tags()->labels();
for (const auto &tag : tags) {
auto tagStatus = qctx_->schemaMng()->toTagID(space_.id, *tag);
NG_RETURN_IF_ERROR(tagStatus);
auto tagId = tagStatus.value();
tagIds_.emplace_back(tagId);
}
} else {
const auto allTagsResult = qctx_->schemaMng()->getAllLatestVerTagSchema(space_.id);
NG_RETURN_IF_ERROR(allTagsResult);
const auto allTags = std::move(allTagsResult).value();
for (const auto &tag : allTags) {
tagIds_.emplace_back(tag.first);
}
}
return Status::OK();
}

std::string DeleteTagsValidator::buildVIds() {
auto input = vctx_->anonVarGen()->getVar();
DataSet ds;
ds.colNames.emplace_back(kVid);
for (auto &vid : vertices_) {
Row row;
row.values.emplace_back(vid);
ds.rows.emplace_back(std::move(row));
}
qctx_->ectx()->setResult(input, ResultBuilder().value(Value(std::move(ds))).finish());
auto *pool = qctx_->objPool();
auto *vIds = VariablePropertyExpression::make(pool, input, kVid);
vidRef_ = vIds;
return input;
}

Status DeleteTagsValidator::toPlan() {
std::string vIdVar;
if (!vertices_.empty() && vidRef_ == nullptr) {
vIdVar = buildVIds();
} else if (vidRef_ != nullptr && vidRef_->kind() == Expression::Kind::kVarProperty) {
vIdVar = static_cast<PropertyExpression *>(vidRef_)->sym();
} else if (vidRef_ != nullptr && vidRef_->kind() == Expression::Kind::kInputProperty) {
vIdVar = inputVarName_;
}
auto *dedupNode = Dedup::make(qctx_, nullptr);
dedupNode->setInputVar(vIdVar);
auto *dtNode = DeleteTags::make(qctx_, dedupNode, spaceId_, vidRef_, tagIds_);
root_ = dtNode;
tail_ = dedupNode;
return Status::OK();
}

Status DeleteEdgesValidator::validateImpl() {
auto sentence = static_cast<DeleteEdgesSentence *>(sentence_);
auto spaceId = vctx_->whichSpace().id;
Expand Down
20 changes: 20 additions & 0 deletions src/graph/validator/MutateValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,26 @@ class DeleteVerticesValidator final : public Validator {
std::vector<EdgeKeyRef*> edgeKeyRefs_;
};

class DeleteTagsValidator final : public Validator {
public:
DeleteTagsValidator(Sentence* sentence, QueryContext* context) : Validator(sentence, context) {}

private:
Status validateImpl() override;

std::string buildVIds();

Status toPlan() override;

private:
GraphSpaceID spaceId_{-1};
// From ConstantExpression
std::vector<Value> vertices_;
// From InputPropertyExpression or InputPropertyExpression
Expression* vidRef_{nullptr};
std::vector<TagID> tagIds_;
};

class DeleteEdgesValidator final : public Validator {
public:
DeleteEdgesValidator(Sentence* sentence, QueryContext* context) : Validator(sentence, context) {}
Expand Down
2 changes: 2 additions & 0 deletions src/graph/validator/Validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ std::unique_ptr<Validator> Validator::makeValidator(Sentence* sentence, QueryCon
return std::make_unique<ShowSnapshotsValidator>(sentence, context);
case Sentence::Kind::kDeleteVertices:
return std::make_unique<DeleteVerticesValidator>(sentence, context);
case Sentence::Kind::kDeleteTags:
return std::make_unique<DeleteTagsValidator>(sentence, context);
case Sentence::Kind::kDeleteEdges:
return std::make_unique<DeleteEdgesValidator>(sentence, context);
case Sentence::Kind::kUpdateVertex:
Expand Down
14 changes: 14 additions & 0 deletions src/parser/MutateSentences.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,20 @@ std::string DeleteVerticesSentence::toString() const {
return buf;
}

std::string DeleteTagsSentence::toString() const {
std::string buf;
buf.reserve(256);
buf += "DELETE TAG ";
if (tags_->empty()) {
buf += "*";
} else {
buf += tags_->toString();
}
buf += " FROM ";
buf += vertices_->toString();
return buf;
}

std::string DeleteEdgesSentence::toString() const {
std::string buf;
buf.reserve(256);
Expand Down
39 changes: 39 additions & 0 deletions src/parser/MutateSentences.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,45 @@ class DeleteVerticesSentence final : public Sentence {
std::unique_ptr<VerticesClause> vertices_;
};

class DeleteTagsSentence final : public Sentence {
public:
DeleteTagsSentence(VertexIDList *vidList, NameLabelList *labelList) {
kind_ = Kind::kDeleteTags;
vertices_.reset(new VerticesClause(vidList));
tags_.reset(labelList);
}

explicit DeleteTagsSentence(VertexIDList *vidList) {
kind_ = Kind::kDeleteTags;
vertices_.reset(new VerticesClause(vidList));
tags_ = std::make_unique<NameLabelList>();
}

DeleteTagsSentence(Expression *ref, NameLabelList *labelList) {
kind_ = Kind::kDeleteTags;
vertices_.reset(new VerticesClause(ref));
tags_.reset(labelList);
}

explicit DeleteTagsSentence(Expression *ref) {
kind_ = Kind::kDeleteTags;
vertices_.reset(new VerticesClause(ref));
tags_ = std::make_unique<NameLabelList>();
}

const VerticesClause *vertices() const { return vertices_.get(); }

const NameLabelList *tags() const { return tags_.get(); }

bool isAllTag() { return tags_->empty(); }

std::string toString() const override;

private:
std::unique_ptr<VerticesClause> vertices_;
std::unique_ptr<NameLabelList> tags_;
};

class DeleteEdgesSentence final : public Sentence {
public:
DeleteEdgesSentence(std::string *edge, EdgeKeys *keys) {
Expand Down
1 change: 1 addition & 0 deletions src/parser/Sentence.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Sentence {
kShowTSClients,
kShowFTIndexes,
kDeleteVertices,
kDeleteTags,
kDeleteEdges,
kLookup,
kCreateSpace,
Expand Down
Loading

0 comments on commit fcf2f42

Please sign in to comment.