if (list_member(gpstate->variables, field1))
{
- GraphPropertyRef *gpr = makeNode(GraphPropertyRef);
+ GraphPropertyRef *gpr;
HeapTuple pgptup;
Form_pg_propgraph_property pgpform;
+ /*
+ * If we are transforming expression in an element pattern,
+ * property references containing only that variable are allowed.
+ */
+ if (gpstate->cur_gep)
+ {
+ if (!gpstate->cur_gep->variable ||
+ strcmp(elvarname, gpstate->cur_gep->variable) != 0)
+ ereport(ERROR,
+ errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("non-local element variable reference is not supported"),
+ parser_errposition(pstate, cref->location));
+ }
+
+ gpr = makeNode(GraphPropertyRef);
pgptup = SearchSysCache2(PROPGRAPHPROPNAME, ObjectIdGetDatum(gpstate->graphid), CStringGetDatum(propname));
if (!HeapTupleIsValid(pgptup))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("element pattern quantifier is not supported")));
- if (gep->variable)
- gpstate->variables = list_append_unique(gpstate->variables, makeString(pstrdup(gep->variable)));
+ Assert(!gpstate->cur_gep);
+
+ gpstate->cur_gep = gep;
gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr);
gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE);
assign_expr_collations(pstate, gep->whereClause);
+ gpstate->cur_gep = NULL;
+
return (Node *) gep;
}
transformPathPatternList(ParseState *pstate, List *path_pattern)
{
List *result = NIL;
+ GraphTableParseState *gpstate = pstate->p_graph_table_pstate;
+
+ Assert(gpstate);
/* Grammar doesn't allow empty path pattern list */
Assert(list_length(path_pattern) > 0);
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("multiple path patterns in one GRAPH_TABLE clause not supported")));
+ /*
+ * Collect all the variables in the path pattern into the
+ * GraphTableParseState so that we can detect any non-local element
+ * variable references. We need to do this before transforming the path
+ * pattern so as to detect forward references to element variables in the
+ * WHERE clause of an element pattern.
+ */
+ foreach_node(List, path_term, path_pattern)
+ {
+ foreach_node(GraphElementPattern, gep, path_term)
+ {
+ if (gep->variable)
+ gpstate->variables = list_append_unique(gpstate->variables, makeString(pstrdup(gep->variable)));
+ }
+ }
+
foreach_node(List, path_term, path_pattern)
result = lappend(result, transformPathTerm(pstate, path_term));
Oid graphid; /* OID of the graph being referenced */
List *variables; /* list of element pattern variables in
* GRAPH_TABLE */
+ GraphElementPattern *cur_gep; /* The element pattern being transformed.
+ * NULL if no element pattern is being
+ * transformed. */
} GraphTableParseState;
/*
2 | customer1 | 1 | 1
(2 rows)
+-- non-local property references are not allowed, even if a lateral column
+-- reference is available
+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; -- error
+ERROR: non-local element variable reference is not supported
+LINE 1: ...customer_orders]->(o IS orders WHERE o.order_id = x1.a) COLU...
+ ^
+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; -- error
+ERROR: non-local element variable reference is not supported
+LINE 1: ...tomers WHERE c.address = 'US' AND c.customer_id = x1.a)-[IS ...
+ ^
DROP TABLE x1;
CREATE TABLE v1 (
id int PRIMARY KEY,
ERROR: edge pattern must be preceded by a vertex pattern
LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH ()-> ->() COLUMNS (1 AS ...
^
+-- non-local element variable reference with element patterns without variable
+-- names
+SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, c.vname AS cname));
+ERROR: non-local element variable reference is not supported
+LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[WHERE a.vprop1 = 10...
+ ^
+SELECT * FROM GRAPH_TABLE (g1 MATCH (WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (b.ename AS bname, c.vname AS cname));
+ERROR: non-local element variable reference is not supported
+LINE 1: SELECT * FROM GRAPH_TABLE (g1 MATCH (WHERE b.eprop1 = 10001)...
+ ^
-- 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));
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 WHERE x1.address = 'US')-[IS customer_orders]->(o IS orders) COLUMNS (x1.name AS customer_name, x1.customer_id AS cid, o.order_id)) g;
+-- non-local property references are not allowed, even if a lateral column
+-- reference is available
+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; -- error
+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; -- error
DROP TABLE x1;
CREATE TABLE v1 (
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));
+-- non-local element variable reference with element patterns without variable
+-- names
+SELECT * FROM GRAPH_TABLE (g1 MATCH (a)-[WHERE a.vprop1 = 10]->(c) COLUMNS (a.vname AS aname, c.vname AS cname));
+SELECT * FROM GRAPH_TABLE (g1 MATCH (WHERE b.eprop1 = 10001)-[b]->(c) COLUMNS (b.ename AS bname, c.vname AS cname));
-- select all the properties across all the labels associated with a given type