From 5e05dc67e1309ef5e6d9110920893335b06c7089 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Mon, 18 Mar 2024 15:04:10 +0100 Subject: [PATCH 01/23] Add test --- .../pattern-matching/undirected_edges.test | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/sql/pattern-matching/undirected_edges.test diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test new file mode 100644 index 00000000..07b4de2c --- /dev/null +++ b/test/sql/pattern-matching/undirected_edges.test @@ -0,0 +1,30 @@ +# name: test/sql/sqlpgq/undirected_edges.test +# group: [duckpgq] + +statement ok +pragma enable_verification + +require duckpgq + +statement ok +CREATE TABLE Student(id BIGINT, name VARCHAR);INSERT INTO Student VALUES (0, 'Daniel'), (1, 'Tavneet'), (2, 'Gabor'), (3, 'Peter'), (4, 'David'); + +statement ok +CREATE TABLE know(src BIGINT, dst BIGINT, createDate BIGINT);INSERT INTO know VALUES (0,1, 10), (0,2, 11), (0,3, 12), (3,0, 13), (1,2, 14), (1,3, 15), (2,3, 16), (4,3, 17); + +statement ok +-CREATE PROPERTY GRAPH pg +VERTEX TABLES (Student) +EDGE TABLES ( + know SOURCE KEY ( src ) REFERENCES Student ( id ) + DESTINATION KEY ( dst ) REFERENCES Student ( id ) + ); + +statement ok +-SELECT study.name, study.school +FROM GRAPH_TABLE (pg + MATCH + (a:Person)-[k:knows]-(b:Person) + WHERE a.name = 'Daniel' + COLUMNS (a.name as person, b.name as friend) + ) study; From 64b998986f4ed5a6d4dda76d5a713fbd467ad272 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Mon, 18 Mar 2024 16:18:08 +0100 Subject: [PATCH 02/23] Add first part of union --- .../functions/tablefunctions/match.hpp | 6 +- .../functions/tablefunctions/match.cpp | 97 +++++++++++++++---- .../create_pg/optional_edge_table_clause.test | 7 ++ 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp index 4144d22a..4c31a129 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp @@ -67,7 +67,8 @@ struct PGQMatchFunction : public TableFunction { const string &edge_binding, const string &prev_binding, const string &next_binding, - vector> &conditions); + vector> &conditions, + unique_ptr &from_clause); static void EdgeTypeLeft(const shared_ptr &edge_table, const string &next_table_name, @@ -128,7 +129,8 @@ struct PGQMatchFunction : public TableFunction { const string &prev_binding, const string &next_binding, vector> &conditions, unordered_map &alias_map, - int32_t &extra_alias_counter); + int32_t &extra_alias_counter, + unique_ptr &from_clause); static void ProcessPathList( vector> &path_pattern, diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 74059c53..4541f89a 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -13,6 +13,7 @@ #include "duckdb/parser/expression/constant_expression.hpp" #include "duckdb/parser/expression/comparison_expression.hpp" #include "duckdb/parser/expression/conjunction_expression.hpp" +#include "duckdb/parser/expression/star_expression.hpp" #include "duckdb/parser/query_node/select_node.hpp" @@ -21,8 +22,6 @@ #include "duckdb/parser/property_graph_table.hpp" #include "duckdb/parser/subpath_element.hpp" - -#include #include namespace duckdb { @@ -364,7 +363,26 @@ void PGQMatchFunction::EdgeTypeAny( const shared_ptr &edge_table, const string &edge_binding, const string &prev_binding, const string &next_binding, - vector> &conditions) { + vector> &conditions, + unique_ptr &from_clause) { + + // START SELECT src, dst, * from edge_table + auto src_dst_select_node = make_uniq(); + + auto edge_ref = make_uniq(); + edge_ref->table_name = edge_table->table_name; + src_dst_select_node->from_table = std::move(edge_ref); + auto src_dst_select_statement = make_uniq(); + auto src_ref = make_uniq(edge_table->source_fk, edge_table->table_name); + auto dst_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); + auto star_expr = make_uniq(); + auto src_dst_children = vector>(); + src_dst_children.push_back(std::move(src_ref)); + src_dst_children.push_back(std::move(dst_ref)); + src_dst_children.push_back(std::move(star_expr)); + + // END SELECT src, dst, * from edge_table + // (a) src.key = edge.src auto src_left_expr = CreateMatchJoinExpression( edge_table->source_pk, edge_table->source_fk, prev_binding, edge_binding); @@ -376,22 +394,58 @@ void PGQMatchFunction::EdgeTypeAny( auto combined_left_expr = make_uniq( ExpressionType::CONJUNCTION_AND, std::move(src_left_expr), std::move(dst_left_expr)); - // (c) src.key = edge.dst - auto src_right_expr = CreateMatchJoinExpression(edge_table->source_pk, - edge_table->destination_fk, - prev_binding, edge_binding); - // (d) dst.key = edge.src - auto dst_right_expr = CreateMatchJoinExpression(edge_table->destination_pk, - edge_table->source_fk, - next_binding, edge_binding); - // (c) AND (d) - auto combined_right_expr = make_uniq( - ExpressionType::CONJUNCTION_AND, std::move(src_right_expr), - std::move(dst_right_expr)); - // ((a) AND (b)) OR ((c) AND (d)) + + + // unique_ptr PGQMatchFunction::CreateCountCTESubquery() { + // //! BEGIN OF (SELECT count(cte1.temp) as temp * 0 from cte1) __x + // + // auto temp_cte_select_node = make_uniq(); + // + // auto cte_table_ref = make_uniq(); + // + // cte_table_ref->table_name = "cte1"; + // temp_cte_select_node->from_table = std::move(cte_table_ref); + // vector> children; + // children.push_back(make_uniq("temp", "cte1")); + // + // auto count_function = + // make_uniq("count", std::move(children)); + // + // auto zero = make_uniq(Value::INTEGER((int32_t)0)); + // + // vector> multiply_children; + // + // multiply_children.push_back(std::move(zero)); + // multiply_children.push_back(std::move(count_function)); + // auto multiply_function = + // make_uniq("multiply", std::move(multiply_children)); + // multiply_function->alias = "temp"; + // temp_cte_select_node->select_list.push_back(std::move(multiply_function)); + // auto temp_cte_select_statement = make_uniq(); + // temp_cte_select_statement->node = std::move(temp_cte_select_node); + // + // auto temp_cte_select_subquery = + // make_uniq(std::move(temp_cte_select_statement), "__x"); + // //! END OF (SELECT count(cte1.temp) * 0 as temp from cte1) __x + // return temp_cte_select_subquery; + // } + + // // (c) src.key = edge.dst + // auto src_right_expr = CreateMatchJoinExpression(edge_table->source_pk, + // edge_table->destination_fk, + // prev_binding, edge_binding); + // // (d) dst.key = edge.src + // auto dst_right_expr = CreateMatchJoinExpression(edge_table->destination_pk, + // edge_table->source_fk, + // next_binding, edge_binding); + // // (c) AND (d) + // auto combined_right_expr = make_uniq( + // ExpressionType::CONJUNCTION_AND, std::move(src_right_expr), + // std::move(dst_right_expr)); + // // ((a) AND (b)) OR ((c) AND (d)) auto combined_expr = make_uniq( ExpressionType::CONJUNCTION_OR, std::move(combined_left_expr), - std::move(combined_right_expr)); + std::move(combined_left_expr)); conditions.push_back(std::move(combined_expr)); } @@ -600,12 +654,13 @@ void PGQMatchFunction::AddEdgeJoins( PGQMatchType edge_type, const string &edge_binding, const string &prev_binding, const string &next_binding, vector> &conditions, - unordered_map &alias_map, int32_t &extra_alias_counter) { + unordered_map &alias_map, int32_t &extra_alias_counter, + unique_ptr &from_clause) { switch (edge_type) { case PGQMatchType::MATCH_EDGE_ANY: { select_node->modifiers.push_back(make_uniq()); EdgeTypeAny(edge_table, edge_binding, prev_binding, next_binding, - conditions); + conditions, from_clause); break; } case PGQMatchType::MATCH_EDGE_LEFT: @@ -870,7 +925,7 @@ void PGQMatchFunction::ProcessPathList( edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, - alias_map, extra_alias_counter); + alias_map, extra_alias_counter, from_clause); } } else { // The edge element is a path element without WHERE or path-finding. @@ -883,7 +938,7 @@ void PGQMatchFunction::ProcessPathList( edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, alias_map, - extra_alias_counter); + extra_alias_counter, from_clause); // Check the edge type // If (a)-[b]->(c) -> b.src = a.id AND b.dst = c.id // If (a)<-[b]-(c) -> b.dst = a.id AND b.src = c.id diff --git a/test/sql/create_pg/optional_edge_table_clause.test b/test/sql/create_pg/optional_edge_table_clause.test index feb9cf98..4c7a24e6 100644 --- a/test/sql/create_pg/optional_edge_table_clause.test +++ b/test/sql/create_pg/optional_edge_table_clause.test @@ -3,6 +3,12 @@ require duckpgq +statement error +-CREATE PROPERTY GRAPH snb +VERTEX TABLES (tabledoesnotexist); +---- + + statement ok import database 'duckdb-pgq/data/SNB0.003'; @@ -10,6 +16,7 @@ statement ok -CREATE PROPERTY GRAPH snb VERTEX TABLES (Message, person); + statement ok -FROM GRAPH_TABLE (snb MATCH (m:Message) From 373b95787a0753756a140a76e4a968e822bc437e Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Mon, 18 Mar 2024 16:31:09 +0100 Subject: [PATCH 03/23] Add second part --- .../functions/tablefunctions/match.cpp | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 4541f89a..1dd71e18 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -369,20 +369,40 @@ void PGQMatchFunction::EdgeTypeAny( // START SELECT src, dst, * from edge_table auto src_dst_select_node = make_uniq(); - auto edge_ref = make_uniq(); - edge_ref->table_name = edge_table->table_name; - src_dst_select_node->from_table = std::move(edge_ref); - auto src_dst_select_statement = make_uniq(); - auto src_ref = make_uniq(edge_table->source_fk, edge_table->table_name); - auto dst_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); - auto star_expr = make_uniq(); + auto edge_left_ref = make_uniq(); + edge_left_ref->table_name = edge_table->table_name; + src_dst_select_node->from_table = std::move(edge_left_ref); + auto src_left_ref = make_uniq(edge_table->source_fk, edge_table->table_name); + auto dst_left_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); + auto star_left_expr = make_uniq(); auto src_dst_children = vector>(); - src_dst_children.push_back(std::move(src_ref)); - src_dst_children.push_back(std::move(dst_ref)); - src_dst_children.push_back(std::move(star_expr)); - + src_dst_children.push_back(std::move(src_left_ref)); + src_dst_children.push_back(std::move(dst_left_ref)); + src_dst_children.push_back(std::move(star_left_expr)); + src_dst_select_node->select_list = std::move(src_dst_children); + auto src_dst_select_statement = make_uniq(); + src_dst_select_statement->node = std::move(src_dst_select_node); // END SELECT src, dst, * from edge_table + // START SELECT dst, src, * from edge_table + auto dst_src_select_node = make_uniq(); + + auto edge_right_ref = make_uniq(); + edge_right_ref->table_name = edge_table->table_name; + dst_src_select_node->from_table = std::move(edge_right_ref); + auto src_right_ref = make_uniq(edge_table->source_fk, edge_table->table_name); + auto dst_right_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); + auto star_right_expr = make_uniq(); + auto dst_src_children = vector>(); + dst_src_children.push_back(std::move(src_right_ref)); + dst_src_children.push_back(std::move(dst_right_ref)); + dst_src_children.push_back(std::move(star_right_expr)); + dst_src_select_node->select_list = std::move(dst_src_children); + auto dst_src_select_statement = make_uniq(); + src_dst_select_statement->node = std::move(src_dst_select_node); + // END SELECT dst, src, * from edge_table + + // (a) src.key = edge.src auto src_left_expr = CreateMatchJoinExpression( edge_table->source_pk, edge_table->source_fk, prev_binding, edge_binding); From fd4f6d5c5bedf415a3617c2bd977f9db74990648 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Mon, 18 Mar 2024 16:36:38 +0100 Subject: [PATCH 04/23] Add union node --- .../functions/tablefunctions/match.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 1dd71e18..c738a96c 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -15,6 +15,8 @@ #include "duckdb/parser/expression/conjunction_expression.hpp" #include "duckdb/parser/expression/star_expression.hpp" +#include "duckdb/parser/query_node/set_operation_node.hpp" + #include "duckdb/parser/query_node/select_node.hpp" #include "duckdb/common/enums/subquery_type.hpp" @@ -23,6 +25,7 @@ #include "duckdb/parser/property_graph_table.hpp" #include "duckdb/parser/subpath_element.hpp" #include +#include namespace duckdb { shared_ptr @@ -390,18 +393,28 @@ void PGQMatchFunction::EdgeTypeAny( auto edge_right_ref = make_uniq(); edge_right_ref->table_name = edge_table->table_name; dst_src_select_node->from_table = std::move(edge_right_ref); + auto dst_right_ref = make_uniq( + edge_table->destination_fk, edge_table->table_name); auto src_right_ref = make_uniq(edge_table->source_fk, edge_table->table_name); - auto dst_right_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); auto star_right_expr = make_uniq(); auto dst_src_children = vector>(); - dst_src_children.push_back(std::move(src_right_ref)); dst_src_children.push_back(std::move(dst_right_ref)); + dst_src_children.push_back(std::move(src_right_ref)); dst_src_children.push_back(std::move(star_right_expr)); dst_src_select_node->select_list = std::move(dst_src_children); auto dst_src_select_statement = make_uniq(); - src_dst_select_statement->node = std::move(src_dst_select_node); + dst_src_select_statement->node = std::move(dst_src_select_node); // END SELECT dst, src, * from edge_table + auto union_node = make_uniq(); + union_node->setop_type = SetOperationType::UNION; + union_node->setop_all = true; + union_node->left = std::move(src_dst_select_node); + union_node->right = std::move(dst_src_select_node); + + auto union_subquery = make_uniq(); + union_subquery->subquery = std::move(union_node); + // (a) src.key = edge.src auto src_left_expr = CreateMatchJoinExpression( From d8b0e07f49a5cddb835bc31cf31797c0de30216d Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Mon, 18 Mar 2024 16:42:26 +0100 Subject: [PATCH 05/23] Add subquery ref --- .../functions/tablefunctions/match.cpp | 66 ++++--------------- 1 file changed, 12 insertions(+), 54 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index c738a96c..0a648e4d 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -411,11 +411,20 @@ void PGQMatchFunction::EdgeTypeAny( union_node->setop_all = true; union_node->left = std::move(src_dst_select_node); union_node->right = std::move(dst_src_select_node); + auto union_select = make_uniq(); + union_select->node = std::move(union_node); auto union_subquery = make_uniq(); - union_subquery->subquery = std::move(union_node); - + union_subquery->subquery = std::move(union_select); + if (from_clause) { + auto from_join = make_uniq(JoinRefType::CROSS); + from_join->left = std::move(from_clause); + from_join->right = std::move(union_subquery); + from_clause = std::move(from_join); + } else { + from_clause = std::move(union_subquery); + } // (a) src.key = edge.src auto src_left_expr = CreateMatchJoinExpression( edge_table->source_pk, edge_table->source_fk, prev_binding, edge_binding); @@ -428,58 +437,7 @@ void PGQMatchFunction::EdgeTypeAny( ExpressionType::CONJUNCTION_AND, std::move(src_left_expr), std::move(dst_left_expr)); - - // unique_ptr PGQMatchFunction::CreateCountCTESubquery() { - // //! BEGIN OF (SELECT count(cte1.temp) as temp * 0 from cte1) __x - // - // auto temp_cte_select_node = make_uniq(); - // - // auto cte_table_ref = make_uniq(); - // - // cte_table_ref->table_name = "cte1"; - // temp_cte_select_node->from_table = std::move(cte_table_ref); - // vector> children; - // children.push_back(make_uniq("temp", "cte1")); - // - // auto count_function = - // make_uniq("count", std::move(children)); - // - // auto zero = make_uniq(Value::INTEGER((int32_t)0)); - // - // vector> multiply_children; - // - // multiply_children.push_back(std::move(zero)); - // multiply_children.push_back(std::move(count_function)); - // auto multiply_function = - // make_uniq("multiply", std::move(multiply_children)); - // multiply_function->alias = "temp"; - // temp_cte_select_node->select_list.push_back(std::move(multiply_function)); - // auto temp_cte_select_statement = make_uniq(); - // temp_cte_select_statement->node = std::move(temp_cte_select_node); - // - // auto temp_cte_select_subquery = - // make_uniq(std::move(temp_cte_select_statement), "__x"); - // //! END OF (SELECT count(cte1.temp) * 0 as temp from cte1) __x - // return temp_cte_select_subquery; - // } - - // // (c) src.key = edge.dst - // auto src_right_expr = CreateMatchJoinExpression(edge_table->source_pk, - // edge_table->destination_fk, - // prev_binding, edge_binding); - // // (d) dst.key = edge.src - // auto dst_right_expr = CreateMatchJoinExpression(edge_table->destination_pk, - // edge_table->source_fk, - // next_binding, edge_binding); - // // (c) AND (d) - // auto combined_right_expr = make_uniq( - // ExpressionType::CONJUNCTION_AND, std::move(src_right_expr), - // std::move(dst_right_expr)); - // // ((a) AND (b)) OR ((c) AND (d)) - auto combined_expr = make_uniq( - ExpressionType::CONJUNCTION_OR, std::move(combined_left_expr), - std::move(combined_left_expr)); - conditions.push_back(std::move(combined_expr)); + conditions.push_back(std::move(combined_left_expr)); } void PGQMatchFunction::EdgeTypeLeft( From 1ec22275c0ddb167bbdf9d12cf335143089c6016 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 10:17:03 +0100 Subject: [PATCH 06/23] Fix errors --- .../functions/tablefunctions/match.cpp | 36 +++++++++---------- .../pattern-matching/undirected_edges.test | 7 ++-- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 0a648e4d..3bfea5e5 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -375,16 +375,14 @@ void PGQMatchFunction::EdgeTypeAny( auto edge_left_ref = make_uniq(); edge_left_ref->table_name = edge_table->table_name; src_dst_select_node->from_table = std::move(edge_left_ref); - auto src_left_ref = make_uniq(edge_table->source_fk, edge_table->table_name); - auto dst_left_ref = make_uniq(edge_table->destination_fk, edge_table->table_name); + auto src_left_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); + auto dst_left_ref = make_uniq(edge_table->destination_fk[0], edge_table->table_name); auto star_left_expr = make_uniq(); auto src_dst_children = vector>(); src_dst_children.push_back(std::move(src_left_ref)); src_dst_children.push_back(std::move(dst_left_ref)); src_dst_children.push_back(std::move(star_left_expr)); src_dst_select_node->select_list = std::move(src_dst_children); - auto src_dst_select_statement = make_uniq(); - src_dst_select_statement->node = std::move(src_dst_select_node); // END SELECT src, dst, * from edge_table // START SELECT dst, src, * from edge_table @@ -394,16 +392,14 @@ void PGQMatchFunction::EdgeTypeAny( edge_right_ref->table_name = edge_table->table_name; dst_src_select_node->from_table = std::move(edge_right_ref); auto dst_right_ref = make_uniq( - edge_table->destination_fk, edge_table->table_name); - auto src_right_ref = make_uniq(edge_table->source_fk, edge_table->table_name); + edge_table->destination_fk[0], edge_table->table_name); + auto src_right_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); auto star_right_expr = make_uniq(); auto dst_src_children = vector>(); dst_src_children.push_back(std::move(dst_right_ref)); dst_src_children.push_back(std::move(src_right_ref)); dst_src_children.push_back(std::move(star_right_expr)); dst_src_select_node->select_list = std::move(dst_src_children); - auto dst_src_select_statement = make_uniq(); - dst_src_select_statement->node = std::move(dst_src_select_node); // END SELECT dst, src, * from edge_table auto union_node = make_uniq(); @@ -413,10 +409,9 @@ void PGQMatchFunction::EdgeTypeAny( union_node->right = std::move(dst_src_select_node); auto union_select = make_uniq(); union_select->node = std::move(union_node); - - auto union_subquery = make_uniq(); - union_subquery->subquery = std::move(union_select); - + // (SELECT src, dst, * from edge_table UNION ALL SELECT dst, src, * from edge_table UNION ALL) + auto union_subquery = make_uniq(std::move(union_select)); + union_subquery->alias = edge_binding; if (from_clause) { auto from_join = make_uniq(JoinRefType::CROSS); from_join->left = std::move(from_clause); @@ -647,6 +642,9 @@ void PGQMatchFunction::AddEdgeJoins( vector> &conditions, unordered_map &alias_map, int32_t &extra_alias_counter, unique_ptr &from_clause) { + if (edge_type != PGQMatchType::MATCH_EDGE_ANY) { + alias_map[edge_binding] = edge_table->table_name; + } switch (edge_type) { case PGQMatchType::MATCH_EDGE_ANY: { select_node->modifiers.push_back(make_uniq()); @@ -923,21 +921,19 @@ void PGQMatchFunction::ProcessPathList( auto edge_table = FindGraphTable(edge_element->label, pg_table); CheckInheritance(edge_table, edge_element, conditions); // check aliases - alias_map[edge_element->variable_binding] = edge_table->table_name; AddEdgeJoins(select_node, edge_table, previous_vertex_table, next_vertex_table, edge_element->match_type, edge_element->variable_binding, previous_vertex_element->variable_binding, - next_vertex_element->variable_binding, conditions, alias_map, - extra_alias_counter, from_clause); + next_vertex_element->variable_binding, conditions, + alias_map, extra_alias_counter, from_clause); // Check the edge type // If (a)-[b]->(c) -> b.src = a.id AND b.dst = c.id // If (a)<-[b]-(c) -> b.dst = a.id AND b.src = c.id - // If (a)-[b]-(c) -> (b.src = a.id AND b.dst = c.id) OR - // (b.dst = a.id AND b.src - // = c.id) If (a)<-[b]->(c) -> (b.src = a.id AND b.dst = c.id) AND - // (b.dst = a.id AND b.src - //= c.id) + // If (a)-[b]-(c) -> (b.src = a.id AND b.dst = c.id) + // FROM (src, dst, * from b UNION ALL dst, src, * from b) + // If (a)<-[b]->(c) -> (b.src = a.id AND b.dst = c.id) AND + // (b.dst = a.id AND b.src = c.id) } previous_vertex_element = next_vertex_element; previous_vertex_table = next_vertex_table; diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index 07b4de2c..a4691cd9 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -21,10 +21,9 @@ EDGE TABLES ( ); statement ok --SELECT study.name, study.school -FROM GRAPH_TABLE (pg +-FROM GRAPH_TABLE (pg MATCH - (a:Person)-[k:knows]-(b:Person) + (a:Student)-[k:know]-(b:Student) WHERE a.name = 'Daniel' COLUMNS (a.name as person, b.name as friend) - ) study; + ); From 0374011239f5f60e32305640ebcecffec9926dc5 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 10:30:58 +0100 Subject: [PATCH 07/23] Disable star expression --- duckpgq/src/duckpgq/functions/tablefunctions/match.cpp | 10 +++++----- test/sql/pattern-matching/undirected_edges.test | 9 +++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 3bfea5e5..70ad3fe5 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -377,11 +377,11 @@ void PGQMatchFunction::EdgeTypeAny( src_dst_select_node->from_table = std::move(edge_left_ref); auto src_left_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); auto dst_left_ref = make_uniq(edge_table->destination_fk[0], edge_table->table_name); - auto star_left_expr = make_uniq(); + // auto star_left_expr = make_uniq(); auto src_dst_children = vector>(); src_dst_children.push_back(std::move(src_left_ref)); src_dst_children.push_back(std::move(dst_left_ref)); - src_dst_children.push_back(std::move(star_left_expr)); + // src_dst_children.push_back(std::move(star_left_expr)); src_dst_select_node->select_list = std::move(src_dst_children); // END SELECT src, dst, * from edge_table @@ -394,11 +394,11 @@ void PGQMatchFunction::EdgeTypeAny( auto dst_right_ref = make_uniq( edge_table->destination_fk[0], edge_table->table_name); auto src_right_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); - auto star_right_expr = make_uniq(); + // auto star_right_expr = make_uniq(); auto dst_src_children = vector>(); dst_src_children.push_back(std::move(dst_right_ref)); dst_src_children.push_back(std::move(src_right_ref)); - dst_src_children.push_back(std::move(star_right_expr)); + // dst_src_children.push_back(std::move(star_right_expr)); dst_src_select_node->select_list = std::move(dst_src_children); // END SELECT dst, src, * from edge_table @@ -1047,7 +1047,7 @@ PGQMatchFunction::MatchBindReplace(ClientContext &context, subquery->node = std::move(select_node); auto result = make_uniq(std::move(subquery), ref->alias); - + result->Print(); return std::move(result); } } // namespace duckdb diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index a4691cd9..ce5724c8 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -10,7 +10,7 @@ statement ok CREATE TABLE Student(id BIGINT, name VARCHAR);INSERT INTO Student VALUES (0, 'Daniel'), (1, 'Tavneet'), (2, 'Gabor'), (3, 'Peter'), (4, 'David'); statement ok -CREATE TABLE know(src BIGINT, dst BIGINT, createDate BIGINT);INSERT INTO know VALUES (0,1, 10), (0,2, 11), (0,3, 12), (3,0, 13), (1,2, 14), (1,3, 15), (2,3, 16), (4,3, 17); +CREATE TABLE know(src BIGINT, dst BIGINT, createDate BIGINT);INSERT INTO know VALUES (0,1, 10), (0,2, 11), (0,3, 12), (3,0, 13), (1,2, 14), (1,3, 15), (2,3, 16), (4,3, 17), (4, 0, 18); statement ok -CREATE PROPERTY GRAPH pg @@ -20,10 +20,15 @@ EDGE TABLES ( DESTINATION KEY ( dst ) REFERENCES Student ( id ) ); -statement ok +query II -FROM GRAPH_TABLE (pg MATCH (a:Student)-[k:know]-(b:Student) WHERE a.name = 'Daniel' COLUMNS (a.name as person, b.name as friend) ); +---- +Daniel Tavneet +Daniel Peter +Daniel David +Daniel Gabor \ No newline at end of file From d0bbf206c05a3868de6fe257efcefc8b46175fe1 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 11:39:47 +0100 Subject: [PATCH 08/23] Remove unneeded --- .../functions/tablefunctions/create_property_graph.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp index b642ef82..8692893a 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp @@ -8,7 +8,6 @@ #pragma once #include "duckdb/function/table_function.hpp" -#include "duckdb/parser/statement/create_statement.hpp" #include "duckdb/parser/parsed_data/create_property_graph_info.hpp" #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" @@ -23,14 +22,14 @@ class CreatePropertyGraphFunction : public TableFunction { function = CreatePropertyGraphFunc; } - struct CreatePropertyGraphBindData : public TableFunctionData { + struct CreatePropertyGraphBindData : TableFunctionData { explicit CreatePropertyGraphBindData(CreatePropertyGraphInfo *pg_info) : create_pg_info(pg_info) {} CreatePropertyGraphInfo *create_pg_info; }; - struct CreatePropertyGraphGlobalData : public GlobalTableFunctionState { + struct CreatePropertyGraphGlobalData : GlobalTableFunctionState { CreatePropertyGraphGlobalData() = default; }; @@ -42,12 +41,12 @@ class CreatePropertyGraphFunction : public TableFunction { CheckPropertyGraphTableColumns(const shared_ptr &pg_table, TableCatalogEntry &table); - static duckdb::unique_ptr + static unique_ptr CreatePropertyGraphBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names); - static duckdb::unique_ptr + static unique_ptr CreatePropertyGraphInit(ClientContext &context, TableFunctionInitInput &input); From da2a0024f93d98698036d288419f2cd37e751f9e Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 11:40:38 +0100 Subject: [PATCH 09/23] Move the include statement --- .../functions/tablefunctions/create_property_graph.hpp | 4 ++-- .../functions/tablefunctions/create_property_graph.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp index 8692893a..20f8c96a 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/create_property_graph.hpp @@ -22,14 +22,14 @@ class CreatePropertyGraphFunction : public TableFunction { function = CreatePropertyGraphFunc; } - struct CreatePropertyGraphBindData : TableFunctionData { + struct CreatePropertyGraphBindData : public TableFunctionData { explicit CreatePropertyGraphBindData(CreatePropertyGraphInfo *pg_info) : create_pg_info(pg_info) {} CreatePropertyGraphInfo *create_pg_info; }; - struct CreatePropertyGraphGlobalData : GlobalTableFunctionState { + struct CreatePropertyGraphGlobalData : public GlobalTableFunctionState { CreatePropertyGraphGlobalData() = default; }; diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp index 53d6da40..1a0b95fe 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp @@ -1,4 +1,5 @@ #include "duckpgq/functions/tablefunctions/create_property_graph.hpp" +#include "duckdb/parser/statement/create_statement.hpp" #include namespace duckdb { From 0b4559ad727d6f91798ef946c54c03e1717a68c7 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 11:41:30 +0100 Subject: [PATCH 10/23] Change c style cast --- .../duckpgq/functions/tablefunctions/create_property_graph.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp index 1a0b95fe..c1949460 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/create_property_graph.cpp @@ -67,7 +67,7 @@ CreatePropertyGraphFunction::CreatePropertyGraphBind( throw Exception(ExceptionType::INVALID, "Registered DuckPGQ state not found"); } - const auto duckpgq_state = (DuckPGQState *)lookup->second.get(); + const auto duckpgq_state = dynamic_cast(lookup->second.get()); const auto duckpgq_parse_data = dynamic_cast(duckpgq_state->parse_data.get()); From bedfe1e81369b976d6dfe1c586bd44d3eede02fe Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 12:56:29 +0100 Subject: [PATCH 11/23] Move import statement --- duckpgq/src/duckpgq_extension.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/duckpgq/src/duckpgq_extension.cpp b/duckpgq/src/duckpgq_extension.cpp index a74bd6e2..b25808a1 100644 --- a/duckpgq/src/duckpgq_extension.cpp +++ b/duckpgq/src/duckpgq_extension.cpp @@ -16,6 +16,7 @@ #include "duckdb/parser/parsed_data/create_table_function_info.hpp" #include "duckdb/parser/query_node/select_node.hpp" #include "duckdb/parser/statement/copy_statement.hpp" +#include "duckdb/parser/statement/create_statement.hpp" #include "duckdb/parser/parsed_data/create_table_info.hpp" #include "duckdb/parser/tableref/joinref.hpp" From dde62eb23728598cdf211c9a01af6d2537959bbb Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 13:36:26 +0100 Subject: [PATCH 12/23] Update expected results --- test/sql/pattern-matching/undirected_edges.test | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index ce5724c8..7571c14e 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -20,6 +20,7 @@ EDGE TABLES ( DESTINATION KEY ( dst ) REFERENCES Student ( id ) ); +# Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples query II -FROM GRAPH_TABLE (pg MATCH @@ -29,6 +30,7 @@ query II ); ---- Daniel Tavneet +Daniel Gabor Daniel Peter Daniel David -Daniel Gabor \ No newline at end of file +Daniel Peter \ No newline at end of file From 9b806c5dc6e1bf97be991a8e214e72b9844541b6 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 14:18:53 +0100 Subject: [PATCH 13/23] Add --- .../functions/tablefunctions/match.cpp | 44 ++++++++++++------- .../pattern-matching/undirected_edges.test | 11 +++++ 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 70ad3fe5..a1c22696 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -375,13 +375,18 @@ void PGQMatchFunction::EdgeTypeAny( auto edge_left_ref = make_uniq(); edge_left_ref->table_name = edge_table->table_name; src_dst_select_node->from_table = std::move(edge_left_ref); - auto src_left_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); - auto dst_left_ref = make_uniq(edge_table->destination_fk[0], edge_table->table_name); - // auto star_left_expr = make_uniq(); auto src_dst_children = vector>(); - src_dst_children.push_back(std::move(src_left_ref)); - src_dst_children.push_back(std::move(dst_left_ref)); - // src_dst_children.push_back(std::move(star_left_expr)); + src_dst_children.push_back(make_uniq(edge_table->source_fk[0], edge_table->table_name)); + src_dst_children.push_back(make_uniq(edge_table->destination_fk[0], edge_table->table_name)); + unordered_set added_columns; + added_columns.insert(edge_table->source_fk[0]); + added_columns.insert(edge_table->destination_fk[0]); + for (const auto& col : edge_table->column_names) { + if (added_columns.find(col) == added_columns.end()) { + src_dst_children.push_back(make_uniq(col, edge_table->table_name)); + added_columns.insert(col); + } + } src_dst_select_node->select_list = std::move(src_dst_children); // END SELECT src, dst, * from edge_table @@ -390,15 +395,23 @@ void PGQMatchFunction::EdgeTypeAny( auto edge_right_ref = make_uniq(); edge_right_ref->table_name = edge_table->table_name; - dst_src_select_node->from_table = std::move(edge_right_ref); - auto dst_right_ref = make_uniq( - edge_table->destination_fk[0], edge_table->table_name); - auto src_right_ref = make_uniq(edge_table->source_fk[0], edge_table->table_name); - // auto star_right_expr = make_uniq(); auto dst_src_children = vector>(); - dst_src_children.push_back(std::move(dst_right_ref)); - dst_src_children.push_back(std::move(src_right_ref)); - // dst_src_children.push_back(std::move(star_right_expr)); + dst_src_select_node->from_table = std::move(edge_right_ref); + + dst_src_children.push_back(make_uniq( + edge_table->destination_fk[0], edge_table->table_name)); + dst_src_children.push_back(make_uniq(edge_table->source_fk[0], + edge_table->table_name)); + added_columns.clear(); + added_columns.insert(edge_table->destination_fk[0]); + added_columns.insert(edge_table->source_fk[0]); + for (const auto& col : edge_table->column_names) { + if (added_columns.find(col) == added_columns.end()) { + dst_src_children.push_back(make_uniq(col, edge_table->table_name)); + added_columns.insert(col); + } + } + dst_src_select_node->select_list = std::move(dst_src_children); // END SELECT dst, src, * from edge_table @@ -647,7 +660,6 @@ void PGQMatchFunction::AddEdgeJoins( } switch (edge_type) { case PGQMatchType::MATCH_EDGE_ANY: { - select_node->modifiers.push_back(make_uniq()); EdgeTypeAny(edge_table, edge_binding, prev_binding, next_binding, conditions, from_clause); break; @@ -942,7 +954,7 @@ void PGQMatchFunction::ProcessPathList( unique_ptr PGQMatchFunction::MatchBindReplace(ClientContext &context, - TableFunctionBindInput &) { + TableFunctionBindInput &bind_input) { auto duckpgq_state_entry = context.registered_state.find("duckpgq"); auto duckpgq_state = dynamic_cast(duckpgq_state_entry->second.get()); diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index 7571c14e..e110c1dd 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -20,6 +20,17 @@ EDGE TABLES ( DESTINATION KEY ( dst ) REFERENCES Student ( id ) ); +query II +SELECT a."name" AS person, b."name" AS friend + FROM ((SELECT know.src, know.dst, know.createDate FROM know) UNION ALL (SELECT know.dst, know.src, know.createDate FROM know)) AS k , Student AS b , Student AS a + WHERE ((a.id = k.src) AND (b.id = k.dst) AND (a."name" = 'Daniel')); +---- +Daniel Tavneet +Daniel Gabor +Daniel Peter +Daniel David +Daniel Peter + # Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples query II -FROM GRAPH_TABLE (pg From 58e0cd97da928c93252c9d454bbd98183d1c22f4 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 16:38:00 +0100 Subject: [PATCH 14/23] Remove comment --- duckpgq/src/duckpgq/functions/tablefunctions/match.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index a1c22696..854755a3 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -422,7 +422,7 @@ void PGQMatchFunction::EdgeTypeAny( union_node->right = std::move(dst_src_select_node); auto union_select = make_uniq(); union_select->node = std::move(union_node); - // (SELECT src, dst, * from edge_table UNION ALL SELECT dst, src, * from edge_table UNION ALL) + // (SELECT src, dst, * from edge_table UNION ALL SELECT dst, src, * from edge_table) auto union_subquery = make_uniq(std::move(union_select)); union_subquery->alias = edge_binding; if (from_clause) { From 71380fe37eb950a7c81eb95f08d12b5c90d7ab4b Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Tue, 19 Mar 2024 16:38:22 +0100 Subject: [PATCH 15/23] Bug seems related to whether column in edge pattern is projected --- .../pattern-matching/undirected_edges.test | 36 ++++++++++++++----- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index e110c1dd..5b61b0f0 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -21,9 +21,9 @@ EDGE TABLES ( ); query II -SELECT a."name" AS person, b."name" AS friend - FROM ((SELECT know.src, know.dst, know.createDate FROM know) UNION ALL (SELECT know.dst, know.src, know.createDate FROM know)) AS k , Student AS b , Student AS a - WHERE ((a.id = k.src) AND (b.id = k.dst) AND (a."name" = 'Daniel')); +SELECT a.name AS person, b.name AS friend + FROM ((SELECT know.src, know.dst FROM know) UNION ALL (SELECT know.dst, know.src FROM know)) AS k , Student AS b , Student AS a + WHERE ((a.id = k.src) AND (b.id = k.dst) AND (a.name = 'Daniel')); ---- Daniel Tavneet Daniel Gabor @@ -31,17 +31,35 @@ Daniel Peter Daniel David Daniel Peter +# Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples +#query III +#-FROM GRAPH_TABLE (pg +# MATCH +# (a:Student)-[k:know]-(b:Student) +# WHERE a.name = 'Daniel' +# COLUMNS (a.name as person, b.name as friend, k.createDate as date) +# ) +#ORDER BY person, friend, date; +#---- +#Daniel David 18 +#Daniel Gabor 11 +#Daniel Peter 12 +#Daniel Peter 13 +#Daniel Tavneet 10 + # Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples query II --FROM GRAPH_TABLE (pg +-SELECT person, friend, date +FROM GRAPH_TABLE (pg MATCH (a:Student)-[k:know]-(b:Student) WHERE a.name = 'Daniel' - COLUMNS (a.name as person, b.name as friend) - ); + COLUMNS (a.name as person, b.name as friend, k.createDate as date) + ) +ORDER BY person, friend; ---- -Daniel Tavneet +Daniel David Daniel Gabor Daniel Peter -Daniel David -Daniel Peter \ No newline at end of file +Daniel Peter +Daniel Tavneet \ No newline at end of file From 55aa6613d04c6565df53c4c48597dcc16f9fecc4 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Wed, 20 Mar 2024 13:25:24 +0100 Subject: [PATCH 16/23] Only add columns to union that are needed --- duckdb-pgq | 2 +- .../functions/tablefunctions/match.hpp | 9 +-- .../functions/tablefunctions/match.cpp | 69 +++++++++++-------- .../pattern-matching/undirected_edges.test | 28 ++++---- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/duckdb-pgq b/duckdb-pgq index 817b9c66..a69a7552 160000 --- a/duckdb-pgq +++ b/duckdb-pgq @@ -1 +1 @@ -Subproject commit 817b9c6681810827774038c25d63989c60772e6e +Subproject commit a69a7552378c5fc80083bb4a3aa9ffa0cfec06ee diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp index 4c31a129..ea728959 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp @@ -68,7 +68,8 @@ struct PGQMatchFunction : public TableFunction { const string &prev_binding, const string &next_binding, vector> &conditions, - unique_ptr &from_clause); + unique_ptr &from_clause, + const vector> &column_list); static void EdgeTypeLeft(const shared_ptr &edge_table, const string &next_table_name, @@ -121,8 +122,7 @@ struct PGQMatchFunction : public TableFunction { const SubPath *subpath); static void - AddEdgeJoins(const unique_ptr &select_node, - const shared_ptr &edge_table, + AddEdgeJoins(const shared_ptr &edge_table, const shared_ptr &previous_vertex_table, const shared_ptr &next_vertex_table, PGQMatchType edge_type, const string &edge_binding, @@ -130,7 +130,8 @@ struct PGQMatchFunction : public TableFunction { vector> &conditions, unordered_map &alias_map, int32_t &extra_alias_counter, - unique_ptr &from_clause); + unique_ptr &from_clause, + vector> &column_list); static void ProcessPathList( vector> &path_pattern, diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 854755a3..cc640fd1 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -367,8 +367,18 @@ void PGQMatchFunction::EdgeTypeAny( const string &edge_binding, const string &prev_binding, const string &next_binding, vector> &conditions, - unique_ptr &from_clause) { - + unique_ptr &from_clause, + const vector> &column_list) { + vector> edge_columns; + for (const auto& expr : column_list) { + const auto column_expr = expr->Cast; + if (column_expr == nullptr) { + continue; + } + if (column_expr->column_names[0] == edge_binding) { + edge_columns.push_back(make_uniq(column_expr->column_names[1], edge_table->table_name)); + } + } // START SELECT src, dst, * from edge_table auto src_dst_select_node = make_uniq(); @@ -378,15 +388,19 @@ void PGQMatchFunction::EdgeTypeAny( auto src_dst_children = vector>(); src_dst_children.push_back(make_uniq(edge_table->source_fk[0], edge_table->table_name)); src_dst_children.push_back(make_uniq(edge_table->destination_fk[0], edge_table->table_name)); - unordered_set added_columns; - added_columns.insert(edge_table->source_fk[0]); - added_columns.insert(edge_table->destination_fk[0]); - for (const auto& col : edge_table->column_names) { - if (added_columns.find(col) == added_columns.end()) { - src_dst_children.push_back(make_uniq(col, edge_table->table_name)); - added_columns.insert(col); - } + for (const auto& expr : edge_columns) { + src_dst_children.push_back(expr->Copy()); } + + // unordered_set added_columns; + // added_columns.insert(edge_table->source_fk[0]); + // added_columns.insert(edge_table->destination_fk[0]); + // for (const auto& col : edge_table->column_names) { + // if (added_columns.find(col) == added_columns.end()) { + // src_dst_children.push_back(make_uniq(col, edge_table->table_name)); + // added_columns.insert(col); + // } + // } src_dst_select_node->select_list = std::move(src_dst_children); // END SELECT src, dst, * from edge_table @@ -402,15 +416,18 @@ void PGQMatchFunction::EdgeTypeAny( edge_table->destination_fk[0], edge_table->table_name)); dst_src_children.push_back(make_uniq(edge_table->source_fk[0], edge_table->table_name)); - added_columns.clear(); - added_columns.insert(edge_table->destination_fk[0]); - added_columns.insert(edge_table->source_fk[0]); - for (const auto& col : edge_table->column_names) { - if (added_columns.find(col) == added_columns.end()) { - dst_src_children.push_back(make_uniq(col, edge_table->table_name)); - added_columns.insert(col); - } + for (const auto& expr : edge_columns) { + dst_src_children.push_back(expr->Copy()); } + // added_columns.clear(); + // added_columns.insert(edge_table->destination_fk[0]); + // added_columns.insert(edge_table->source_fk[0]); + // for (const auto& col : edge_table->column_names) { + // if (added_columns.find(col) == added_columns.end()) { + // dst_src_children.push_back(make_uniq(col, edge_table->table_name)); + // added_columns.insert(col); + // } + // } dst_src_select_node->select_list = std::move(dst_src_children); // END SELECT dst, src, * from edge_table @@ -645,23 +662,21 @@ unique_ptr PGQMatchFunction::CreatePathFindingFunction( return final_list; } -void PGQMatchFunction::AddEdgeJoins( - const unique_ptr &select_node, - const shared_ptr &edge_table, +void PGQMatchFunction::AddEdgeJoins(const shared_ptr &edge_table, const shared_ptr &previous_vertex_table, const shared_ptr &next_vertex_table, PGQMatchType edge_type, const string &edge_binding, const string &prev_binding, const string &next_binding, vector> &conditions, unordered_map &alias_map, int32_t &extra_alias_counter, - unique_ptr &from_clause) { + unique_ptr &from_clause, vector> &column_list) { if (edge_type != PGQMatchType::MATCH_EDGE_ANY) { alias_map[edge_binding] = edge_table->table_name; } switch (edge_type) { case PGQMatchType::MATCH_EDGE_ANY: { EdgeTypeAny(edge_table, edge_binding, prev_binding, next_binding, - conditions, from_clause); + conditions, from_clause, column_list); break; } case PGQMatchType::MATCH_EDGE_LEFT: @@ -921,24 +936,24 @@ void PGQMatchFunction::ProcessPathList( } else { alias_map[edge_element->variable_binding] = edge_table->source_reference; - AddEdgeJoins(select_node, edge_table, previous_vertex_table, + AddEdgeJoins(edge_table, previous_vertex_table, next_vertex_table, edge_element->match_type, edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, - alias_map, extra_alias_counter, from_clause); + alias_map, extra_alias_counter, from_clause, column_list); } } else { // The edge element is a path element without WHERE or path-finding. auto edge_table = FindGraphTable(edge_element->label, pg_table); CheckInheritance(edge_table, edge_element, conditions); // check aliases - AddEdgeJoins(select_node, edge_table, previous_vertex_table, + AddEdgeJoins(edge_table, previous_vertex_table, next_vertex_table, edge_element->match_type, edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, - alias_map, extra_alias_counter, from_clause); + alias_map, extra_alias_counter, from_clause, column_list); // Check the edge type // If (a)-[b]->(c) -> b.src = a.id AND b.dst = c.id // If (a)<-[b]-(c) -> b.dst = a.id AND b.src = c.id diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index 5b61b0f0..5a95777b 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -32,20 +32,20 @@ Daniel David Daniel Peter # Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples -#query III -#-FROM GRAPH_TABLE (pg -# MATCH -# (a:Student)-[k:know]-(b:Student) -# WHERE a.name = 'Daniel' -# COLUMNS (a.name as person, b.name as friend, k.createDate as date) -# ) -#ORDER BY person, friend, date; -#---- -#Daniel David 18 -#Daniel Gabor 11 -#Daniel Peter 12 -#Daniel Peter 13 -#Daniel Tavneet 10 +query III +-FROM GRAPH_TABLE (pg + MATCH + (a:Student)-[k:know]-(b:Student) + WHERE a.name = 'Daniel' + COLUMNS (a.name as person, b.name as friend, k.createDate as date) + ) +ORDER BY person, friend, date; +---- +Daniel David 18 +Daniel Gabor 11 +Daniel Peter 12 +Daniel Peter 13 +Daniel Tavneet 10 # Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples query II From 47da5ae6504ba430b5b413ebbf0731b2ed56b93b Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 10:14:19 +0100 Subject: [PATCH 17/23] Revert cast --- duckpgq/src/duckpgq/functions/tablefunctions/match.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index cc640fd1..46175fb1 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -371,7 +371,7 @@ void PGQMatchFunction::EdgeTypeAny( const vector> &column_list) { vector> edge_columns; for (const auto& expr : column_list) { - const auto column_expr = expr->Cast; + const auto column_expr = dynamic_cast(expr.get()); if (column_expr == nullptr) { continue; } From 532804f32d35aabbd28f8031298c08867f453d99 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 10:15:21 +0100 Subject: [PATCH 18/23] move test, remove pritn --- .../functions/tablefunctions/match.cpp | 1 - .../pattern-matching/undirected_edges.test | 33 ++++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 46175fb1..ea6ff117 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -1074,7 +1074,6 @@ PGQMatchFunction::MatchBindReplace(ClientContext &context, subquery->node = std::move(select_node); auto result = make_uniq(std::move(subquery), ref->alias); - result->Print(); return std::move(result); } } // namespace duckdb diff --git a/test/sql/pattern-matching/undirected_edges.test b/test/sql/pattern-matching/undirected_edges.test index 5a95777b..e96ecbb0 100644 --- a/test/sql/pattern-matching/undirected_edges.test +++ b/test/sql/pattern-matching/undirected_edges.test @@ -31,6 +31,23 @@ Daniel Peter Daniel David Daniel Peter +# Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples +query II +-SELECT person, friend +FROM GRAPH_TABLE (pg + MATCH + (a:Student)-[k:know]-(b:Student) + WHERE a.name = 'Daniel' + COLUMNS (a.name as person, b.name as friend) + ) +ORDER BY person, friend; +---- +Daniel David +Daniel Gabor +Daniel Peter +Daniel Peter +Daniel Tavneet + # Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples query III -FROM GRAPH_TABLE (pg @@ -47,19 +64,3 @@ Daniel Peter 12 Daniel Peter 13 Daniel Tavneet 10 -# Daniel has 3 outgoing edges and 2 incoming edges, so there should be 5 tuples -query II --SELECT person, friend, date -FROM GRAPH_TABLE (pg - MATCH - (a:Student)-[k:know]-(b:Student) - WHERE a.name = 'Daniel' - COLUMNS (a.name as person, b.name as friend, k.createDate as date) - ) -ORDER BY person, friend; ----- -Daniel David -Daniel Gabor -Daniel Peter -Daniel Peter -Daniel Tavneet \ No newline at end of file From 1f16e35420bf09bbbeece8b9e07e6bacc713d1f9 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 10:56:35 +0100 Subject: [PATCH 19/23] Pass binder to new binder --- duckpgq/src/duckpgq_extension.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/duckpgq/src/duckpgq_extension.cpp b/duckpgq/src/duckpgq_extension.cpp index b25808a1..ee83e825 100644 --- a/duckpgq/src/duckpgq_extension.cpp +++ b/duckpgq/src/duckpgq_extension.cpp @@ -102,7 +102,7 @@ BoundStatement duckpgq_bind(ClientContext &context, Binder &binder, } auto duckpgq_state = (DuckPGQState *)lookup->second.get(); - auto duckpgq_binder = Binder::CreateBinder(context); + auto duckpgq_binder = Binder::CreateBinder(context, &binder); auto duckpgq_parse_data = dynamic_cast(duckpgq_state->parse_data.get()); if (duckpgq_parse_data) { From 54d2575ce752df1fd175b0cb2fef3e6af09acc53 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 10:57:04 +0100 Subject: [PATCH 20/23] Remove commented code --- .../functions/tablefunctions/match.cpp | 26 ++----------------- 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index ea6ff117..883ba9ec 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -388,19 +388,8 @@ void PGQMatchFunction::EdgeTypeAny( auto src_dst_children = vector>(); src_dst_children.push_back(make_uniq(edge_table->source_fk[0], edge_table->table_name)); src_dst_children.push_back(make_uniq(edge_table->destination_fk[0], edge_table->table_name)); - for (const auto& expr : edge_columns) { - src_dst_children.push_back(expr->Copy()); - } + src_dst_children.push_back(make_uniq()); - // unordered_set added_columns; - // added_columns.insert(edge_table->source_fk[0]); - // added_columns.insert(edge_table->destination_fk[0]); - // for (const auto& col : edge_table->column_names) { - // if (added_columns.find(col) == added_columns.end()) { - // src_dst_children.push_back(make_uniq(col, edge_table->table_name)); - // added_columns.insert(col); - // } - // } src_dst_select_node->select_list = std::move(src_dst_children); // END SELECT src, dst, * from edge_table @@ -416,18 +405,7 @@ void PGQMatchFunction::EdgeTypeAny( edge_table->destination_fk[0], edge_table->table_name)); dst_src_children.push_back(make_uniq(edge_table->source_fk[0], edge_table->table_name)); - for (const auto& expr : edge_columns) { - dst_src_children.push_back(expr->Copy()); - } - // added_columns.clear(); - // added_columns.insert(edge_table->destination_fk[0]); - // added_columns.insert(edge_table->source_fk[0]); - // for (const auto& col : edge_table->column_names) { - // if (added_columns.find(col) == added_columns.end()) { - // dst_src_children.push_back(make_uniq(col, edge_table->table_name)); - // added_columns.insert(col); - // } - // } + dst_src_children.push_back(make_uniq()); dst_src_select_node->select_list = std::move(dst_src_children); // END SELECT dst, src, * from edge_table From fe65e721b209edea04c7165ccbcbf18054dcbb24 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 11:00:48 +0100 Subject: [PATCH 21/23] Remove segfaulting test, see #103 --- test/sql/create_pg/optional_edge_table_clause.test | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/sql/create_pg/optional_edge_table_clause.test b/test/sql/create_pg/optional_edge_table_clause.test index 4c7a24e6..83b9c2e1 100644 --- a/test/sql/create_pg/optional_edge_table_clause.test +++ b/test/sql/create_pg/optional_edge_table_clause.test @@ -1,14 +1,8 @@ -# name: test/sql/sqlpgq/snb.test +# name: test/sql/create_pg/optional_edge_table_clause.test # group: [duckpgq] require duckpgq -statement error --CREATE PROPERTY GRAPH snb -VERTEX TABLES (tabledoesnotexist); ----- - - statement ok import database 'duckdb-pgq/data/SNB0.003'; From ce3a0a9b9fcf1baff460a6a04d6b586b3cbb5034 Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 11:01:26 +0100 Subject: [PATCH 22/23] Update expected results --- test/sql/pattern-matching/basic_match.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/sql/pattern-matching/basic_match.test b/test/sql/pattern-matching/basic_match.test index 01471e5d..c44d1371 100644 --- a/test/sql/pattern-matching/basic_match.test +++ b/test/sql/pattern-matching/basic_match.test @@ -132,7 +132,6 @@ Peter Tavneet Peter Gabor Peter David -# Disabled, see https://github.com/cwida/duckpgq-extension/issues/60 query II -SELECT study.a_name, study.b_name FROM GRAPH_TABLE (pg @@ -144,6 +143,7 @@ FROM GRAPH_TABLE (pg ORDER BY a_name, b_name; ---- Peter Daniel +Peter Daniel Peter David Peter Gabor Peter Tavneet From 6abad549052d475d1ba7c988d8f77b7905a9ba9c Mon Sep 17 00:00:00 2001 From: dtenwolde Date: Fri, 22 Mar 2024 11:03:15 +0100 Subject: [PATCH 23/23] Remove column_list argument --- .../functions/tablefunctions/match.hpp | 6 ++--- .../functions/tablefunctions/match.cpp | 22 +++++-------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp index ea728959..c2f050e8 100644 --- a/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp +++ b/duckpgq/include/duckpgq/functions/tablefunctions/match.hpp @@ -68,8 +68,7 @@ struct PGQMatchFunction : public TableFunction { const string &prev_binding, const string &next_binding, vector> &conditions, - unique_ptr &from_clause, - const vector> &column_list); + unique_ptr &from_clause); static void EdgeTypeLeft(const shared_ptr &edge_table, const string &next_table_name, @@ -130,8 +129,7 @@ struct PGQMatchFunction : public TableFunction { vector> &conditions, unordered_map &alias_map, int32_t &extra_alias_counter, - unique_ptr &from_clause, - vector> &column_list); + unique_ptr &from_clause); static void ProcessPathList( vector> &path_pattern, diff --git a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp index 883ba9ec..cd93baef 100644 --- a/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp +++ b/duckpgq/src/duckpgq/functions/tablefunctions/match.cpp @@ -367,18 +367,8 @@ void PGQMatchFunction::EdgeTypeAny( const string &edge_binding, const string &prev_binding, const string &next_binding, vector> &conditions, - unique_ptr &from_clause, - const vector> &column_list) { - vector> edge_columns; - for (const auto& expr : column_list) { - const auto column_expr = dynamic_cast(expr.get()); - if (column_expr == nullptr) { - continue; - } - if (column_expr->column_names[0] == edge_binding) { - edge_columns.push_back(make_uniq(column_expr->column_names[1], edge_table->table_name)); - } - } + unique_ptr &from_clause) { + // START SELECT src, dst, * from edge_table auto src_dst_select_node = make_uniq(); @@ -647,14 +637,14 @@ void PGQMatchFunction::AddEdgeJoins(const shared_ptr &edge_t const string &prev_binding, const string &next_binding, vector> &conditions, unordered_map &alias_map, int32_t &extra_alias_counter, - unique_ptr &from_clause, vector> &column_list) { + unique_ptr &from_clause) { if (edge_type != PGQMatchType::MATCH_EDGE_ANY) { alias_map[edge_binding] = edge_table->table_name; } switch (edge_type) { case PGQMatchType::MATCH_EDGE_ANY: { EdgeTypeAny(edge_table, edge_binding, prev_binding, next_binding, - conditions, from_clause, column_list); + conditions, from_clause); break; } case PGQMatchType::MATCH_EDGE_LEFT: @@ -919,7 +909,7 @@ void PGQMatchFunction::ProcessPathList( edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, - alias_map, extra_alias_counter, from_clause, column_list); + alias_map, extra_alias_counter, from_clause); } } else { // The edge element is a path element without WHERE or path-finding. @@ -931,7 +921,7 @@ void PGQMatchFunction::ProcessPathList( edge_element->variable_binding, previous_vertex_element->variable_binding, next_vertex_element->variable_binding, conditions, - alias_map, extra_alias_counter, from_clause, column_list); + alias_map, extra_alias_counter, from_clause); // Check the edge type // If (a)-[b]->(c) -> b.src = a.id AND b.dst = c.id // If (a)<-[b]-(c) -> b.dst = a.id AND b.src = c.id