On Wed, Mar 25, 2026 at 2:11 PM Peter Eisentraut <[email protected]> wrote: > > On 20.03.26 14:42, Ashutosh Bapat wrote: > >> We should either: > >> > >> (1) Support G041 fully -- both directions. Junwang's patch handles > >> this cleanly with minimal code change, or > >> (2) Not support G041 -- reject all non-local element pattern > >> references, throwing an error for both directions. > >> > >> What do you think? > > > > We will support the cross variable references in future once we > > support more path patterns leading to a more mature code in that area. > > But it doesn't harm to support backward references which can be easily > > supported now. I don't see the code to do so getting disturbed as it > > matures. For the segmentation fault a simple fix to add graph_pattern > > suffices for now. Let's see if Peter has a different opinion. > > I think we should not allow non-local references in either direction > (until we implement feature G041), option 2 above. Allowing only > backward references seems kind of an arbitrary implementation artifact. >
Sorry, I didn't explain well earlier. It isn't arbitrary. It mimics backward lateral references. Consider following query Query1 SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers)-[IS customer_orders]->(o IS orders WHERE o.order_id = x1.a) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid)) g; x1 is a table referenced in from clause as well as an element pattern variable in path pattern. If we don't allow backward (cross) referencing, x1.a in the element pattern o resolves to the table x1's column a, but x1.name resolves to element x1's property reference name. So within the same graph pattern x1 may get resolved to two different things, even though x1 was declared before using it. Is that how we expect it to happen? Let's call this inconsistency1. However, if we allow backward references, we resolve x1 to the table column reference till the point where x1 appears in the path pattern and then onwards resolve x1 to the element pattern variable. So x1.a and x1.name are both resolved into a property of element x1. Ofc, in this example x1.a will result in an error since there is no property with name a in the property graph. But in case label "customers" also exposes property a, x1.a will be resolved to a property reference - applying resolution rule consistently everywhere. The behaviour remains consistent even with a forward reference like Query 2 SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(x1 IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid, x1.order_id)) g; x1 in element pattern c is resolved to table x1 since that's the only known resolution so far. x1.order_id however gets resolved to order_id property of label orders as by then there is a closer reference available. If we do not support backward references now, but start supporting it later, the Query 1's semantics will change, breaking backward compatibility. Let's call this "backward incompatibility 1". If we do not support forward element pattern references, that will be inline with the fact that we don't support forward lateral references. Those products which do not support lateral with graph_table don't have to worry about any of these problems when supporting cross element references. We have the following options 1. Don't support cross referencing element variables, but then we have "inconsistency1". 2. Support backward referencing element variables, with a risk of "backward incompatibility 1". I think the standard leaves room to not support forward referencing at all while supporting backward referencing 3. Support both backward and forward referencing now, with a risk that it may become a hurdle when we support more advanced features in graph pattern matching. Given that we are in an early phase of implementing PGQ query support, avoiding such hurdles is better. I am leaning towards 2 + not supporting forward referencing at all. But in the attached patchset I have implemented option 1 as you suggested. If you are fine with option 1, let's use that patch. On Wed, Mar 25, 2026 at 3:04 PM Peter Eisentraut <[email protected]> wrote: > > On 25.03.26 10:12, Ashutosh Bapat wrote: > > On Wed, Mar 25, 2026 at 2:27 PM Peter Eisentraut <[email protected]> > > wrote: > >> > >> This functionality that you can leave off empty vertex patterns at the > >> beginning and end is part of the optional feature G047, which we don't > >> claim to support. So we should reject these path patterns. > >> > > > > Thanks for the clarification. What about the implicit empty vertex > > patterns in the middle of the path? Should we reject these path > > patterns also? > Yes, I think so. > > The specification of feature G047 is: > > "... in conforming SQL language, any <edge pattern> shall be immediately > preceded and followed by a <vertex pattern>." > > So if you write > > () -[]-> -[]-> () > > then the first edge pattern is not followed immediately by a vertex > pattern, and so it would be invalid without feature G047. Implemented it this way in the attached patchset. 0001: is a small adjustment to make sure that we add an element variable name to the graph table namespace only once. This isn't a problem right now, but we will have to do that anyway in [1] and it has some effect one 0002. 0002: prohibits cross element variable references within graph_table clause. It adds a new member GraphTableParseState::cur_variable to track the variable name of the current pattern being transformed. We can not use llast() simply because a. pattern currently being transformed may not have name, so llast will be misleading b. changes in 0001. We may want to combine 0001 and 0002 when committing. 0003: prohibits consecutive element patterns of the same kind 0004: some cleanup remaining from 5282bf535e474dc2517f2e835d147420ae2144de. We may want to wait to accumulate more cleanups. [1] https://www.postgresql.org/message-id/CAExHW5tYCE9QyCvVraKUeesKW5RTR%2Bmrzsg3u64qSps-RPJR5A%40mail.gmail.com -- Best Wishes, Ashutosh Bapat
From 5f73779b33bd31fa80bb67f9a8aa26e89db26a71 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Tue, 17 Mar 2026 14:30:16 +0530 Subject: [PATCH v20260326 4/4] Cleanup and other cosmetic fixes ... collected over time TODO: provide a proper commit message Author: Man Zeng <[email protected]> Author: Ashutosh Bapat <[email protected]> --- src/backend/parser/parse_graphtable.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index d1d0076789a..bc7195c5ad0 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -95,14 +95,14 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) { if (pstate->p_expr_kind == EXPR_KIND_SELECT_TARGET) ereport(ERROR, - errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("\"*\" is not supported here"), - parser_errposition(pstate, cref->location)); + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("\"*\" is not supported here"), + parser_errposition(pstate, cref->location))); else ereport(ERROR, - errcode(ERRCODE_SYNTAX_ERROR), - errmsg("\"*\" not allowed here"), - parser_errposition(pstate, cref->location)); + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("\"*\" not allowed here"), + parser_errposition(pstate, cref->location))); } elvarname = strVal(field1); @@ -129,8 +129,8 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) pgptup = SearchSysCache2(PROPGRAPHPROPNAME, ObjectIdGetDatum(gpstate->graphid), CStringGetDatum(propname)); if (!HeapTupleIsValid(pgptup)) ereport(ERROR, - errcode(ERRCODE_SYNTAX_ERROR), - errmsg("property \"%s\" does not exist", propname)); + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("property \"%s\" does not exist", propname))); pgpform = (Form_pg_propgraph_property) GETSTRUCT(pgptup); gpr->location = cref->location; @@ -185,8 +185,9 @@ transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) labelid = GetSysCacheOid2(PROPGRAPHLABELNAME, Anum_pg_propgraph_label_oid, ObjectIdGetDatum(gpstate->graphid), CStringGetDatum(labelname)); if (!labelid) ereport(ERROR, - errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("label \"%s\" does not exist in property graph \"%s\"", labelname, get_rel_name(gpstate->graphid))); + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("label \"%s\" does not exist in property graph \"%s\"", + labelname, get_rel_name(gpstate->graphid)))); lref = makeNode(GraphLabelRef); lref->labelid = labelid; -- 2.34.1
From e3e0a1c020fcf673a1411754514bf297d9455b51 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Thu, 26 Mar 2026 12:01:51 +0530 Subject: [PATCH v20260326 1/4] Add a graph pattern variable only once An element pattern variable may be repeated in the path pattern. GraphTableParseState maintains a list of all variable names used in the graph pattern. Add a new variable name to that list only when it is not present already. Author: Ashutosh Bapat <[email protected]> --- src/backend/parser/parse_graphtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index bf805b4beb6..bbe105b823d 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -236,7 +236,7 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) errmsg("element pattern quantifier is not supported"))); if (gep->variable) - gpstate->variables = lappend(gpstate->variables, makeString(pstrdup(gep->variable))); + gpstate->variables = list_append_unique(gpstate->variables, makeString(pstrdup(gep->variable))); gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr); base-commit: 735e8fe685359480e77d837493a5dc0a38866944 -- 2.34.1
From 4aae62b2682e5e8d9c5d5874e85c1a17f410a2b7 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Wed, 25 Mar 2026 17:15:10 +0530 Subject: [PATCH v20260326 2/4] Cross variable references in graph pattern causes segfault When converting the WHERE clause in an element pattern, generate_query_for_graph_path() calls replace_property_refs() to replace the property references in it. Only the current graph element pattern is passed as the context for replacement. If there are references to variables from other element patterns, it causes a segmentation fault (an assertion failure in an Assert enabled build) since it does not find path_element object corresponding to those variables. We do not support forward and backward variable references within a graph table clause. Hence prohibit all the cross references. Author: Ashutosh Bapat <[email protected]> Reported by: Man Zeng <[email protected]> Investigated by: Henson Choi <[email protected]> Reviewed by: Junwang Zhao <[email protected]> --- src/backend/parser/parse_graphtable.c | 24 +++++++++++++++++++++-- src/include/parser/parse_node.h | 4 ++++ src/test/regress/expected/graph_table.out | 23 ++++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 6 ++++++ 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index bbe105b823d..626d3b681d0 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -89,6 +89,7 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) Node *field2 = lsecond(cref->fields); char *elvarname; char *propname; + bool is_prop_ref = false; if (IsA(field1, A_Star) || IsA(field2, A_Star)) { @@ -107,7 +108,19 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) elvarname = strVal(field1); propname = strVal(field2); - if (list_member(gpstate->variables, field1)) + /* + * If we are transforming expression in an element pattern, property + * references containing only that variable are allowed. + */ + if (gpstate->cur_variable) + { + if (equal(gpstate->cur_variable, field1)) + is_prop_ref = true; + } + else if (list_member(gpstate->variables, field1)) + is_prop_ref = true; + + if (is_prop_ref) { GraphPropertyRef *gpr = makeNode(GraphPropertyRef); HeapTuple pgptup; @@ -235,14 +248,21 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("element pattern quantifier is not supported"))); + Assert(!gpstate->cur_variable); + if (gep->variable) - gpstate->variables = list_append_unique(gpstate->variables, makeString(pstrdup(gep->variable))); + { + gpstate->cur_variable = makeString(pstrdup(gep->variable)); + gpstate->variables = list_append_unique(gpstate->variables, gpstate->cur_variable); + } gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr); gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE); assign_expr_collations(pstate, gep->whereClause); + gpstate->cur_variable = NULL; + return (Node *) gep; } diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h index fc2cbeb2083..d23d37dfaec 100644 --- a/src/include/parser/parse_node.h +++ b/src/include/parser/parse_node.h @@ -110,6 +110,10 @@ typedef struct GraphTableParseState Oid graphid; /* OID of the graph being referenced */ List *variables; /* list of element pattern variables in * GRAPH_TABLE */ + String *cur_variable; /* Variable in the element pattern being + * transformed. NULL if no element pattern is + * being transformed or the pattern has no + * variable. */ } GraphTableParseState; /* diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index 27c81ec6e42..ca7b74e6912 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -242,6 +242,19 @@ SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'U 1 | one | customer1 | 1 (1 row) +SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers)-[IS customer_orders]->(o IS orders WHERE o.order_id = x1.a) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g; + a | customer_name | cid | order_id +---+---------------+-----+---------- + 1 | customer1 | 1 | 1 + 2 | customer2 | 2 | 2 +(2 rows) + +SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(x1 IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid, x1.order_id)) g; + a | customer_name | cid | order_id +---+---------------+-----+---------- + 1 | customer1 | 1 | 1 +(1 row) + DROP TABLE x1; CREATE TABLE v1 ( id int PRIMARY KEY, @@ -395,6 +408,16 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-(v2) COLUMNS (v1.vname AS v1name v22 | v32 (3 rows) +-- cross variable references +SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; +ERROR: missing FROM-clause entry for table "a" +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b WHERE a.vprop1 = ... + ^ +-- forward variable reference, not supported +SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; +ERROR: missing FROM-clause entry for table "b" +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 1000... + ^ -- Errors -- vl1 is not associated with property vprop2 SELECT src, src_vprop2, conn, dest FROM GRAPH_TABLE (g1 MATCH (a IS vl1)-[b IS el1]->(c IS vl2 | vl3) COLUMNS (a.vname AS src, a.vprop2 AS src_vprop2, b.ename AS conn, c.vname AS dest)); diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 6d2b08b997b..88215ea427a 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -154,6 +154,8 @@ SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers)->(o IS orders) COLUMNS CREATE TABLE x1 (a int, b text); INSERT INTO x1 VALUES (1, 'one'), (2, 'two'); SELECT * FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(o IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid)); +SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (x1 IS customers)-[IS customer_orders]->(o IS orders WHERE o.order_id = x1.a) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g; +SELECT x1.a, g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS customer_orders]->(x1 IS orders) COLUMNS (c.name AS customer_name, c.customer_id AS cid, x1.order_id)) g; DROP TABLE x1; CREATE TABLE v1 ( @@ -274,6 +276,10 @@ SELECT src, conn, dest, lprop1, vprop2, vprop1 FROM GRAPH_TABLE (g1 MATCH (a IS -- edges directed in both ways - to and from v2 SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-[conn]-(v2) COLUMNS (v1.vname AS v1name, conn.ename AS cname, v2.vname AS v2name)); SELECT * FROM GRAPH_TABLE (g1 MATCH (v1 IS vl2)-(v2) COLUMNS (v1.vname AS v1name, v2.vname AS v2name)); +-- cross variable references +SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[b WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; +-- forward variable reference, not supported +SELECT * FROM GRAPH_TABLE (g1 MATCH (a WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (a.vname AS aname, a.vprop1 AS ap1, b.ename AS bname, b.eprop1 AS bp1, c.vname AS cname, c.vprop1 AS cp1)) ORDER BY aname, bname, cname; -- Errors -- vl1 is not associated with property vprop2 -- 2.34.1
From 50c670d26ff7c38e56009ade58cd1e1dd83ff545 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <[email protected]> Date: Wed, 25 Mar 2026 17:49:02 +0530 Subject: [PATCH v20260326 3/4] Consecutive element patterns of same kind Adding an implicit empty vertex pattern when a path pattern starts or ends with an edge pattern or when two consecutive edge patterns appear in the pattern is not supported right not. Prohibit such path patterns. Author: Ashutosh Bapat <[email protected]> Reported by: Alexander Lakhin <[email protected]> Investigation by: Henson Choi <[email protected]> Reviewed by: Henson Choi <[email protected]> --- src/backend/parser/parse_graphtable.c | 58 +++++++++++++++++++++-- src/backend/rewrite/rewriteGraphTable.c | 10 ++++ src/test/regress/expected/graph_table.out | 19 ++++++++ src/test/regress/sql/graph_table.sql | 6 +++ 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index 626d3b681d0..d1d0076789a 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -238,11 +238,6 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) { GraphTableParseState *gpstate = pstate->p_graph_table_pstate; - if (gep->kind != VERTEX_PATTERN && !IS_EDGE_PATTERN(gep->kind)) - ereport(ERROR, - errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("unsupported element pattern kind: \"%s\"", get_gep_kind_name(gep->kind))); - if (gep->quantifier) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), @@ -273,10 +268,63 @@ static Node * transformPathTerm(ParseState *pstate, List *path_term) { List *result = NIL; + GraphElementPattern *prev_gep = NULL; foreach_node(GraphElementPattern, gep, path_term) + { + if (gep->kind != VERTEX_PATTERN && !IS_EDGE_PATTERN(gep->kind)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported element pattern kind: \"%s\"", get_gep_kind_name(gep->kind)), + parser_errposition(pstate, gep->location))); + + if (IS_EDGE_PATTERN(gep->kind)) + { + /* An edge pattern should always be preceded by a vertex pattern */ + if (!prev_gep) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("a path pattern cannot start with an edge pattern"), + parser_errposition(pstate, gep->location))); + } + + if (prev_gep->kind != VERTEX_PATTERN) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("path pattern with two consecutive edge patterns without a vertex pattern in between is not supported"), + parser_errposition(pstate, gep->location))); + } + } + else + { + if (prev_gep && !IS_EDGE_PATTERN(prev_gep->kind)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("path pattern with two consecutive vertex patterns without an edge pattern in between is not supported"), + parser_errposition(pstate, gep->location))); + } + result = lappend(result, transformGraphElementPattern(pstate, gep)); + prev_gep = gep; + } + + /* Path pattern should have at least one element pattern. */ + Assert(prev_gep); + + /* + * Add an implicit vertex pattern at the end if the last element is an + * edge pattern. + */ + if (IS_EDGE_PATTERN(prev_gep->kind)) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("a path pattern cannot end with an edge pattern"), + parser_errposition(pstate, prev_gep->location))); + } return (Node *) result; } diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 9c293586e44..2c3199d3230 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -300,6 +300,11 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) errmsg("an edge cannot connect more than two vertexes even in a cyclic pattern")); prev_pf->src_pf = pf; } + else + { + Assert(prev_pf->kind == VERTEX_PATTERN); + Assert(IS_EDGE_PATTERN(pf->kind)); + } if (pf->kind == EDGE_PATTERN_RIGHT || pf->kind == EDGE_PATTERN_ANY) { @@ -319,6 +324,11 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) errmsg("an edge cannot connect more than two vertexes even in a cyclic pattern")); pf->dest_pf = prev_pf; } + else + { + Assert(pf->kind == VERTEX_PATTERN); + Assert(IS_EDGE_PATTERN(prev_pf->kind)); + } } prev_pf = pf; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index ca7b74e6912..ba433ce3713 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -103,6 +103,8 @@ SELECT customer_name FROM GRAPH_TABLE (myshop MATCH (c IS customers)->{1,2}(o IS ERROR: element pattern quantifier is not supported SELECT * FROM GRAPH_TABLE (myshop MATCH ((c IS customers)->(o IS orders)) COLUMNS (c.name)); ERROR: unsupported element pattern kind: "nested path pattern" +LINE 1: SELECT * FROM GRAPH_TABLE (myshop MATCH ((c IS customers)->(... + ^ -- a property graph can be referenced only from within GRAPH_TABLE clause. SELECT * FROM myshop; -- error ERROR: cannot open relation "myshop" @@ -443,6 +445,23 @@ SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT NULL)-[ ERROR: "*" not allowed here LINE 1: ...M GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT... ^ +-- consecutive element patterns with same kind +SELECT * FROM GRAPH_TABLE (g1 MATCH ()() COLUMNS (1 as one)); +ERROR: path pattern with two consecutive vertex patterns without an edge pattern in between is not supported +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH ()() COLUMNS (1 as one))... + ^ +SELECT * FROM GRAPH_TABLE (g1 MATCH -> COLUMNS (1 AS one)); +ERROR: a path pattern cannot start with an edge pattern +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH -> COLUMNS (1 AS one)); + ^ +SELECT * FROM GRAPH_TABLE (g1 MATCH ()-[]- COLUMNS (1 AS one)); +ERROR: a path pattern cannot end with an edge pattern +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH ()-[]- COLUMNS (1 AS one... + ^ +SELECT * FROM GRAPH_TABLE (g1 MATCH ()-> ->() COLUMNS (1 AS one)); +ERROR: path pattern with two consecutive edge patterns without a vertex pattern in between is not supported +LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH ()-> ->() COLUMNS (1 AS ... + ^ -- select all the properties across all the labels associated with a given type -- of graph element SELECT * FROM GRAPH_TABLE (g1 MATCH (src)-[conn]->(dest) COLUMNS (src.vname AS svname, conn.ename AS cename, dest.vname AS dvname, src.vprop1 AS svp1, src.vprop2 AS svp2, src.lprop1 AS slp1, dest.vprop1 AS dvp1, dest.vprop2 AS dvp2, dest.lprop1 AS dlp1, conn.eprop1 AS cep1, conn.lprop2 AS clp2)); diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 88215ea427a..bbff150a6d9 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -295,6 +295,12 @@ SELECT * FROM GRAPH_TABLE (g1 MATCH (src IS el1 | vl1)-[conn]->(dest) COLUMNS (c SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (c.*)); -- star anywhere else is not allowed as a property reference SELECT * FROM GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.* IS NOT NULL)-[IS customer_orders]->(o IS orders) COLUMNS (c.name)); +-- consecutive element patterns with same kind +SELECT * FROM GRAPH_TABLE (g1 MATCH ()() COLUMNS (1 as one)); +SELECT * FROM GRAPH_TABLE (g1 MATCH -> COLUMNS (1 AS one)); +SELECT * FROM GRAPH_TABLE (g1 MATCH ()-[]- COLUMNS (1 AS one)); +SELECT * FROM GRAPH_TABLE (g1 MATCH ()-> ->() COLUMNS (1 AS one)); + -- select all the properties across all the labels associated with a given type -- of graph element -- 2.34.1
