Reject 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 now.  Prohibit such path
patterns.

Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reported-by: Alexander Lakhin <exclusion@gmail.com>
Reviewed-by: Henson Choi <assam258@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/72a23702-6d96-4103-a54b-057c2352e885%2540eisentraut.org
This commit is contained in:
Peter Eisentraut 2026-03-27 10:30:01 +01:00
parent b4a1320224
commit 720f0f89d6
4 changed files with 78 additions and 5 deletions

View file

@ -225,11 +225,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),
@ -253,10 +248,53 @@ 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))
{
if (!prev_gep)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("path pattern cannot start with an edge pattern"),
parser_errposition(pstate, gep->location)));
else if (prev_gep->kind != VERTEX_PATTERN)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("edge pattern must be preceded by a vertex pattern"),
parser_errposition(pstate, gep->location)));
}
else
{
if (prev_gep && !IS_EDGE_PATTERN(prev_gep->kind))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("adjacent vertex patterns are 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);
if (IS_EDGE_PATTERN(prev_gep->kind))
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("path pattern cannot end with an edge pattern"),
parser_errposition(pstate, prev_gep->location)));
}
return (Node *) result;
}

View file

@ -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;

View file

@ -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"
@ -420,6 +422,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: adjacent vertex patterns are 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: 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: 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: edge pattern must be preceded by a vertex pattern
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));

View file

@ -289,6 +289,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