diff --git a/src/context/ast/QueryAstContext.h b/src/context/ast/QueryAstContext.h index 90522856ee0042016e4fd5a4598e8c901457fc48..07fc9f06d04c6ba9216fa310c7dede819ca548a9 100644 --- a/src/context/ast/QueryAstContext.h +++ b/src/context/ast/QueryAstContext.h @@ -48,7 +48,7 @@ struct EdgeInfo { MatchStepRange *range{nullptr}; std::vector<EdgeType> edgeTypes; MatchEdge::Direction direction{MatchEdge::Direction::OUT_EDGE}; - std::vector<std::string> types; + std::vector<const std::string*> types; const std::string *alias{nullptr}; const MapExpression *props{nullptr}; Expression *filter{nullptr}; @@ -64,6 +64,8 @@ struct ScanInfo { std::vector<const std::string*> schemaNames; // use for seek by index itself std::vector<IndexID> indexIds; + // use for seek by edge only + MatchEdge::Direction direction{MatchEdge::Direction::OUT_EDGE}; }; struct CypherClauseContextBase : AstContext { @@ -175,6 +177,11 @@ struct EdgeContext final : PatternContext { : PatternContext(PatternKind::kEdge, m), info(i) {} EdgeInfo* info{nullptr}; + + // Output fields + ScanInfo scanInfo; + // initialize start expression in project node + std::unique_ptr<Expression> initialExpr; }; } // namespace graph } // namespace nebula diff --git a/src/planner/match/LabelIndexSeek.cpp b/src/planner/match/LabelIndexSeek.cpp index 46631540935f1704fb39ca6b56ca3fe2082ee584..7aa2ed6848c9f4df045c6c4d6f9c035a348cf8da 100644 --- a/src/planner/match/LabelIndexSeek.cpp +++ b/src/planner/match/LabelIndexSeek.cpp @@ -17,6 +17,7 @@ bool LabelIndexSeek::matchNode(NodeContext* nodeCtx) { // only require the tag if (node.tids.size() != 1) { // TODO multiple tag index seek need the IndexScan support + VLOG(2) << "Multple tag index seek is not supported now."; return false; } @@ -33,9 +34,28 @@ bool LabelIndexSeek::matchNode(NodeContext* nodeCtx) { return true; } -bool LabelIndexSeek::matchEdge(EdgeContext*) { - // TODO - return false; +bool LabelIndexSeek::matchEdge(EdgeContext* edgeCtx) { + const auto &edge = *edgeCtx->info; + // require one edge at least + if (edge.edgeTypes.size() != 1 || edge.range != nullptr) { + // TODO multiple edge index seek need the IndexScan support + VLOG(2) << "Multiple edge index seek and variable length edge seek are not supported now."; + return false; + } + + edgeCtx->scanInfo.schemaIds = edge.edgeTypes; + edgeCtx->scanInfo.schemaNames = edge.types; + + auto indexResult = pickEdgeIndex(edgeCtx); + if (!indexResult.ok()) { + LOG(ERROR) << indexResult.status(); + return false; + } + + edgeCtx->scanInfo.indexIds = std::move(indexResult).value(); + edgeCtx->scanInfo.direction = edge.direction; + + return true; } StatusOr<SubPlan> LabelIndexSeek::transformNode(NodeContext* nodeCtx) { @@ -65,9 +85,65 @@ StatusOr<SubPlan> LabelIndexSeek::transformNode(NodeContext* nodeCtx) { return plan; } -StatusOr<SubPlan> LabelIndexSeek::transformEdge(EdgeContext*) { - // TODO - return Status::Error("TODO"); +StatusOr<SubPlan> LabelIndexSeek::transformEdge(EdgeContext* edgeCtx) { + SubPlan plan; + auto* matchClauseCtx = edgeCtx->matchClauseCtx; + DCHECK_EQ(edgeCtx->scanInfo.indexIds.size(), 1) << "Not supported multiple edge indices seek."; + using IQC = nebula::storage::cpp2::IndexQueryContext; + IQC iqctx; + iqctx.set_index_id(edgeCtx->scanInfo.indexIds.back()); + auto contexts = std::make_unique<std::vector<IQC>>(); + contexts->emplace_back(std::move(iqctx)); + auto columns = std::make_unique<std::vector<std::string>>(); + std::vector<std::string> columnsName; + switch (edgeCtx->scanInfo.direction) { + case MatchEdge::Direction::OUT_EDGE: + columns->emplace_back(kSrc); + columnsName.emplace_back(kVid); + break; + case MatchEdge::Direction::IN_EDGE: + columns->emplace_back(kDst); + columnsName.emplace_back(kVid); + break; + case MatchEdge::Direction::BOTH: + columns->emplace_back(kSrc); + columns->emplace_back(kDst); + columnsName.emplace_back(kSrc); + columnsName.emplace_back(kDst); + break; + } + auto scan = IndexScan::make(matchClauseCtx->qctx, + nullptr, + matchClauseCtx->space.id, + std::move(contexts), + std::move(columns), + true, + edgeCtx->scanInfo.schemaIds.back()); + scan->setColNames(columnsName); + plan.tail = scan; + plan.root = scan; + + if (edgeCtx->scanInfo.direction == MatchEdge::Direction::BOTH) { + // merge the src,dst to one column + auto *yieldColumns = matchClauseCtx->qctx->objPool()->makeAndAdd<YieldColumns>(); + auto *exprList = new ExpressionList(); + exprList->add(new ColumnExpression(0)); // src + exprList->add(new ColumnExpression(1)); // dst + yieldColumns->addColumn(new YieldColumn(new ListExpression(exprList))); + auto *project = Project::make(matchClauseCtx->qctx, + scan, + yieldColumns); + project->setColNames({kVid}); + auto *unwindColumns = matchClauseCtx->qctx->objPool()->makeAndAdd<YieldColumns>(); + unwindColumns->addColumn(new YieldColumn(new ColumnExpression(0))); + auto *unwind = Unwind::make(matchClauseCtx->qctx, project, unwindColumns); + unwind->setColNames({kVid}); + plan.root = unwind; + } + + // initialize start expression in project node + edgeCtx->initialExpr.reset(ExpressionUtils::newVarPropExpr(kVid)); + return plan; } /*static*/ StatusOr<std::vector<IndexID>> LabelIndexSeek::pickTagIndex(const NodeContext* nodeCtx) { @@ -98,5 +174,34 @@ StatusOr<SubPlan> LabelIndexSeek::transformEdge(EdgeContext*) { return indexIds; } +/*static*/ StatusOr<std::vector<IndexID>> +LabelIndexSeek::pickEdgeIndex(const EdgeContext* edgeCtx) { + std::vector<IndexID> indexIds; + const auto* qctx = edgeCtx->matchClauseCtx->qctx; + auto edgeIndexesResult = qctx->indexMng()->getEdgeIndexes(edgeCtx->matchClauseCtx->space.id); + NG_RETURN_IF_ERROR(edgeIndexesResult); + auto edgeIndexes = std::move(edgeIndexesResult).value(); + indexIds.reserve(edgeCtx->scanInfo.schemaIds.size()); + for (std::size_t i = 0; i < edgeCtx->scanInfo.schemaIds.size(); ++i) { + auto edgeId = edgeCtx->scanInfo.schemaIds[i]; + std::shared_ptr<meta::cpp2::IndexItem> candidateIndex{nullptr}; + for (const auto& index : edgeIndexes) { + if (index->get_schema_id().get_edge_type() == edgeId) { + if (candidateIndex == nullptr) { + candidateIndex = index; + } else { + candidateIndex = selectIndex(candidateIndex, index); + } + } + } + if (candidateIndex == nullptr) { + return Status::SemanticError("No valid index for label `%s'.", + edgeCtx->scanInfo.schemaNames[i]->c_str()); + } + indexIds.emplace_back(candidateIndex->get_index_id()); + } + return indexIds; +} + } // namespace graph } // namespace nebula diff --git a/src/planner/match/LabelIndexSeek.h b/src/planner/match/LabelIndexSeek.h index 151b860c161d93e7a21ae901902601d8c37b07a3..211fce137fae0f542c5863b485b86f19322a2e39 100644 --- a/src/planner/match/LabelIndexSeek.h +++ b/src/planner/match/LabelIndexSeek.h @@ -34,6 +34,8 @@ private: static StatusOr<std::vector<IndexID>> pickTagIndex(const NodeContext* nodeCtx); + static StatusOr<std::vector<IndexID>> pickEdgeIndex(const EdgeContext* edgeCtx); + static std::shared_ptr<meta::cpp2::IndexItem> selectIndex( const std::shared_ptr<meta::cpp2::IndexItem> candidate, const std::shared_ptr<meta::cpp2::IndexItem> income) { diff --git a/src/planner/match/MatchClausePlanner.cpp b/src/planner/match/MatchClausePlanner.cpp index 238c73b1a343a0815a7f0ff818f6cc3edfef4e1b..184499ac0ac243411b57837c042dcb5a05f2a1ae 100644 --- a/src/planner/match/MatchClausePlanner.cpp +++ b/src/planner/match/MatchClausePlanner.cpp @@ -81,6 +81,7 @@ Status MatchClausePlanner::findStarts(MatchClauseContext* matchClauseCtx, startFromEdge = true; startIndex = i; foundStart = true; + initialExpr_ = edgeCtx.initialExpr->clone(); break; } } @@ -246,12 +247,7 @@ Status MatchClausePlanner::expandFromEdge(const std::vector<NodeInfo>& nodeInfos MatchClauseContext* matchClauseCtx, size_t startIndex, SubPlan& subplan) { - UNUSED(nodeInfos); - UNUSED(edgeInfos); - UNUSED(matchClauseCtx); - UNUSED(startIndex); - UNUSED(subplan); - return Status::Error("Expand from edge has not been implemented yet."); + return expandFromNode(nodeInfos, edgeInfos, matchClauseCtx, startIndex, subplan); } Status MatchClausePlanner::projectColumnsBySymbols(MatchClauseContext* matchClauseCtx, diff --git a/src/planner/match/MatchSolver.cpp b/src/planner/match/MatchSolver.cpp index ab3863dee68fb02841347e2829526eb189675171..554064107b86a3f417fe4e308cf2f739ef461f0f 100644 --- a/src/planner/match/MatchSolver.cpp +++ b/src/planner/match/MatchSolver.cpp @@ -85,17 +85,26 @@ Expression* MatchSolver::doRewrite(const std::unordered_map<std::string, AliasTy Expression* MatchSolver::makeIndexFilter(const std::string& label, const MapExpression* map, - QueryContext* qctx) { + QueryContext* qctx, + bool isEdgeProperties) { auto& items = map->items(); Expression* root = new RelationalExpression( Expression::Kind::kRelEQ, - new TagPropertyExpression(new std::string(label), new std::string(*items[0].first)), + isEdgeProperties ? + static_cast<Expression*>(new EdgePropertyExpression(new std::string(label), + new std::string(*items[0].first))) : + static_cast<Expression*>(new TagPropertyExpression(new std::string(label), + new std::string(*items[0].first))), items[0].second->clone().release()); for (auto i = 1u; i < items.size(); i++) { auto* left = root; auto* right = new RelationalExpression( Expression::Kind::kRelEQ, - new TagPropertyExpression(new std::string(label), new std::string(*items[i].first)), + isEdgeProperties ? + static_cast<Expression*>(new EdgePropertyExpression(new std::string(label), + new std::string(*items[i].first))) : + static_cast<Expression*>(new TagPropertyExpression(new std::string(label), + new std::string(*items[i].first))), items[i].second->clone().release()); root = new LogicalExpression(Expression::Kind::kLogicalAnd, left, right); } @@ -105,7 +114,8 @@ Expression* MatchSolver::makeIndexFilter(const std::string& label, Expression* MatchSolver::makeIndexFilter(const std::string& label, const std::string& alias, Expression* filter, - QueryContext* qctx) { + QueryContext* qctx, + bool isEdgeProperties) { static const std::unordered_set<Expression::Kind> kinds = { Expression::Kind::kRelEQ, Expression::Kind::kRelLT, @@ -155,10 +165,13 @@ Expression* MatchSolver::makeIndexFilter(const std::string& label, continue; } - const auto& value = la->right()->value(); - auto* tpExpr = - new TagPropertyExpression(new std::string(label), new std::string(value.getStr())); - auto* newConstant = constant->clone().release(); + const auto &value = la->right()->value(); + auto *tpExpr = isEdgeProperties ? + static_cast<Expression*>(new EdgePropertyExpression(new std::string(label), + new std::string(value.getStr()))) : + static_cast<Expression*>(new TagPropertyExpression(new std::string(label), + new std::string(value.getStr()))); + auto *newConstant = constant->clone().release(); if (left->kind() == Expression::Kind::kLabelAttribute) { auto* rel = new RelationalExpression(item->kind(), tpExpr, newConstant); relationals.emplace_back(rel); diff --git a/src/planner/match/MatchSolver.h b/src/planner/match/MatchSolver.h index b57d865bf112a7f707a43895befc06ddbf6bfbe7..ab8bab2c4f66c9b93f869cfa0f41c1cb85089bb7 100644 --- a/src/planner/match/MatchSolver.h +++ b/src/planner/match/MatchSolver.h @@ -35,12 +35,14 @@ public: static Expression* makeIndexFilter(const std::string& label, const MapExpression* map, - QueryContext* qctx); + QueryContext* qctx, + bool isEdgeProperties = false); static Expression* makeIndexFilter(const std::string& label, const std::string& alias, Expression* filter, - QueryContext* qctx); + QueryContext* qctx, + bool isEdgeProperties = false); static void extractAndDedupVidColumn(QueryContext* qctx, Expression* initialExpr, diff --git a/src/planner/match/PropIndexSeek.cpp b/src/planner/match/PropIndexSeek.cpp index 459fb0ee093c6a8e325823e595ce8dd3335d7d3e..fe853537aee6b84a968fe11d0c68f8adfaf5a859 100644 --- a/src/planner/match/PropIndexSeek.cpp +++ b/src/planner/match/PropIndexSeek.cpp @@ -13,19 +13,110 @@ namespace nebula { namespace graph { bool PropIndexSeek::matchEdge(EdgeContext* edgeCtx) { - UNUSED(edgeCtx); - return false; + auto& edge = *edgeCtx->info; + if (edge.types.size() != 1 || edge.range != nullptr) { + // TODO multiple edge index seek need the IndexScan support + VLOG(2) << "Multiple edge index seek and variable length edge seek are not supported now."; + return false; + } + + auto* matchClauseCtx = edgeCtx->matchClauseCtx; + Expression* filter = nullptr; + if (matchClauseCtx->where != nullptr && matchClauseCtx->where->filter != nullptr) { + filter = MatchSolver::makeIndexFilter(*edge.types.back(), + *edge.alias, + matchClauseCtx->where->filter, + matchClauseCtx->qctx, + true); + } + if (filter == nullptr) { + if (edge.props != nullptr && !edge.props->items().empty()) { + filter = MatchSolver::makeIndexFilter(*edge.types.back(), + edge.props, + matchClauseCtx->qctx, + true); + } + } + + if (filter == nullptr) { + return false; + } + + edgeCtx->scanInfo.filter = filter; + edgeCtx->scanInfo.schemaIds = edge.edgeTypes; + edgeCtx->scanInfo.schemaNames = edge.types; + edgeCtx->scanInfo.direction = edge.direction; + + return true; } StatusOr<SubPlan> PropIndexSeek::transformEdge(EdgeContext* edgeCtx) { - UNUSED(edgeCtx); - return Status::Error("Unimplement for edge pattern."); + SubPlan plan; + auto* matchClauseCtx = edgeCtx->matchClauseCtx; + DCHECK_EQ(edgeCtx->scanInfo.schemaIds.size(), 1) << + "Not supported multiple edge properties seek."; + using IQC = nebula::storage::cpp2::IndexQueryContext; + IQC iqctx; + iqctx.set_filter(Expression::encode(*edgeCtx->scanInfo.filter)); + auto contexts = std::make_unique<std::vector<IQC>>(); + contexts->emplace_back(std::move(iqctx)); + auto columns = std::make_unique<std::vector<std::string>>(); + std::vector<std::string> columnsName; + switch (edgeCtx->scanInfo.direction) { + case MatchEdge::Direction::OUT_EDGE: + columns->emplace_back(kSrc); + columnsName.emplace_back(kVid); + break; + case MatchEdge::Direction::IN_EDGE: + columns->emplace_back(kDst); + columnsName.emplace_back(kVid); + break; + case MatchEdge::Direction::BOTH: + columns->emplace_back(kSrc); + columns->emplace_back(kDst); + columnsName.emplace_back(kSrc); + columnsName.emplace_back(kDst); + break; + } + auto scan = IndexScan::make(matchClauseCtx->qctx, + nullptr, + matchClauseCtx->space.id, + std::move(contexts), + std::move(columns), + true, + edgeCtx->scanInfo.schemaIds.back()); + scan->setColNames(columnsName); + plan.tail = scan; + plan.root = scan; + + if (edgeCtx->scanInfo.direction == MatchEdge::Direction::BOTH) { + // merge the src,dst to one column + auto *yieldColumns = matchClauseCtx->qctx->objPool()->makeAndAdd<YieldColumns>(); + auto *exprList = new ExpressionList(); + exprList->add(new ColumnExpression(0)); // src + exprList->add(new ColumnExpression(1)); // dst + yieldColumns->addColumn(new YieldColumn(new ListExpression(exprList))); + auto *project = Project::make(matchClauseCtx->qctx, + scan, + yieldColumns); + project->setColNames({kVid}); + auto *unwindColumns = matchClauseCtx->qctx->objPool()->makeAndAdd<YieldColumns>(); + unwindColumns->addColumn(new YieldColumn(new ColumnExpression(0))); + auto *unwind = Unwind::make(matchClauseCtx->qctx, project, unwindColumns); + unwind->setColNames({kVid}); + plan.root = unwind; + } + + // initialize start expression in project edge + edgeCtx->initialExpr = std::unique_ptr<Expression>(ExpressionUtils::newVarPropExpr(kVid)); + return plan; } bool PropIndexSeek::matchNode(NodeContext* nodeCtx) { auto& node = *nodeCtx->info; if (node.labels.size() != 1) { // TODO multiple tag index seek need the IndexScan support + VLOG(2) << "Multple tag index seek is not supported now."; return false; } diff --git a/src/validator/MatchValidator.cpp b/src/validator/MatchValidator.cpp index 80fdb336b401e292b2adeaa729b219089151c0a7..2a55d403b2d9da1430200c64e86dae2a47baec8e 100644 --- a/src/validator/MatchValidator.cpp +++ b/src/validator/MatchValidator.cpp @@ -249,7 +249,7 @@ Status MatchValidator::buildEdgeInfo(const MatchPath *path, return Status::SemanticError("`%s': Unknown edge type", type->c_str()); } edgeInfos[i].edgeTypes.emplace_back(etype.value()); - edgeInfos[i].types.emplace_back(*type); + edgeInfos[i].types.emplace_back(type.get()); } } else { const auto allEdgesResult = diff --git a/src/validator/test/MatchValidatorTest.cpp b/src/validator/test/MatchValidatorTest.cpp index 4e0c0887feeb3f2bdee9c4791ffae93a19dd0b31..b2cc8cd3e68d3a62cb16f22e89e174dc8bf2e0fc 100644 --- a/src/validator/test/MatchValidatorTest.cpp +++ b/src/validator/test/MatchValidatorTest.cpp @@ -75,6 +75,29 @@ TEST_F(MatchValidatorTest, SeekByTagIndex) { } } +TEST_F(MatchValidatorTest, SeekByEdgeIndex) { + // empty properties index + { + std::string query = "MATCH (v1)-[:like]->(v2) RETURN id(v1), id(v2);"; + std::vector<PlanNode::Kind> expected = {PlanNode::Kind::kProject, + PlanNode::Kind::kFilter, + PlanNode::Kind::kProject, + PlanNode::Kind::kInnerJoin, + PlanNode::Kind::kProject, + PlanNode::Kind::kGetVertices, + PlanNode::Kind::kDedup, + PlanNode::Kind::kProject, + PlanNode::Kind::kFilter, + PlanNode::Kind::kProject, + PlanNode::Kind::kGetNeighbors, + PlanNode::Kind::kDedup, + PlanNode::Kind::kProject, + PlanNode::Kind::kIndexScan, + PlanNode::Kind::kStart}; + EXPECT_TRUE(checkResult(query, expected)); + } +} + TEST_F(MatchValidatorTest, groupby) { { std::string query = "MATCH(n:person)" diff --git a/src/validator/test/MockIndexManager.cpp b/src/validator/test/MockIndexManager.cpp index 2064e31a07fe9fa69d0458158e925d50d19e69bd..b8b840e4c1b4eaa517082590997728f041789e82 100644 --- a/src/validator/test/MockIndexManager.cpp +++ b/src/validator/test/MockIndexManager.cpp @@ -11,6 +11,8 @@ // tag index: // person() // book(name(32)) +// edge index: +// like() namespace nebula { namespace graph { @@ -41,11 +43,22 @@ void MockIndexManager::init() { book_name_index.set_fields({}); book_name_index.fields_ref().value().emplace_back(std::move(field)); + meta::cpp2::IndexItem like_index; + like_index.set_index_id(235); + like_index.set_index_name("like_index"); + meta::cpp2::SchemaID likeSchemaId; + likeSchemaId.set_edge_type(3); + like_index.set_schema_id(std::move(likeSchemaId)); + like_index.set_schema_name("like"); + tagIndexes_.emplace(1, std::vector<std::shared_ptr<meta::cpp2::IndexItem>>{}); tagIndexes_[1].emplace_back( std::make_shared<meta::cpp2::IndexItem>(std::move(person_no_props_index))); tagIndexes_[1].emplace_back( std::make_shared<meta::cpp2::IndexItem>(std::move(book_name_index))); + edgeIndexes_.emplace(1, std::vector<std::shared_ptr<meta::cpp2::IndexItem>>{}); + edgeIndexes_[1].emplace_back( + std::make_shared<meta::cpp2::IndexItem>(std::move(like_index))); } } // namespace graph diff --git a/src/validator/test/MockIndexManager.h b/src/validator/test/MockIndexManager.h index 3bd59812046381ebedb19eca07d4f6d2643e8a82..2a0408fdc3803a0c3a799ec105295daa669a237a 100644 --- a/src/validator/test/MockIndexManager.h +++ b/src/validator/test/MockIndexManager.h @@ -49,8 +49,11 @@ public: } StatusOr<std::vector<std::shared_ptr<IndexItem>>> getEdgeIndexes(GraphSpaceID space) override { - UNUSED(space); - LOG(FATAL) << "Unimplemented"; + auto fd = edgeIndexes_.find(space); + if (fd == edgeIndexes_.end()) { + return Status::Error("No space for index"); + } + return fd->second; } StatusOr<IndexID> toTagIndexID(GraphSpaceID space, std::string tagName) override { @@ -80,6 +83,7 @@ public: private: // index related std::unordered_map<GraphSpaceID, std::vector<std::shared_ptr<IndexItem>>> tagIndexes_; + std::unordered_map<GraphSpaceID, std::vector<std::shared_ptr<IndexItem>>> edgeIndexes_; }; } // namespace graph diff --git a/tests/tck/features/match/Base.IntVid.feature b/tests/tck/features/match/Base.IntVid.feature index 999c9681875d797622d891245f853036c7db96ae..f26b8654bc43299caa1b774953aa57a490510237 100644 --- a/tests/tck/features/match/Base.IntVid.feature +++ b/tests/tck/features/match/Base.IntVid.feature @@ -434,11 +434,6 @@ Feature: Basic match MATCH (v:player{age:23}:bachelor) RETURN v """ Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (v:player{age:23}:bachelor) RETURN v - When executing query: - """ - MATCH () -[r:serve]-> () return * - """ - Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH ()-[r:serve]->() RETURN * When executing query: """ MATCH () -[]-> (v) return * @@ -449,3 +444,13 @@ Feature: Basic match MATCH () --> (v) --> () return * """ Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH ()-->(v)-->() RETURN * + When executing query: + """ + MATCH (p)-[:serve*2..3]->(t) RETURN p + """ + Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (p)-[:serve*2..3]->(t) RETURN p + When executing query: + """ + MATCH (p)-[:serve*2..3{likeness: 90}]->(t) RETURN p + """ + Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (p)-[:serve*2..3{likeness:90}]->(t) RETURN p diff --git a/tests/tck/features/match/Base.feature b/tests/tck/features/match/Base.feature index 1be11df3e72ed74640bf0c1e1f1b14bb44f592c2..88fa10cb8c7985318fe22fce263f5fed52381fce 100644 --- a/tests/tck/features/match/Base.feature +++ b/tests/tck/features/match/Base.feature @@ -478,11 +478,6 @@ Feature: Basic match MATCH (v:player{age:23}:bachelor) RETURN v """ Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (v:player{age:23}:bachelor) RETURN v - When executing query: - """ - MATCH () -[r:serve]-> () return * - """ - Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH ()-[r:serve]->() RETURN * When executing query: """ MATCH () -[]-> (v) return * @@ -493,3 +488,13 @@ Feature: Basic match MATCH () --> (v) --> () return * """ Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH ()-->(v)-->() RETURN * + When executing query: + """ + MATCH (p)-[:serve*2..3]->(t) RETURN p + """ + Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (p)-[:serve*2..3]->(t) RETURN p + When executing query: + """ + MATCH (p)-[:serve*2..3{likeness: 90}]->(t) RETURN p + """ + Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (p)-[:serve*2..3{likeness:90}]->(t) RETURN p diff --git a/tests/tck/features/match/SeekByEdge.feature b/tests/tck/features/match/SeekByEdge.feature new file mode 100644 index 0000000000000000000000000000000000000000..3e00364f3596a3d0bdf13612676103c1433574a4 --- /dev/null +++ b/tests/tck/features/match/SeekByEdge.feature @@ -0,0 +1,937 @@ +Feature: Match seek by edge + Examples: + | space_name | + | nba | + | nba_int_vid | + + Background: Prepare space + Given a graph with space named "<space_name>" + + Scenario: seek by edge index + When executing query: + """ + MATCH (player)-[:serve]->(team) + RETURN player.name, team.name + """ + Then the result should be, in any order: + | player.name | team.name | + | "Amar'e Stoudemire" | "Suns" | + | "Amar'e Stoudemire" | "Knicks" | + | "Amar'e Stoudemire" | "Heat" | + | "Russell Westbrook" | "Thunders" | + | "James Harden" | "Thunders" | + | "James Harden" | "Rockets" | + | "Kobe Bryant" | "Lakers" | + | "Tracy McGrady" | "Raptors" | + | "Tracy McGrady" | "Magic" | + | "Tracy McGrady" | "Rockets" | + | "Tracy McGrady" | "Spurs" | + | "Chris Paul" | "Hornets" | + | "Chris Paul" | "Clippers" | + | "Chris Paul" | "Rockets" | + | "Boris Diaw" | "Hawks" | + | "Boris Diaw" | "Suns" | + | "Boris Diaw" | "Hornets" | + | "Boris Diaw" | "Spurs" | + | "Boris Diaw" | "Jazz" | + | "LeBron James" | "Cavaliers" | + | "LeBron James" | "Heat" | + | "LeBron James" | "Cavaliers" | + | "LeBron James" | "Lakers" | + | "Klay Thompson" | "Warriors" | + | "Kristaps Porzingis" | "Knicks" | + | "Kristaps Porzingis" | "Mavericks" | + | "Jonathon Simmons" | "Spurs" | + | "Jonathon Simmons" | "Magic" | + | "Jonathon Simmons" | "76ers" | + | "Marco Belinelli" | "Warriors" | + | "Marco Belinelli" | "Raptors" | + | "Marco Belinelli" | "Hornets" | + | "Marco Belinelli" | "Bulls" | + | "Marco Belinelli" | "Spurs" | + | "Marco Belinelli" | "Kings" | + | "Marco Belinelli" | "Hornets" | + | "Marco Belinelli" | "Hawks" | + | "Marco Belinelli" | "76ers" | + | "Marco Belinelli" | "Spurs" | + | "Luka Doncic" | "Mavericks" | + | "David West" | "Hornets" | + | "David West" | "Pacers" | + | "David West" | "Spurs" | + | "David West" | "Warriors" | + | "Tony Parker" | "Spurs" | + | "Tony Parker" | "Hornets" | + | "Danny Green" | "Cavaliers" | + | "Danny Green" | "Spurs" | + | "Danny Green" | "Raptors" | + | "Rudy Gay" | "Grizzlies" | + | "Rudy Gay" | "Raptors" | + | "Rudy Gay" | "Kings" | + | "Rudy Gay" | "Spurs" | + | "LaMarcus Aldridge" | "Trail Blazers" | + | "LaMarcus Aldridge" | "Spurs" | + | "Tim Duncan" | "Spurs" | + | "Kevin Durant" | "Thunders" | + | "Kevin Durant" | "Warriors" | + | "Stephen Curry" | "Warriors" | + | "Ray Allen" | "Bucks" | + | "Ray Allen" | "Thunders" | + | "Ray Allen" | "Celtics" | + | "Ray Allen" | "Heat" | + | "Tiago Splitter" | "Spurs" | + | "Tiago Splitter" | "Hawks" | + | "Tiago Splitter" | "76ers" | + | "DeAndre Jordan" | "Clippers" | + | "DeAndre Jordan" | "Mavericks" | + | "DeAndre Jordan" | "Knicks" | + | "Paul Gasol" | "Grizzlies" | + | "Paul Gasol" | "Lakers" | + | "Paul Gasol" | "Bulls" | + | "Paul Gasol" | "Spurs" | + | "Paul Gasol" | "Bucks" | + | "Aron Baynes" | "Spurs" | + | "Aron Baynes" | "Pistons" | + | "Aron Baynes" | "Celtics" | + | "Cory Joseph" | "Spurs" | + | "Cory Joseph" | "Raptors" | + | "Cory Joseph" | "Pacers" | + | "Vince Carter" | "Raptors" | + | "Vince Carter" | "Nets" | + | "Vince Carter" | "Magic" | + | "Vince Carter" | "Suns" | + | "Vince Carter" | "Mavericks" | + | "Vince Carter" | "Grizzlies" | + | "Vince Carter" | "Kings" | + | "Vince Carter" | "Hawks" | + | "Marc Gasol" | "Grizzlies" | + | "Marc Gasol" | "Raptors" | + | "Ricky Rubio" | "Timberwolves" | + | "Ricky Rubio" | "Jazz" | + | "Ben Simmons" | "76ers" | + | "Giannis Antetokounmpo" | "Bucks" | + | "Rajon Rondo" | "Celtics" | + | "Rajon Rondo" | "Mavericks" | + | "Rajon Rondo" | "Kings" | + | "Rajon Rondo" | "Bulls" | + | "Rajon Rondo" | "Pelicans" | + | "Rajon Rondo" | "Lakers" | + | "Manu Ginobili" | "Spurs" | + | "Kyrie Irving" | "Cavaliers" | + | "Kyrie Irving" | "Celtics" | + | "Carmelo Anthony" | "Nuggets" | + | "Carmelo Anthony" | "Knicks" | + | "Carmelo Anthony" | "Thunders" | + | "Carmelo Anthony" | "Rockets" | + | "Dwyane Wade" | "Heat" | + | "Dwyane Wade" | "Bulls" | + | "Dwyane Wade" | "Cavaliers" | + | "Dwyane Wade" | "Heat" | + | "Joel Embiid" | "76ers" | + | "Damian Lillard" | "Trail Blazers" | + | "Yao Ming" | "Rockets" | + | "Kyle Anderson" | "Spurs" | + | "Kyle Anderson" | "Grizzlies" | + | "Dejounte Murray" | "Spurs" | + | "Blake Griffin" | "Clippers" | + | "Blake Griffin" | "Pistons" | + | "Steve Nash" | "Suns" | + | "Steve Nash" | "Mavericks" | + | "Steve Nash" | "Suns" | + | "Steve Nash" | "Lakers" | + | "Jason Kidd" | "Mavericks" | + | "Jason Kidd" | "Suns" | + | "Jason Kidd" | "Nets" | + | "Jason Kidd" | "Mavericks" | + | "Jason Kidd" | "Knicks" | + | "Dirk Nowitzki" | "Mavericks" | + | "Paul George" | "Pacers" | + | "Paul George" | "Thunders" | + | "Grant Hill" | "Pistons" | + | "Grant Hill" | "Magic" | + | "Grant Hill" | "Suns" | + | "Grant Hill" | "Clippers" | + | "Shaquile O'Neal" | "Magic" | + | "Shaquile O'Neal" | "Lakers" | + | "Shaquile O'Neal" | "Heat" | + | "Shaquile O'Neal" | "Suns" | + | "Shaquile O'Neal" | "Cavaliers" | + | "Shaquile O'Neal" | "Celtics" | + | "JaVale McGee" | "Wizards" | + | "JaVale McGee" | "Nuggets" | + | "JaVale McGee" | "Mavericks" | + | "JaVale McGee" | "Warriors" | + | "JaVale McGee" | "Lakers" | + | "Dwight Howard" | "Magic" | + | "Dwight Howard" | "Lakers" | + | "Dwight Howard" | "Rockets" | + | "Dwight Howard" | "Hawks" | + | "Dwight Howard" | "Hornets" | + | "Dwight Howard" | "Wizards" | + When executing query: + """ + MATCH (team)<-[:serve]-(player) + RETURN player.name, team.name + """ + Then the result should be, in any order: + | player.name | team.name | + | "Amar'e Stoudemire" | "Suns" | + | "Amar'e Stoudemire" | "Knicks" | + | "Amar'e Stoudemire" | "Heat" | + | "Russell Westbrook" | "Thunders" | + | "James Harden" | "Thunders" | + | "James Harden" | "Rockets" | + | "Kobe Bryant" | "Lakers" | + | "Tracy McGrady" | "Raptors" | + | "Tracy McGrady" | "Magic" | + | "Tracy McGrady" | "Rockets" | + | "Tracy McGrady" | "Spurs" | + | "Chris Paul" | "Hornets" | + | "Chris Paul" | "Clippers" | + | "Chris Paul" | "Rockets" | + | "Boris Diaw" | "Hawks" | + | "Boris Diaw" | "Suns" | + | "Boris Diaw" | "Hornets" | + | "Boris Diaw" | "Spurs" | + | "Boris Diaw" | "Jazz" | + | "LeBron James" | "Cavaliers" | + | "LeBron James" | "Heat" | + | "LeBron James" | "Cavaliers" | + | "LeBron James" | "Lakers" | + | "Klay Thompson" | "Warriors" | + | "Kristaps Porzingis" | "Knicks" | + | "Kristaps Porzingis" | "Mavericks" | + | "Jonathon Simmons" | "Spurs" | + | "Jonathon Simmons" | "Magic" | + | "Jonathon Simmons" | "76ers" | + | "Marco Belinelli" | "Warriors" | + | "Marco Belinelli" | "Raptors" | + | "Marco Belinelli" | "Hornets" | + | "Marco Belinelli" | "Bulls" | + | "Marco Belinelli" | "Spurs" | + | "Marco Belinelli" | "Kings" | + | "Marco Belinelli" | "Hornets" | + | "Marco Belinelli" | "Hawks" | + | "Marco Belinelli" | "76ers" | + | "Marco Belinelli" | "Spurs" | + | "Luka Doncic" | "Mavericks" | + | "David West" | "Hornets" | + | "David West" | "Pacers" | + | "David West" | "Spurs" | + | "David West" | "Warriors" | + | "Tony Parker" | "Spurs" | + | "Tony Parker" | "Hornets" | + | "Danny Green" | "Cavaliers" | + | "Danny Green" | "Spurs" | + | "Danny Green" | "Raptors" | + | "Rudy Gay" | "Grizzlies" | + | "Rudy Gay" | "Raptors" | + | "Rudy Gay" | "Kings" | + | "Rudy Gay" | "Spurs" | + | "LaMarcus Aldridge" | "Trail Blazers" | + | "LaMarcus Aldridge" | "Spurs" | + | "Tim Duncan" | "Spurs" | + | "Kevin Durant" | "Thunders" | + | "Kevin Durant" | "Warriors" | + | "Stephen Curry" | "Warriors" | + | "Ray Allen" | "Bucks" | + | "Ray Allen" | "Thunders" | + | "Ray Allen" | "Celtics" | + | "Ray Allen" | "Heat" | + | "Tiago Splitter" | "Spurs" | + | "Tiago Splitter" | "Hawks" | + | "Tiago Splitter" | "76ers" | + | "DeAndre Jordan" | "Clippers" | + | "DeAndre Jordan" | "Mavericks" | + | "DeAndre Jordan" | "Knicks" | + | "Paul Gasol" | "Grizzlies" | + | "Paul Gasol" | "Lakers" | + | "Paul Gasol" | "Bulls" | + | "Paul Gasol" | "Spurs" | + | "Paul Gasol" | "Bucks" | + | "Aron Baynes" | "Spurs" | + | "Aron Baynes" | "Pistons" | + | "Aron Baynes" | "Celtics" | + | "Cory Joseph" | "Spurs" | + | "Cory Joseph" | "Raptors" | + | "Cory Joseph" | "Pacers" | + | "Vince Carter" | "Raptors" | + | "Vince Carter" | "Nets" | + | "Vince Carter" | "Magic" | + | "Vince Carter" | "Suns" | + | "Vince Carter" | "Mavericks" | + | "Vince Carter" | "Grizzlies" | + | "Vince Carter" | "Kings" | + | "Vince Carter" | "Hawks" | + | "Marc Gasol" | "Grizzlies" | + | "Marc Gasol" | "Raptors" | + | "Ricky Rubio" | "Timberwolves" | + | "Ricky Rubio" | "Jazz" | + | "Ben Simmons" | "76ers" | + | "Giannis Antetokounmpo" | "Bucks" | + | "Rajon Rondo" | "Celtics" | + | "Rajon Rondo" | "Mavericks" | + | "Rajon Rondo" | "Kings" | + | "Rajon Rondo" | "Bulls" | + | "Rajon Rondo" | "Pelicans" | + | "Rajon Rondo" | "Lakers" | + | "Manu Ginobili" | "Spurs" | + | "Kyrie Irving" | "Cavaliers" | + | "Kyrie Irving" | "Celtics" | + | "Carmelo Anthony" | "Nuggets" | + | "Carmelo Anthony" | "Knicks" | + | "Carmelo Anthony" | "Thunders" | + | "Carmelo Anthony" | "Rockets" | + | "Dwyane Wade" | "Heat" | + | "Dwyane Wade" | "Bulls" | + | "Dwyane Wade" | "Cavaliers" | + | "Dwyane Wade" | "Heat" | + | "Joel Embiid" | "76ers" | + | "Damian Lillard" | "Trail Blazers" | + | "Yao Ming" | "Rockets" | + | "Kyle Anderson" | "Spurs" | + | "Kyle Anderson" | "Grizzlies" | + | "Dejounte Murray" | "Spurs" | + | "Blake Griffin" | "Clippers" | + | "Blake Griffin" | "Pistons" | + | "Steve Nash" | "Suns" | + | "Steve Nash" | "Mavericks" | + | "Steve Nash" | "Suns" | + | "Steve Nash" | "Lakers" | + | "Jason Kidd" | "Mavericks" | + | "Jason Kidd" | "Suns" | + | "Jason Kidd" | "Nets" | + | "Jason Kidd" | "Mavericks" | + | "Jason Kidd" | "Knicks" | + | "Dirk Nowitzki" | "Mavericks" | + | "Paul George" | "Pacers" | + | "Paul George" | "Thunders" | + | "Grant Hill" | "Pistons" | + | "Grant Hill" | "Magic" | + | "Grant Hill" | "Suns" | + | "Grant Hill" | "Clippers" | + | "Shaquile O'Neal" | "Magic" | + | "Shaquile O'Neal" | "Lakers" | + | "Shaquile O'Neal" | "Heat" | + | "Shaquile O'Neal" | "Suns" | + | "Shaquile O'Neal" | "Cavaliers" | + | "Shaquile O'Neal" | "Celtics" | + | "JaVale McGee" | "Wizards" | + | "JaVale McGee" | "Nuggets" | + | "JaVale McGee" | "Mavericks" | + | "JaVale McGee" | "Warriors" | + | "JaVale McGee" | "Lakers" | + | "Dwight Howard" | "Magic" | + | "Dwight Howard" | "Lakers" | + | "Dwight Howard" | "Rockets" | + | "Dwight Howard" | "Hawks" | + | "Dwight Howard" | "Hornets" | + | "Dwight Howard" | "Wizards" | + When executing query: + """ + MATCH (team)-[:serve]-(player) + RETURN player.name, team.name + """ + Then the result should be, in any order: + | player.name | team.name | + | "Heat" | "Amar'e Stoudemire" | + | "Suns" | "Amar'e Stoudemire" | + | "Knicks" | "Amar'e Stoudemire" | + | "Thunders" | "Russell Westbrook" | + | "Rockets" | "James Harden" | + | "Thunders" | "James Harden" | + | "Lakers" | "Kobe Bryant" | + | "Rockets" | "Tracy McGrady" | + | "Spurs" | "Tracy McGrady" | + | "Magic" | "Tracy McGrady" | + | "Raptors" | "Tracy McGrady" | + | "Hornets" | "Chris Paul" | + | "Rockets" | "Chris Paul" | + | "Clippers" | "Chris Paul" | + | "Spurs" | "Boris Diaw" | + | "Hornets" | "Boris Diaw" | + | "Hawks" | "Boris Diaw" | + | "Jazz" | "Boris Diaw" | + | "Suns" | "Boris Diaw" | + | "Heat" | "LeBron James" | + | "Cavaliers" | "LeBron James" | + | "Cavaliers" | "LeBron James" | + | "Lakers" | "LeBron James" | + | "Warriors" | "Klay Thompson" | + | "Knicks" | "Kristaps Porzingis" | + | "Mavericks" | "Kristaps Porzingis" | + | "Magic" | "Jonathon Simmons" | + | "76ers" | "Jonathon Simmons" | + | "Spurs" | "Jonathon Simmons" | + | "Kings" | "Marco Belinelli" | + | "Warriors" | "Marco Belinelli" | + | "Raptors" | "Marco Belinelli" | + | "Hornets" | "Marco Belinelli" | + | "Spurs" | "Marco Belinelli" | + | "76ers" | "Marco Belinelli" | + | "Hawks" | "Marco Belinelli" | + | "Hornets" | "Marco Belinelli" | + | "Spurs" | "Marco Belinelli" | + | "Bulls" | "Marco Belinelli" | + | "Mavericks" | "Luka Doncic" | + | "Hornets" | "David West" | + | "Warriors" | "David West" | + | "Pacers" | "David West" | + | "Spurs" | "David West" | + | "Spurs" | "Tony Parker" | + | "Hornets" | "Tony Parker" | + | "Raptors" | "Danny Green" | + | "Cavaliers" | "Danny Green" | + | "Spurs" | "Danny Green" | + | "Grizzlies" | "Rudy Gay" | + | "Kings" | "Rudy Gay" | + | "Spurs" | "Rudy Gay" | + | "Raptors" | "Rudy Gay" | + | "Spurs" | "LaMarcus Aldridge" | + | "Trail Blazers" | "LaMarcus Aldridge" | + | "Spurs" | "Tim Duncan" | + | "Thunders" | "Kevin Durant" | + | "Warriors" | "Kevin Durant" | + | "Warriors" | "Stephen Curry" | + | "Bucks" | "Ray Allen" | + | "Thunders" | "Ray Allen" | + | "Heat" | "Ray Allen" | + | "Celtics" | "Ray Allen" | + | "76ers" | "Tiago Splitter" | + | "Spurs" | "Tiago Splitter" | + | "Hawks" | "Tiago Splitter" | + | "Clippers" | "DeAndre Jordan" | + | "Mavericks" | "DeAndre Jordan" | + | "Knicks" | "DeAndre Jordan" | + | "Bucks" | "Paul Gasol" | + | "Spurs" | "Paul Gasol" | + | "Grizzlies" | "Paul Gasol" | + | "Bulls" | "Paul Gasol" | + | "Lakers" | "Paul Gasol" | + | "Celtics" | "Aron Baynes" | + | "Pistons" | "Aron Baynes" | + | "Spurs" | "Aron Baynes" | + | "Spurs" | "Cory Joseph" | + | "Raptors" | "Cory Joseph" | + | "Pacers" | "Cory Joseph" | + | "Nets" | "Vince Carter" | + | "Grizzlies" | "Vince Carter" | + | "Raptors" | "Vince Carter" | + | "Hawks" | "Vince Carter" | + | "Suns" | "Vince Carter" | + | "Mavericks" | "Vince Carter" | + | "Magic" | "Vince Carter" | + | "Kings" | "Vince Carter" | + | "Raptors" | "Marc Gasol" | + | "Grizzlies" | "Marc Gasol" | + | "Jazz" | "Ricky Rubio" | + | "Timberwolves" | "Ricky Rubio" | + | "76ers" | "Ben Simmons" | + | "Bucks" | "Giannis Antetokounmpo" | + | "Bulls" | "Rajon Rondo" | + | "Kings" | "Rajon Rondo" | + | "Mavericks" | "Rajon Rondo" | + | "Lakers" | "Rajon Rondo" | + | "Celtics" | "Rajon Rondo" | + | "Pelicans" | "Rajon Rondo" | + | "Spurs" | "Manu Ginobili" | + | "Cavaliers" | "Kyrie Irving" | + | "Celtics" | "Kyrie Irving" | + | "Rockets" | "Carmelo Anthony" | + | "Thunders" | "Carmelo Anthony" | + | "Nuggets" | "Carmelo Anthony" | + | "Knicks" | "Carmelo Anthony" | + | "Bulls" | "Dwyane Wade" | + | "Heat" | "Dwyane Wade" | + | "Cavaliers" | "Dwyane Wade" | + | "Heat" | "Dwyane Wade" | + | "76ers" | "Joel Embiid" | + | "Trail Blazers" | "Damian Lillard" | + | "Rockets" | "Yao Ming" | + | "Spurs" | "Kyle Anderson" | + | "Grizzlies" | "Kyle Anderson" | + | "Spurs" | "Dejounte Murray" | + | "Clippers" | "Blake Griffin" | + | "Pistons" | "Blake Griffin" | + | "Suns" | "Steve Nash" | + | "Suns" | "Steve Nash" | + | "Mavericks" | "Steve Nash" | + | "Lakers" | "Steve Nash" | + | "Mavericks" | "Jason Kidd" | + | "Mavericks" | "Jason Kidd" | + | "Nets" | "Jason Kidd" | + | "Knicks" | "Jason Kidd" | + | "Suns" | "Jason Kidd" | + | "Mavericks" | "Dirk Nowitzki" | + | "Thunders" | "Paul George" | + | "Pacers" | "Paul George" | + | "Suns" | "Grant Hill" | + | "Magic" | "Grant Hill" | + | "Clippers" | "Grant Hill" | + | "Pistons" | "Grant Hill" | + | "Celtics" | "Shaquile O'Neal" | + | "Cavaliers" | "Shaquile O'Neal" | + | "Lakers" | "Shaquile O'Neal" | + | "Magic" | "Shaquile O'Neal" | + | "Suns" | "Shaquile O'Neal" | + | "Heat" | "Shaquile O'Neal" | + | "Warriors" | "JaVale McGee" | + | "Mavericks" | "JaVale McGee" | + | "Wizards" | "JaVale McGee" | + | "Lakers" | "JaVale McGee" | + | "Nuggets" | "JaVale McGee" | + | "Rockets" | "Dwight Howard" | + | "Wizards" | "Dwight Howard" | + | "Magic" | "Dwight Howard" | + | "Hornets" | "Dwight Howard" | + | "Lakers" | "Dwight Howard" | + | "Hawks" | "Dwight Howard" | + | "Vince Carter" | "Nets" | + | "Jason Kidd" | "Nets" | + | "Grant Hill" | "Pistons" | + | "Blake Griffin" | "Pistons" | + | "Aron Baynes" | "Pistons" | + | "Ray Allen" | "Bucks" | + | "Paul Gasol" | "Bucks" | + | "Giannis Antetokounmpo" | "Bucks" | + | "Jason Kidd" | "Mavericks" | + | "Steve Nash" | "Mavericks" | + | "Jason Kidd" | "Mavericks" | + | "Dirk Nowitzki" | "Mavericks" | + | "JaVale McGee" | "Mavericks" | + | "Rajon Rondo" | "Mavericks" | + | "Kristaps Porzingis" | "Mavericks" | + | "Vince Carter" | "Mavericks" | + | "DeAndre Jordan" | "Mavericks" | + | "Luka Doncic" | "Mavericks" | + | "Grant Hill" | "Clippers" | + | "Blake Griffin" | "Clippers" | + | "DeAndre Jordan" | "Clippers" | + | "Chris Paul" | "Clippers" | + | "Russell Westbrook" | "Thunders" | + | "Kevin Durant" | "Thunders" | + | "Carmelo Anthony" | "Thunders" | + | "Ray Allen" | "Thunders" | + | "James Harden" | "Thunders" | + | "Paul George" | "Thunders" | + | "Kobe Bryant" | "Lakers" | + | "Steve Nash" | "Lakers" | + | "Rajon Rondo" | "Lakers" | + | "LeBron James" | "Lakers" | + | "JaVale McGee" | "Lakers" | + | "Dwight Howard" | "Lakers" | + | "Shaquile O'Neal" | "Lakers" | + | "Paul Gasol" | "Lakers" | + | "Ricky Rubio" | "Jazz" | + | "Boris Diaw" | "Jazz" | + | "Carmelo Anthony" | "Nuggets" | + | "JaVale McGee" | "Nuggets" | + | "Dwight Howard" | "Wizards" | + | "JaVale McGee" | "Wizards" | + | "David West" | "Pacers" | + | "Cory Joseph" | "Pacers" | + | "Paul George" | "Pacers" | + | "Ricky Rubio" | "Timberwolves" | + | "Vince Carter" | "Hawks" | + | "Boris Diaw" | "Hawks" | + | "Marco Belinelli" | "Hawks" | + | "Tiago Splitter" | "Hawks" | + | "Dwight Howard" | "Hawks" | + | "Marco Belinelli" | "Warriors" | + | "Klay Thompson" | "Warriors" | + | "JaVale McGee" | "Warriors" | + | "David West" | "Warriors" | + | "Stephen Curry" | "Warriors" | + | "Kevin Durant" | "Warriors" | + | "Jonathon Simmons" | "Magic" | + | "Grant Hill" | "Magic" | + | "Dwight Howard" | "Magic" | + | "Tracy McGrady" | "Magic" | + | "Vince Carter" | "Magic" | + | "Shaquile O'Neal" | "Magic" | + | "Carmelo Anthony" | "Rockets" | + | "Tracy McGrady" | "Rockets" | + | "Dwight Howard" | "Rockets" | + | "Yao Ming" | "Rockets" | + | "James Harden" | "Rockets" | + | "Chris Paul" | "Rockets" | + | "Rajon Rondo" | "Pelicans" | + | "Marc Gasol" | "Raptors" | + | "Vince Carter" | "Raptors" | + | "Danny Green" | "Raptors" | + | "Marco Belinelli" | "Raptors" | + | "Cory Joseph" | "Raptors" | + | "Rudy Gay" | "Raptors" | + | "Tracy McGrady" | "Raptors" | + | "Boris Diaw" | "Spurs" | + | "Kyle Anderson" | "Spurs" | + | "Cory Joseph" | "Spurs" | + | "Tiago Splitter" | "Spurs" | + | "LaMarcus Aldridge" | "Spurs" | + | "Paul Gasol" | "Spurs" | + | "Marco Belinelli" | "Spurs" | + | "Tracy McGrady" | "Spurs" | + | "David West" | "Spurs" | + | "Manu Ginobili" | "Spurs" | + | "Tony Parker" | "Spurs" | + | "Rudy Gay" | "Spurs" | + | "Jonathon Simmons" | "Spurs" | + | "Aron Baynes" | "Spurs" | + | "Danny Green" | "Spurs" | + | "Tim Duncan" | "Spurs" | + | "Marco Belinelli" | "Spurs" | + | "Dejounte Murray" | "Spurs" | + | "LeBron James" | "Heat" | + | "Dwyane Wade" | "Heat" | + | "Ray Allen" | "Heat" | + | "Amar'e Stoudemire" | "Heat" | + | "Dwyane Wade" | "Heat" | + | "Shaquile O'Neal" | "Heat" | + | "Marc Gasol" | "Grizzlies" | + | "Kyle Anderson" | "Grizzlies" | + | "Vince Carter" | "Grizzlies" | + | "Paul Gasol" | "Grizzlies" | + | "Rudy Gay" | "Grizzlies" | + | "Kristaps Porzingis" | "Knicks" | + | "Jason Kidd" | "Knicks" | + | "Carmelo Anthony" | "Knicks" | + | "DeAndre Jordan" | "Knicks" | + | "Amar'e Stoudemire" | "Knicks" | + | "Steve Nash" | "Suns" | + | "Steve Nash" | "Suns" | + | "Grant Hill" | "Suns" | + | "Vince Carter" | "Suns" | + | "Amar'e Stoudemire" | "Suns" | + | "Shaquile O'Neal" | "Suns" | + | "Jason Kidd" | "Suns" | + | "Boris Diaw" | "Suns" | + | "David West" | "Hornets" | + | "Boris Diaw" | "Hornets" | + | "Marco Belinelli" | "Hornets" | + | "Chris Paul" | "Hornets" | + | "Dwight Howard" | "Hornets" | + | "Tony Parker" | "Hornets" | + | "Marco Belinelli" | "Hornets" | + | "LeBron James" | "Cavaliers" | + | "LeBron James" | "Cavaliers" | + | "Dwyane Wade" | "Cavaliers" | + | "Kyrie Irving" | "Cavaliers" | + | "Danny Green" | "Cavaliers" | + | "Shaquile O'Neal" | "Cavaliers" | + | "Marco Belinelli" | "Kings" | + | "Rajon Rondo" | "Kings" | + | "Rudy Gay" | "Kings" | + | "Vince Carter" | "Kings" | + | "Aron Baynes" | "Celtics" | + | "Shaquile O'Neal" | "Celtics" | + | "Kyrie Irving" | "Celtics" | + | "Rajon Rondo" | "Celtics" | + | "Ray Allen" | "Celtics" | + | "Ben Simmons" | "76ers" | + | "Joel Embiid" | "76ers" | + | "Tiago Splitter" | "76ers" | + | "Marco Belinelli" | "76ers" | + | "Jonathon Simmons" | "76ers" | + | "LaMarcus Aldridge" | "Trail Blazers" | + | "Damian Lillard" | "Trail Blazers" | + | "Dwyane Wade" | "Bulls" | + | "Rajon Rondo" | "Bulls" | + | "Paul Gasol" | "Bulls" | + | "Marco Belinelli" | "Bulls" | + When executing query: + """ + MATCH (p1)-[:like]->(player)-[:serve]->(team) + RETURN p1.name, player.name, team.name + """ + Then the result should be, in any order: + | p1.name | player.name | team.name | + | "Amar'e Stoudemire" | "Steve Nash" | "Suns" | + | "Amar'e Stoudemire" | "Steve Nash" | "Lakers" | + | "Amar'e Stoudemire" | "Steve Nash" | "Mavericks" | + | "Amar'e Stoudemire" | "Steve Nash" | "Suns" | + | "Russell Westbrook" | "James Harden" | "Thunders" | + | "Russell Westbrook" | "James Harden" | "Rockets" | + | "Russell Westbrook" | "Paul George" | "Thunders" | + | "Russell Westbrook" | "Paul George" | "Pacers" | + | "James Harden" | "Russell Westbrook" | "Thunders" | + | "Tracy McGrady" | "Rudy Gay" | "Raptors" | + | "Tracy McGrady" | "Rudy Gay" | "Spurs" | + | "Tracy McGrady" | "Rudy Gay" | "Kings" | + | "Tracy McGrady" | "Rudy Gay" | "Grizzlies" | + | "Tracy McGrady" | "Grant Hill" | "Clippers" | + | "Tracy McGrady" | "Grant Hill" | "Magic" | + | "Tracy McGrady" | "Grant Hill" | "Pistons" | + | "Tracy McGrady" | "Grant Hill" | "Suns" | + | "Tracy McGrady" | "Kobe Bryant" | "Lakers" | + | "Chris Paul" | "Dwyane Wade" | "Heat" | + | "Chris Paul" | "Dwyane Wade" | "Cavaliers" | + | "Chris Paul" | "Dwyane Wade" | "Bulls" | + | "Chris Paul" | "Dwyane Wade" | "Heat" | + | "Chris Paul" | "Carmelo Anthony" | "Knicks" | + | "Chris Paul" | "Carmelo Anthony" | "Rockets" | + | "Chris Paul" | "Carmelo Anthony" | "Nuggets" | + | "Chris Paul" | "Carmelo Anthony" | "Thunders" | + | "Chris Paul" | "LeBron James" | "Cavaliers" | + | "Chris Paul" | "LeBron James" | "Lakers" | + | "Chris Paul" | "LeBron James" | "Heat" | + | "Chris Paul" | "LeBron James" | "Cavaliers" | + | "Boris Diaw" | "Tim Duncan" | "Spurs" | + | "Boris Diaw" | "Tony Parker" | "Spurs" | + | "Boris Diaw" | "Tony Parker" | "Hornets" | + | "LeBron James" | "Ray Allen" | "Heat" | + | "LeBron James" | "Ray Allen" | "Celtics" | + | "LeBron James" | "Ray Allen" | "Bucks" | + | "LeBron James" | "Ray Allen" | "Thunders" | + | "Klay Thompson" | "Stephen Curry" | "Warriors" | + | "Kristaps Porzingis" | "Luka Doncic" | "Mavericks" | + | "Marco Belinelli" | "Danny Green" | "Cavaliers" | + | "Marco Belinelli" | "Danny Green" | "Spurs" | + | "Marco Belinelli" | "Danny Green" | "Raptors" | + | "Marco Belinelli" | "Tim Duncan" | "Spurs" | + | "Marco Belinelli" | "Tony Parker" | "Spurs" | + | "Marco Belinelli" | "Tony Parker" | "Hornets" | + | "Luka Doncic" | "James Harden" | "Thunders" | + | "Luka Doncic" | "James Harden" | "Rockets" | + | "Luka Doncic" | "Kristaps Porzingis" | "Knicks" | + | "Luka Doncic" | "Kristaps Porzingis" | "Mavericks" | + | "Luka Doncic" | "Dirk Nowitzki" | "Mavericks" | + | "Tony Parker" | "LaMarcus Aldridge" | "Spurs" | + | "Tony Parker" | "LaMarcus Aldridge" | "Trail Blazers" | + | "Tony Parker" | "Manu Ginobili" | "Spurs" | + | "Tony Parker" | "Tim Duncan" | "Spurs" | + | "Danny Green" | "LeBron James" | "Cavaliers" | + | "Danny Green" | "LeBron James" | "Lakers" | + | "Danny Green" | "LeBron James" | "Heat" | + | "Danny Green" | "LeBron James" | "Cavaliers" | + | "Danny Green" | "Tim Duncan" | "Spurs" | + | "Danny Green" | "Marco Belinelli" | "76ers" | + | "Danny Green" | "Marco Belinelli" | "Warriors" | + | "Danny Green" | "Marco Belinelli" | "Hornets" | + | "Danny Green" | "Marco Belinelli" | "Kings" | + | "Danny Green" | "Marco Belinelli" | "Raptors" | + | "Danny Green" | "Marco Belinelli" | "Bulls" | + | "Danny Green" | "Marco Belinelli" | "Spurs" | + | "Danny Green" | "Marco Belinelli" | "Hornets" | + | "Danny Green" | "Marco Belinelli" | "Spurs" | + | "Danny Green" | "Marco Belinelli" | "Hawks" | + | "Rudy Gay" | "LaMarcus Aldridge" | "Spurs" | + | "Rudy Gay" | "LaMarcus Aldridge" | "Trail Blazers" | + | "LaMarcus Aldridge" | "Tim Duncan" | "Spurs" | + | "LaMarcus Aldridge" | "Tony Parker" | "Spurs" | + | "LaMarcus Aldridge" | "Tony Parker" | "Hornets" | + | "Tim Duncan" | "Manu Ginobili" | "Spurs" | + | "Tim Duncan" | "Tony Parker" | "Spurs" | + | "Tim Duncan" | "Tony Parker" | "Hornets" | + | "Ray Allen" | "Rajon Rondo" | "Mavericks" | + | "Ray Allen" | "Rajon Rondo" | "Kings" | + | "Ray Allen" | "Rajon Rondo" | "Celtics" | + | "Ray Allen" | "Rajon Rondo" | "Pelicans" | + | "Ray Allen" | "Rajon Rondo" | "Lakers" | + | "Ray Allen" | "Rajon Rondo" | "Bulls" | + | "Tiago Splitter" | "Tim Duncan" | "Spurs" | + | "Tiago Splitter" | "Manu Ginobili" | "Spurs" | + | "Paul Gasol" | "Marc Gasol" | "Raptors" | + | "Paul Gasol" | "Marc Gasol" | "Grizzlies" | + | "Paul Gasol" | "Kobe Bryant" | "Lakers" | + | "Aron Baynes" | "Tim Duncan" | "Spurs" | + | "Vince Carter" | "Jason Kidd" | "Nets" | + | "Vince Carter" | "Jason Kidd" | "Suns" | + | "Vince Carter" | "Jason Kidd" | "Mavericks" | + | "Vince Carter" | "Jason Kidd" | "Knicks" | + | "Vince Carter" | "Jason Kidd" | "Mavericks" | + | "Vince Carter" | "Tracy McGrady" | "Spurs" | + | "Vince Carter" | "Tracy McGrady" | "Magic" | + | "Vince Carter" | "Tracy McGrady" | "Rockets" | + | "Vince Carter" | "Tracy McGrady" | "Raptors" | + | "Marc Gasol" | "Paul Gasol" | "Lakers" | + | "Marc Gasol" | "Paul Gasol" | "Grizzlies" | + | "Marc Gasol" | "Paul Gasol" | "Bucks" | + | "Marc Gasol" | "Paul Gasol" | "Spurs" | + | "Marc Gasol" | "Paul Gasol" | "Bulls" | + | "Ben Simmons" | "Joel Embiid" | "76ers" | + | "Rajon Rondo" | "Ray Allen" | "Heat" | + | "Rajon Rondo" | "Ray Allen" | "Celtics" | + | "Rajon Rondo" | "Ray Allen" | "Bucks" | + | "Rajon Rondo" | "Ray Allen" | "Thunders" | + | "Manu Ginobili" | "Tim Duncan" | "Spurs" | + | "Kyrie Irving" | "LeBron James" | "Cavaliers" | + | "Kyrie Irving" | "LeBron James" | "Lakers" | + | "Kyrie Irving" | "LeBron James" | "Heat" | + | "Kyrie Irving" | "LeBron James" | "Cavaliers" | + | "Carmelo Anthony" | "LeBron James" | "Cavaliers" | + | "Carmelo Anthony" | "LeBron James" | "Lakers" | + | "Carmelo Anthony" | "LeBron James" | "Heat" | + | "Carmelo Anthony" | "LeBron James" | "Cavaliers" | + | "Carmelo Anthony" | "Dwyane Wade" | "Heat" | + | "Carmelo Anthony" | "Dwyane Wade" | "Cavaliers" | + | "Carmelo Anthony" | "Dwyane Wade" | "Bulls" | + | "Carmelo Anthony" | "Dwyane Wade" | "Heat" | + | "Carmelo Anthony" | "Chris Paul" | "Hornets" | + | "Carmelo Anthony" | "Chris Paul" | "Clippers" | + | "Carmelo Anthony" | "Chris Paul" | "Rockets" | + | "Dwyane Wade" | "Carmelo Anthony" | "Knicks" | + | "Dwyane Wade" | "Carmelo Anthony" | "Rockets" | + | "Dwyane Wade" | "Carmelo Anthony" | "Nuggets" | + | "Dwyane Wade" | "Carmelo Anthony" | "Thunders" | + | "Dwyane Wade" | "Chris Paul" | "Hornets" | + | "Dwyane Wade" | "Chris Paul" | "Clippers" | + | "Dwyane Wade" | "Chris Paul" | "Rockets" | + | "Dwyane Wade" | "LeBron James" | "Cavaliers" | + | "Dwyane Wade" | "LeBron James" | "Lakers" | + | "Dwyane Wade" | "LeBron James" | "Heat" | + | "Dwyane Wade" | "LeBron James" | "Cavaliers" | + | "Joel Embiid" | "Ben Simmons" | "76ers" | + | "Damian Lillard" | "LaMarcus Aldridge" | "Spurs" | + | "Damian Lillard" | "LaMarcus Aldridge" | "Trail Blazers" | + | "Yao Ming" | "Tracy McGrady" | "Spurs" | + | "Yao Ming" | "Tracy McGrady" | "Magic" | + | "Yao Ming" | "Tracy McGrady" | "Rockets" | + | "Yao Ming" | "Tracy McGrady" | "Raptors" | + | "Yao Ming" | "Shaquile O'Neal" | "Suns" | + | "Yao Ming" | "Shaquile O'Neal" | "Celtics" | + | "Yao Ming" | "Shaquile O'Neal" | "Heat" | + | "Yao Ming" | "Shaquile O'Neal" | "Magic" | + | "Yao Ming" | "Shaquile O'Neal" | "Cavaliers" | + | "Yao Ming" | "Shaquile O'Neal" | "Lakers" | + | "Dejounte Murray" | "Chris Paul" | "Hornets" | + | "Dejounte Murray" | "Chris Paul" | "Clippers" | + | "Dejounte Murray" | "Chris Paul" | "Rockets" | + | "Dejounte Murray" | "LeBron James" | "Cavaliers" | + | "Dejounte Murray" | "LeBron James" | "Lakers" | + | "Dejounte Murray" | "LeBron James" | "Heat" | + | "Dejounte Murray" | "LeBron James" | "Cavaliers" | + | "Dejounte Murray" | "James Harden" | "Thunders" | + | "Dejounte Murray" | "James Harden" | "Rockets" | + | "Dejounte Murray" | "Russell Westbrook" | "Thunders" | + | "Dejounte Murray" | "Marco Belinelli" | "76ers" | + | "Dejounte Murray" | "Marco Belinelli" | "Warriors" | + | "Dejounte Murray" | "Marco Belinelli" | "Hornets" | + | "Dejounte Murray" | "Marco Belinelli" | "Kings" | + | "Dejounte Murray" | "Marco Belinelli" | "Raptors" | + | "Dejounte Murray" | "Marco Belinelli" | "Bulls" | + | "Dejounte Murray" | "Marco Belinelli" | "Spurs" | + | "Dejounte Murray" | "Marco Belinelli" | "Hornets" | + | "Dejounte Murray" | "Marco Belinelli" | "Spurs" | + | "Dejounte Murray" | "Marco Belinelli" | "Hawks" | + | "Dejounte Murray" | "Danny Green" | "Cavaliers" | + | "Dejounte Murray" | "Danny Green" | "Spurs" | + | "Dejounte Murray" | "Danny Green" | "Raptors" | + | "Dejounte Murray" | "Kyle Anderson" | "Spurs" | + | "Dejounte Murray" | "Kyle Anderson" | "Grizzlies" | + | "Dejounte Murray" | "Tim Duncan" | "Spurs" | + | "Dejounte Murray" | "Manu Ginobili" | "Spurs" | + | "Dejounte Murray" | "Tony Parker" | "Spurs" | + | "Dejounte Murray" | "Tony Parker" | "Hornets" | + | "Dejounte Murray" | "Kevin Durant" | "Warriors" | + | "Dejounte Murray" | "Kevin Durant" | "Thunders" | + | "Blake Griffin" | "Chris Paul" | "Hornets" | + | "Blake Griffin" | "Chris Paul" | "Clippers" | + | "Blake Griffin" | "Chris Paul" | "Rockets" | + | "Steve Nash" | "Stephen Curry" | "Warriors" | + | "Steve Nash" | "Amar'e Stoudemire" | "Knicks" | + | "Steve Nash" | "Amar'e Stoudemire" | "Suns" | + | "Steve Nash" | "Amar'e Stoudemire" | "Heat" | + | "Steve Nash" | "Jason Kidd" | "Nets" | + | "Steve Nash" | "Jason Kidd" | "Suns" | + | "Steve Nash" | "Jason Kidd" | "Mavericks" | + | "Steve Nash" | "Jason Kidd" | "Knicks" | + | "Steve Nash" | "Jason Kidd" | "Mavericks" | + | "Steve Nash" | "Dirk Nowitzki" | "Mavericks" | + | "Jason Kidd" | "Steve Nash" | "Suns" | + | "Jason Kidd" | "Steve Nash" | "Lakers" | + | "Jason Kidd" | "Steve Nash" | "Mavericks" | + | "Jason Kidd" | "Steve Nash" | "Suns" | + | "Jason Kidd" | "Dirk Nowitzki" | "Mavericks" | + | "Jason Kidd" | "Vince Carter" | "Hawks" | + | "Jason Kidd" | "Vince Carter" | "Kings" | + | "Jason Kidd" | "Vince Carter" | "Magic" | + | "Jason Kidd" | "Vince Carter" | "Raptors" | + | "Jason Kidd" | "Vince Carter" | "Suns" | + | "Jason Kidd" | "Vince Carter" | "Nets" | + | "Jason Kidd" | "Vince Carter" | "Mavericks" | + | "Jason Kidd" | "Vince Carter" | "Grizzlies" | + | "Dirk Nowitzki" | "Jason Kidd" | "Nets" | + | "Dirk Nowitzki" | "Jason Kidd" | "Suns" | + | "Dirk Nowitzki" | "Jason Kidd" | "Mavericks" | + | "Dirk Nowitzki" | "Jason Kidd" | "Knicks" | + | "Dirk Nowitzki" | "Jason Kidd" | "Mavericks" | + | "Dirk Nowitzki" | "Dwyane Wade" | "Heat" | + | "Dirk Nowitzki" | "Dwyane Wade" | "Cavaliers" | + | "Dirk Nowitzki" | "Dwyane Wade" | "Bulls" | + | "Dirk Nowitzki" | "Dwyane Wade" | "Heat" | + | "Dirk Nowitzki" | "Steve Nash" | "Suns" | + | "Dirk Nowitzki" | "Steve Nash" | "Lakers" | + | "Dirk Nowitzki" | "Steve Nash" | "Mavericks" | + | "Dirk Nowitzki" | "Steve Nash" | "Suns" | + | "Paul George" | "Russell Westbrook" | "Thunders" | + | "Grant Hill" | "Tracy McGrady" | "Spurs" | + | "Grant Hill" | "Tracy McGrady" | "Magic" | + | "Grant Hill" | "Tracy McGrady" | "Rockets" | + | "Grant Hill" | "Tracy McGrady" | "Raptors" | + | "Shaquile O'Neal" | "Tim Duncan" | "Spurs" | + | "Shaquile O'Neal" | "JaVale McGee" | "Lakers" | + | "Shaquile O'Neal" | "JaVale McGee" | "Warriors" | + | "Shaquile O'Neal" | "JaVale McGee" | "Wizards" | + | "Shaquile O'Neal" | "JaVale McGee" | "Nuggets" | + | "Shaquile O'Neal" | "JaVale McGee" | "Mavericks" | + + Scenario: Seek by edge with properties + When executing query: + """ + match (player)-[:serve {start_year : 2001}]->(team) return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + When executing query: + """ + match (team)<-[:serve {start_year : 2001}]-(player) return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + When executing query: + """ + match (player)-[:serve {start_year : 2001}]-(team) return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + | "Grizzlies" | "Paul Gasol" | + | "Nets" | "Jason Kidd" | + When executing query: + """ + match (player)-[s:serve]->(team) where s.start_year == 2001 return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + When executing query: + """ + match (team)<-[s:serve]-(player) where s.start_year == 2001 return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + When executing query: + """ + match (player)-[s:serve]-(team) where s.start_year == 2001 return player.name AS player, team.name AS team + """ + Then the result should be, in any order: + | player | team | + | "Paul Gasol" | "Grizzlies" | + | "Jason Kidd" | "Nets" | + | "Grizzlies" | "Paul Gasol" | + | "Nets" | "Jason Kidd" | + + Scenario: seek by edge without index + When executing query: + """ + MATCH (p1)-[:like]->(p2) + RETURN p1.name, id(p2) + """ + Then a SemanticError should be raised at runtime: Can't solve the start vids from the sentence: MATCH (p1)-[:like]->(p2) RETURN p1.name,id(p2)