diff --git a/src/graph/service/GraphFlags.cpp b/src/graph/service/GraphFlags.cpp index f34cc55a857..07a65c4b02c 100644 --- a/src/graph/service/GraphFlags.cpp +++ b/src/graph/service/GraphFlags.cpp @@ -105,3 +105,5 @@ DEFINE_uint32( gc_worker_size, 0, "Background garbage clean workers, default number is 0 which means using hardware core size."); + +DEFINE_bool(graph_use_vertex_key, false, "whether allow insert or query the vertex key"); diff --git a/src/graph/service/GraphFlags.h b/src/graph/service/GraphFlags.h index 0160df6c996..6cb54849762 100644 --- a/src/graph/service/GraphFlags.h +++ b/src/graph/service/GraphFlags.h @@ -67,4 +67,7 @@ DECLARE_int32(max_job_size); DECLARE_bool(enable_async_gc); DECLARE_uint32(gc_worker_size); + +DECLARE_bool(graph_use_vertex_key); + #endif // GRAPH_GRAPHFLAGS_H_ diff --git a/src/graph/validator/MutateValidator.cpp b/src/graph/validator/MutateValidator.cpp index d97323f239e..ce16006280d 100644 --- a/src/graph/validator/MutateValidator.cpp +++ b/src/graph/validator/MutateValidator.cpp @@ -46,6 +46,9 @@ Status InsertVerticesValidator::check() { } auto tagItems = sentence->tagItems(); + if (!FLAGS_graph_use_vertex_key && tagItems.empty()) { + return Status::SemanticError("Insert vertex is forbidden, please speicify the tag"); + } schemas_.reserve(tagItems.size()); diff --git a/src/storage/exec/GetPropNode.h b/src/storage/exec/GetPropNode.h index 4f2bf6a495f..9b0be49cbb3 100644 --- a/src/storage/exec/GetPropNode.h +++ b/src/storage/exec/GetPropNode.h @@ -21,7 +21,8 @@ class GetTagPropNode : public QueryNode { std::vector tagNodes, nebula::DataSet* resultDataSet, Expression* filter, - std::size_t limit) + std::size_t limit, + TagContext* tagContext) : context_(context), tagNodes_(std::move(tagNodes)), resultDataSet_(resultDataSet), @@ -29,7 +30,8 @@ class GetTagPropNode : public QueryNode { ? nullptr : new StorageExpressionContext(context->vIdLen(), context->isIntId())), filter_(filter), - limit_(limit) { + limit_(limit), + tagContext_(tagContext) { name_ = "GetTagPropNode"; } @@ -69,7 +71,36 @@ class GetTagPropNode : public QueryNode { } else if (!iter->valid()) { return nebula::cpp2::ErrorCode::SUCCEEDED; } - // if has any tag, will emplace a row with vId + + bool hasValidTag = false; + for (; iter->valid(); iter->next()) { + // check if tag schema exists + auto key = iter->key(); + auto tagId = NebulaKeyUtils::getTagId(context_->vIdLen(), key); + auto schemaIter = tagContext_->schemas_.find(tagId); + if (schemaIter == tagContext_->schemas_.end()) { + continue; + } + // check if ttl expired + auto schemas = &(schemaIter->second); + RowReaderWrapper reader; + reader.reset(*schemas, iter->val()); + if (!reader) { + continue; + } + auto ttl = QueryUtils::getTagTTLInfo(tagContext_, tagId); + if (ttl.has_value() && + CommonUtils::checkDataExpiredForTTL( + schemas->back().get(), reader.get(), ttl.value().first, ttl.value().second)) { + continue; + } + hasValidTag = true; + break; + } + if (!hasValidTag) { + return nebula::cpp2::ErrorCode::SUCCEEDED; + } + // if has any valid tag, will emplace a row with vId } } @@ -131,6 +162,7 @@ class GetTagPropNode : public QueryNode { std::unique_ptr expCtx_{nullptr}; Expression* filter_{nullptr}; const std::size_t limit_{std::numeric_limits::max()}; + TagContext* tagContext_; }; class GetEdgePropNode : public QueryNode { diff --git a/src/storage/query/GetPropProcessor.cpp b/src/storage/query/GetPropProcessor.cpp index 21231ef8217..1c1303a3131 100644 --- a/src/storage/query/GetPropProcessor.cpp +++ b/src/storage/query/GetPropProcessor.cpp @@ -208,7 +208,7 @@ StoragePlan GetPropProcessor::buildTagPlan(RuntimeContext* context, plan.addNode(std::move(tag)); } auto output = std::make_unique( - context, tags, result, filter_ == nullptr ? nullptr : filter_->clone(), limit_); + context, tags, result, filter_ == nullptr ? nullptr : filter_->clone(), limit_, &tagContext_); for (auto* tag : tags) { output->addDependency(tag); } diff --git a/tests/tck/features/delete/DeleteTag.IntVid.feature b/tests/tck/features/delete/DeleteTag.IntVid.feature index 70eadfc8626..1bf23a2d956 100644 --- a/tests/tck/features/delete/DeleteTag.IntVid.feature +++ b/tests/tck/features/delete/DeleteTag.IntVid.feature @@ -161,7 +161,6 @@ Feature: Delete int vid of tag | id | Then drop the used space - @wtf Scenario: delete int vid multiple vertex one tag Given an empty graph And load "nba_int_vid" csv data to a new space diff --git a/tests/tck/features/insert/insertVertexOnly.feature b/tests/tck/features/insert/insertVertexOnly.feature index 29ebff743d9..9419e29e54b 100644 --- a/tests/tck/features/insert/insertVertexOnly.feature +++ b/tests/tck/features/insert/insertVertexOnly.feature @@ -19,6 +19,10 @@ Feature: insert vertex without tag When executing query and retrying it on failure every 6 seconds for 3 times: """ INSERT VERTEX VALUES 1:(),2:(),3:(); + """ + Then a SemanticError should be raised at runtime: Insert vertex is forbidden, please speicify the tag + When executing query: + """ INSERT EDGE e() VALUES 1->2:(),2->3:(); """ Then the execution should be successful diff --git a/tests/tck/features/match/Base.feature b/tests/tck/features/match/Base.feature index 1d0c826ee7d..27348d21ef9 100644 --- a/tests/tck/features/match/Base.feature +++ b/tests/tck/features/match/Base.feature @@ -718,3 +718,46 @@ Feature: Basic match Then the result should be, in any order: | v | | ("Boris Diaw" :player{age: 36, name: "Boris Diaw"}) | + + Scenario: Match with id when all tag is dropped, ent-#1420 + Given an empty graph + And create a space with following options: + | partition_num | 1 | + | replica_factor | 1 | + | vid_type | FIXED_STRING(20) | + And having executed: + """ + CREATE TAG IF NOT EXISTS player(name string, age int); + CREATE TAG IF NOT EXISTS team(name string); + CREATE TAG INDEX IF NOT EXISTS player_index_1 on player(name(10), age); + """ + And wait 5 seconds + When try to execute query: + """ + INSERT VERTEX player() VALUES "v2":(); + INSERT VERTEX player(name, age) VALUES "v3":("v3", 18); + UPSERT VERTEX ON player "v4" SET name = "v4", age = 18; + """ + Then the execution should be successful + When executing query: + """ + MATCH (v) WHERE id(v) in ["v1", "v2", "v3", "v4"] return id(v) limit 10; + """ + Then the result should be, in any order, with relax comparison: + | id(v) | + | "v2" | + | "v3" | + | "v4" | + When try to execute query: + """ + DROP TAG INDEX player_index_1; + DROP TAG player; + """ + Then the execution should be successful + And wait 5 seconds + When executing query: + """ + MATCH (v) WHERE id(v) in ["v1", "v2", "v3", "v4"] return id(v) limit 10; + """ + Then the result should be, in any order, with relax comparison: + | id(v) | diff --git a/tests/tck/features/ttl/TTL.feature b/tests/tck/features/ttl/TTL.feature index f3f74c6c618..a5aaec23196 100644 --- a/tests/tck/features/ttl/TTL.feature +++ b/tests/tck/features/ttl/TTL.feature @@ -393,22 +393,19 @@ Feature: TTLTest FETCH PROP ON person "1" YIELD vertex as node; """ Then the result should be, in any order, with relax comparison: - | node | - | ("1") | + | node | When executing query: """ FETCH PROP ON person "1" YIELD person.id as id """ Then the result should be, in any order: - | id | - | EMPTY | + | id | When executing query: """ FETCH PROP ON * "1" YIELD person.id, career.id """ Then the result should be, in any order: | person.id | career.id | - | EMPTY | EMPTY | When executing query: """ FETCH PROP ON person "2" YIELD person.id @@ -491,6 +488,5 @@ Feature: TTLTest FETCH PROP ON person "1" YIELD person.age as age; """ Then the result should be, in any order: - | age | - | EMPTY | + | age | And drop the used space