This is an automated email from the ASF dual-hosted git repository.

mtaha pushed a commit to branch PG16
in repository https://gitbox.apache.org/repos/asf/age.git


The following commit(s) were added to refs/heads/PG16 by this push:
     new 28a3ac74 Fix issue 1767: CREATE TABLE AS SELECT * FROM cypher, errors 
(#1804)
28a3ac74 is described below

commit 28a3ac7436932e01d13525a1583ff0c4af54b621
Author: John Gemignani <jrgemign...@gmail.com>
AuthorDate: Fri Apr 26 08:07:20 2024 -0700

    Fix issue 1767: CREATE TABLE AS SELECT * FROM cypher, errors (#1804)
    
    Fixed issue 1767: create table as select * from cypher()... throws
    an error -
    
    ERROR:  unhandled cypher(cstring) function call
    
    CREATE TABLE AS is a utility command and therefore is not seen by the
    query tree walker. This is by design, per the query_tree_walker code
    comments. This is why the cypher command wasn't transformed causing
    the above error.
    
    The fix was to add a check for utility commands in the Query section
    of the convert_cypher_walker. If found, the embedded query from
    CreateTableAsStmts nodes is extracted and processed.
    
    NOTE: This only enables the utility command CreateTableAsStmts nodes.
          Others will need to be added on a case by case basis.
    
    Added regression tests.
---
 regress/expected/cypher.out         | 112 ++++++++++++++++++++++++++++++++++++
 regress/sql/cypher.sql              |  41 +++++++++++++
 src/backend/parser/cypher_analyze.c |  21 +++++++
 3 files changed, 174 insertions(+)

diff --git a/regress/expected/cypher.out b/regress/expected/cypher.out
index d2b569b5..31bafc6c 100644
--- a/regress/expected/cypher.out
+++ b/regress/expected/cypher.out
@@ -111,6 +111,115 @@ SELECT * FROM cypher('cypher', $$RETURN 0$$) AS (c oid);
 ERROR:  cannot cast type agtype to oid for column "c"
 LINE 1: SELECT * FROM cypher('cypher', $$RETURN 0$$) AS (c oid);
                       ^
+--
+-- Issue 1767: create table as select * from cypher()... throw an error
+--             This is due to the convert_cypher_walker not recognizing
+--             utility commands.
+-- create our graph
+SELECT * FROM create_graph('issue_1767');
+NOTICE:  graph "issue_1767" has been created
+ create_graph 
+--------------
+ 
+(1 row)
+
+-- add in 5 relationships
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+ result 
+--------
+(0 rows)
+
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+ result 
+--------
+(0 rows)
+
+-- show the 5 relationships
+SELECT * FROM cypher('issue_1767', $$ MATCH ()-[e]->() RETURN e $$) as (e 
agtype);
+                                                             e                 
                                            
+---------------------------------------------------------------------------------------------------------------------------
+ {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, 
"start_id": 281474976710657, "properties": {}}::edge
+ {"id": 844424930131970, "label": "knows", "end_id": 281474976710660, 
"start_id": 281474976710659, "properties": {}}::edge
+ {"id": 844424930131971, "label": "knows", "end_id": 281474976710662, 
"start_id": 281474976710661, "properties": {}}::edge
+ {"id": 844424930131972, "label": "knows", "end_id": 281474976710664, 
"start_id": 281474976710663, "properties": {}}::edge
+ {"id": 844424930131973, "label": "knows", "end_id": 281474976710666, 
"start_id": 281474976710665, "properties": {}}::edge
+(5 rows)
+
+-- create table my_vertices from the vertices. should be 10 rows.
+CREATE TABLE my_vertices AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH (u) RETURN u $$) as (u 
agtype));
+-- create table my_edges from the edges. should be 5 rows
+CREATE TABLE my_edges AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH ()-[e]->() RETURN e $$) as (e 
agtype));
+-- create a table of 4 columns, u, e, v, p. should be 5 rows
+CREATE TABLE my_detailed_paths AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH p=(u)-[e]->(v) RETURN u,e,v,p 
$$) as (u agtype, e agtype, v agtype, p agtype));
+-- dump out the tables
+SELECT * FROM my_vertices;
+                               u                                
+----------------------------------------------------------------
+ {"id": 281474976710657, "label": "", "properties": {}}::vertex
+ {"id": 281474976710658, "label": "", "properties": {}}::vertex
+ {"id": 281474976710659, "label": "", "properties": {}}::vertex
+ {"id": 281474976710660, "label": "", "properties": {}}::vertex
+ {"id": 281474976710661, "label": "", "properties": {}}::vertex
+ {"id": 281474976710662, "label": "", "properties": {}}::vertex
+ {"id": 281474976710663, "label": "", "properties": {}}::vertex
+ {"id": 281474976710664, "label": "", "properties": {}}::vertex
+ {"id": 281474976710665, "label": "", "properties": {}}::vertex
+ {"id": 281474976710666, "label": "", "properties": {}}::vertex
+(10 rows)
+
+SELECT * FROM my_edges;
+                                                             e                 
                                            
