diff --git a/src/duckpgq_extension.cpp b/src/duckpgq_extension.cpp index a8de89da..35c46eaa 100644 --- a/src/duckpgq_extension.cpp +++ b/src/duckpgq_extension.cpp @@ -89,7 +89,7 @@ ParserExtensionParseResult duckpgq_parse(ParserExtensionInfo *info, : query); if (parser.statements.size() != 1) { throw Exception(ExceptionType::PARSER, - "More than 1 statement detected, please only give one."); + "More than one statement detected, please only give one."); } return ParserExtensionParseResult(make_uniq_base( std::move(parser.statements[0]))); @@ -119,15 +119,11 @@ void duckpgq_find_match_function(TableRef *table_ref, // Handle TableFunctionRef case auto function = dynamic_cast(table_function_ref->function.get()); - if (function->function_name == "duckpgq_match") { - if (duckpgq_state.transform_expression != nullptr) { - throw Exception(ExceptionType::INVALID, - "Multiple graph tables in a single query are not supported yet"); - } - duckpgq_state.transform_expression = - std::move(std::move(function->children[0])); - function->children.pop_back(); + if (function->function_name != "duckpgq_match") { + return; } + duckpgq_state.transform_expression.push_back(std::move(function->children[0])); + function->children.pop_back(); } else if (auto join_ref = dynamic_cast(table_ref)) { // Handle JoinRef case duckpgq_find_match_function(join_ref->left.get(), duckpgq_state); diff --git a/src/functions/tablefunctions/match.cpp b/src/functions/tablefunctions/match.cpp index cd93baef..d1ebf0f3 100644 --- a/src/functions/tablefunctions/match.cpp +++ b/src/functions/tablefunctions/match.cpp @@ -943,11 +943,9 @@ PGQMatchFunction::MatchBindReplace(ClientContext &context, dynamic_cast(duckpgq_state_entry->second.get()); auto ref = dynamic_cast( - duckpgq_state->transform_expression.get()); + duckpgq_state->transform_expression[0].get()); auto pg_table = duckpgq_state->GetPropertyGraph(ref->pg_name); - auto data = make_uniq(); - vector> conditions; auto select_node = make_uniq(); @@ -1040,8 +1038,16 @@ PGQMatchFunction::MatchBindReplace(ClientContext &context, auto subquery = make_uniq(); subquery->node = std::move(select_node); + if (ref->alias == "unnamed_graphtable") { + if (duckpgq_state->unnamed_graphtable_index > 1) { + ref->alias = "unnamed_graphtable" + + std::to_string(duckpgq_state->unnamed_graphtable_index); + } + duckpgq_state->unnamed_graphtable_index++; + } auto result = make_uniq(std::move(subquery), ref->alias); + duckpgq_state->transform_expression.erase(duckpgq_state->transform_expression.begin()); return std::move(result); } } // namespace duckdb diff --git a/src/include/duckpgq_extension.hpp b/src/include/duckpgq_extension.hpp index bec5ff6c..d9fe0e04 100644 --- a/src/include/duckpgq_extension.hpp +++ b/src/include/duckpgq_extension.hpp @@ -79,7 +79,8 @@ class DuckPGQState : public ClientContextState { void QueryEnd() override { parse_data.reset(); - transform_expression = nullptr; + transform_expression.clear(); + unnamed_graphtable_index = 1; // Reset the index for (const auto &csr_id : csr_to_delete) { csr_list.erase(csr_id); } @@ -105,7 +106,10 @@ class DuckPGQState : public ClientContextState { public: unique_ptr parse_data; - unique_ptr transform_expression; + vector> transform_expression; + + int32_t unnamed_graphtable_index = 1; // Used to generate unique names for + // unnamed graph tables //! Property graphs that are registered std::unordered_map> registered_property_graphs; diff --git a/test/sql/multiple_graph_table.test b/test/sql/multiple_graph_table.test new file mode 100644 index 00000000..59dfd0e7 --- /dev/null +++ b/test/sql/multiple_graph_table.test @@ -0,0 +1,171 @@ +# name: test/sql/multiple_graph_table.test +# group: [duckpgq] + +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 TABLE School(name VARCHAR, Id BIGINT, Kind VARCHAR);INSERT INTO School VALUES ('VU', 0, 'University'), ('UVA', 1, 'University'); + +statement ok +CREATE TABLE StudyAt(personId BIGINT, schoolId BIGINT);INSERT INTO StudyAt VALUES (0, 0), (1, 0), (2, 1), (3, 1), (4, 1); + +statement ok +-CREATE PROPERTY GRAPH pg +VERTEX TABLES ( + Student, + School + ) +EDGE TABLES ( + know SOURCE KEY ( src ) REFERENCES Student ( id ) + DESTINATION KEY ( dst ) REFERENCES Student ( id ), + studyAt SOURCE KEY ( personId ) REFERENCES Student ( id ) + DESTINATION KEY ( SchoolId ) REFERENCES School ( id ) + ); + +query II +-select a.id, b.id FROM GRAPH_TABLE(pg MATCH (a:student)) a, GRAPH_TABLE(pg MATCH (b:student)) b; +---- +0 0 +0 1 +0 2 +0 3 +0 4 +1 0 +1 1 +1 2 +1 3 +1 4 +2 0 +2 1 +2 2 +2 3 +2 4 +3 0 +3 1 +3 2 +3 3 +3 4 +4 0 +4 1 +4 2 +4 3 +4 4 + +query II +-select unnamed_graphtable.id, unnamed_graphtable2.id FROM GRAPH_TABLE(pg MATCH (a:student)), GRAPH_TABLE(pg MATCH (b:student)); +---- +0 0 +0 1 +0 2 +0 3 +0 4 +1 0 +1 1 +1 2 +1 3 +1 4 +2 0 +2 1 +2 2 +2 3 +2 4 +3 0 +3 1 +3 2 +3 3 +3 4 +4 0 +4 1 +4 2 +4 3 +4 4 + + +query IIII +-select a.id, a.name, unnamed_graphtable.id, unnamed_graphtable.name FROM GRAPH_TABLE(pg MATCH (a:student)) a, GRAPH_TABLE(pg MATCH (b:student)-[r:know]->(c:student)); +---- +0 Daniel 1 Tavneet +0 Daniel 2 Gabor +0 Daniel 3 Peter +0 Daniel 0 Daniel +0 Daniel 2 Gabor +0 Daniel 3 Peter +0 Daniel 3 Peter +0 Daniel 3 Peter +1 Tavneet 1 Tavneet +1 Tavneet 2 Gabor +1 Tavneet 3 Peter +1 Tavneet 0 Daniel +1 Tavneet 2 Gabor +1 Tavneet 3 Peter +1 Tavneet 3 Peter +1 Tavneet 3 Peter +2 Gabor 1 Tavneet +2 Gabor 2 Gabor +2 Gabor 3 Peter +2 Gabor 0 Daniel +2 Gabor 2 Gabor +2 Gabor 3 Peter +2 Gabor 3 Peter +2 Gabor 3 Peter +3 Peter 1 Tavneet +3 Peter 2 Gabor +3 Peter 3 Peter +3 Peter 0 Daniel +3 Peter 2 Gabor +3 Peter 3 Peter +3 Peter 3 Peter +3 Peter 3 Peter +4 David 1 Tavneet +4 David 2 Gabor +4 David 3 Peter +4 David 0 Daniel +4 David 2 Gabor +4 David 3 Peter +4 David 3 Peter +4 David 3 Peter + + +query II +-select unnamed_subquery.id, unnamed_graphtable.id +FROM GRAPH_TABLE(pg MATCH (a:student)), (select 1 as id); +---- +1 0 +1 1 +1 2 +1 3 +1 4 + +statement ok +CREATE TABLE cities ( +name VARCHAR, +lat DECIMAL, +lon DECIMAL +); + +statement ok +CREATE TABLE cities_are_adjacent ( +city1name VARCHAR, +city2name VARCHAR +); + +statement ok +-CREATE PROPERTY GRAPH citymap +VERTEX TABLES ( +cities PROPERTIES (name,lat,lon) LABEL city +) +EDGE TABLES ( +cities_are_adjacent SOURCE KEY ( city1name ) REFERENCES cities ( name ) +DESTINATION KEY ( city2name ) REFERENCES cities ( name ) +LABEL adjacent +); + +statement ok +-select * from GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g1, GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g2; + diff --git a/test/sql/multiple_graph_table_error.test b/test/sql/multiple_graph_table_error.test deleted file mode 100644 index eb04b3c0..00000000 --- a/test/sql/multiple_graph_table_error.test +++ /dev/null @@ -1,45 +0,0 @@ -# name: test/sql/sqlpgq/multiple_graph_table_error.test -# group: [duckpgq] - -require duckpgq - -statement ok -CREATE TABLE cities ( -name VARCHAR, -lat DECIMAL, -lon DECIMAL -); - -statement ok -CREATE TABLE cities_are_adjacent ( -city1name VARCHAR, -city2name VARCHAR -); - -statement ok --CREATE PROPERTY GRAPH citymap -VERTEX TABLES ( -cities PROPERTIES (name,lat,lon) LABEL city -) -EDGE TABLES ( -cities_are_adjacent SOURCE KEY ( city1name ) REFERENCES cities ( name ) -DESTINATION KEY ( city2name ) REFERENCES cities ( name ) -LABEL adjacent -); - -statement error --select * from GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g1, GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g2; ----- -Invalid Error: Multiple graph tables in a single query are not supported yet - -statement ok --FROM GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g1; - -statement ok --FROM GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g1; - -statement error --select * from GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g1, GRAPH_TABLE (citymap MATCH (s:city)-[r:adjacent]->(t:city)) g2; ----- -Invalid Error: Multiple graph tables in a single query are not supported yet -