+---------------------------------------------------------------------------------------------------------------------------
+ {"id": 844424930131969, "label": "knows", "end_id": 281474976710658, 
"start_id": 281474976710657, "properties": {}}::edge
+ {"id": 844424930131970, "label": "knows", "end_id": 281474976710660, 
"start_id": 281474976710659, "properties": {}}::edge
+ {"id": 844424930131971, "label": "knows", "end_id": 281474976710662, 
"start_id": 281474976710661, "properties": {}}::edge
+ {"id": 844424930131972, "label": "knows", "end_id": 281474976710664, 
"start_id": 281474976710663, "properties": {}}::edge
+ {"id": 844424930131973, "label": "knows", "end_id": 281474976710666, 
"start_id": 281474976710665, "properties": {}}::edge
+(5 rows)
+
+SELECT * FROM my_detailed_paths;
+                               u                                |              
                                               e                                
                             |                               v                  
              |                                                                 
                                                                p               
                                                                                
              [...]
+----------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 [...]
+ {"id": 281474976710657, "label": "", "properties": {}}::vertex | {"id": 
844424930131969, "label": "knows", "end_id": 281474976710658, "start_id": 
281474976710657, "properties": {}}::edge | {"id": 281474976710658, "label": "", 
"properties": {}}::vertex | [{"id": 281474976710657, "label": "", "properties": 
{}}::vertex, {"id": 844424930131969, "label": "knows", "end_id": 
281474976710658, "start_id": 281474976710657, "properties": {}}::edge, {"id": 
281474976710658, "label": "", "properties" [...]
+ {"id": 281474976710659, "label": "", "properties": {}}::vertex | {"id": 
844424930131970, "label": "knows", "end_id": 281474976710660, "start_id": 
281474976710659, "properties": {}}::edge | {"id": 281474976710660, "label": "", 
"properties": {}}::vertex | [{"id": 281474976710659, "label": "", "properties": 
{}}::vertex, {"id": 844424930131970, "label": "knows", "end_id": 
281474976710660, "start_id": 281474976710659, "properties": {}}::edge, {"id": 
281474976710660, "label": "", "properties" [...]
+ {"id": 281474976710661, "label": "", "properties": {}}::vertex | {"id": 
844424930131971, "label": "knows", "end_id": 281474976710662, "start_id": 
281474976710661, "properties": {}}::edge | {"id": 281474976710662, "label": "", 
"properties": {}}::vertex | [{"id": 281474976710661, "label": "", "properties": 
{}}::vertex, {"id": 844424930131971, "label": "knows", "end_id": 
281474976710662, "start_id": 281474976710661, "properties": {}}::edge, {"id": 
281474976710662, "label": "", "properties" [...]
+ {"id": 281474976710663, "label": "", "properties": {}}::vertex | {"id": 
844424930131972, "label": "knows", "end_id": 281474976710664, "start_id": 
281474976710663, "properties": {}}::edge | {"id": 281474976710664, "label": "", 
"properties": {}}::vertex | [{"id": 281474976710663, "label": "", "properties": 
{}}::vertex, {"id": 844424930131972, "label": "knows", "end_id": 
281474976710664, "start_id": 281474976710663, "properties": {}}::edge, {"id": 
281474976710664, "label": "", "properties" [...]
+ {"id": 281474976710665, "label": "", "properties": {}}::vertex | {"id": 
844424930131973, "label": "knows", "end_id": 281474976710666, "start_id": 
281474976710665, "properties": {}}::edge | {"id": 281474976710666, "label": "", 
"properties": {}}::vertex | [{"id": 281474976710665, "label": "", "properties": 
{}}::vertex, {"id": 844424930131973, "label": "knows", "end_id": 
281474976710666, "start_id": 281474976710665, "properties": {}}::edge, {"id": 
281474976710666, "label": "", "properties" [...]
+(5 rows)
+
+-- cleanup
+DROP TABLE my_vertices;
+DROP TABLE my_edges;
+DROP TABLE my_detailed_paths;
+SELECT drop_graph('issue_1767', true);
+NOTICE:  drop cascades to 3 other objects
+DETAIL:  drop cascades to table issue_1767._ag_label_vertex
+drop cascades to table issue_1767._ag_label_edge
+drop cascades to table issue_1767.knows
+NOTICE:  graph "issue_1767" has been dropped
+ drop_graph 
+------------
+ 
+(1 row)
+
 SELECT drop_graph('cypher', true);
 NOTICE:  drop cascades to 2 other objects
 DETAIL:  drop cascades to table cypher._ag_label_vertex
@@ -121,3 +230,6 @@ NOTICE:  graph "cypher" has been dropped
  
 (1 row)
 
+--
+-- End
+--
diff --git a/regress/sql/cypher.sql b/regress/sql/cypher.sql
index 6f375451..7ded61ee 100644
--- a/regress/sql/cypher.sql
+++ b/regress/sql/cypher.sql
@@ -68,4 +68,45 @@ SELECT (SELECT * FROM cypher('cypher', $$RETURN 0$$) AS r(c 
agtype));
 SELECT * FROM cypher('cypher', $$RETURN true$$) AS (c bool);
 SELECT * FROM cypher('cypher', $$RETURN 0$$) AS (c oid);
 
+--
+-- Issue 1767: create table as select * from cypher()... throw an error
+--             This is due to the convert_cypher_walker not recognizing
+--             utility commands.
+
+-- create our graph
+SELECT * FROM create_graph('issue_1767');
+-- add in 5 relationships
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+SELECT * FROM cypher('issue_1767', $$ CREATE ()-[:knows]->() $$) AS (result 
agtype);
+-- show the 5 relationships
+SELECT * FROM cypher('issue_1767', $$ MATCH ()-[e]->() RETURN e $$) as (e 
agtype);
+
+-- create table my_vertices from the vertices. should be 10 rows.
+CREATE TABLE my_vertices AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH (u) RETURN u $$) as (u 
agtype));
+-- create table my_edges from the edges. should be 5 rows
+CREATE TABLE my_edges AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH ()-[e]->() RETURN e $$) as (e 
agtype));
+-- create a table of 4 columns, u, e, v, p. should be 5 rows
+CREATE TABLE my_detailed_paths AS
+    (SELECT * FROM cypher('issue_1767', $$ MATCH p=(u)-[e]->(v) RETURN u,e,v,p 
$$) as (u agtype, e agtype, v agtype, p agtype));
+
+-- dump out the tables
+SELECT * FROM my_vertices;
+SELECT * FROM my_edges;
+SELECT * FROM my_detailed_paths;
+
+-- cleanup
+DROP TABLE my_vertices;
+DROP TABLE my_edges;
+DROP TABLE my_detailed_paths;
+
+SELECT drop_graph('issue_1767', true);
 SELECT drop_graph('cypher', true);
+
+--
+-- End
+--
diff --git a/src/backend/parser/cypher_analyze.c 
b/src/backend/parser/cypher_analyze.c
index d69cc055..50ecdde7 100644
--- a/src/backend/parser/cypher_analyze.c
+++ b/src/backend/parser/cypher_analyze.c
@@ -211,6 +211,27 @@ static bool convert_cypher_walker(Node *node, ParseState 
*pstate)
         bool result = false;
         Query *query = (Query *)node;
 
+        /*
+         * If this is a utility command, we need to unwrap the internal query
+         * and pass it as the query.
+         *
+         * NOTE: This code only "knows" about the following utility commands -
+         *
+         * CREATE TABLE AS
+         *
+         * Others need to be added on a case by case basis.
+         */
+        if (query->utilityStmt != NULL &&
+            IsA(query->utilityStmt, CreateTableAsStmt))
+        {
+            CreateTableAsStmt *ctas = (CreateTableAsStmt *)query->utilityStmt;
+
+            if (IsA(ctas->query, Query))
+            {
+                query = (Query *)ctas->query;
+            }
+        }
+
         /*
          * QTW_EXAMINE_RTES
          *     We convert RTE_FUNCTION (cypher()) to RTE_SUBQUERY (SELECT)

Reply via email to