transformGraphElementPattern() and transformGraphPattern() ran their
WHERE clauses through transformExpr() without ever applying
coerce_to_boolean(), so a WHERE clause of any type was accepted and
its bare datum was used as the qual, which resulted in wrong results
without a diagnostic. Route both sites through
transformWhereClause(), like every other WHERE clause, and add
regression tests for the element-level and pattern-level cases.
Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Chao Li <li.evan.chao@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAON2xHNZUS8ZwzVEJFeRirsC_-7EJvdbwABSzdGaJ_DF9DvHoQ%40mail.gmail.com
Add a test for view containing labels which are shared by both vertex
and edge tables. When such a label is dropped from only vertex tables
or only edge tables, the view may be rendered invalid because it does
not find any elements associated with the label. Right now, you get
an error at run time. It would be correct per SQL standard to make
this a syntax error (parse time error), which would require some
restrict/cascade action when dropping labels. This is not a big
problem, because you still get a clean error, but it might be worth
improving sometime. Add a test case to record the current behavior.
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAExHW5toFV8b984ipuBSAar-W50K%3D%2BXmPOcG5ZUZNP4jrf4zSg%40mail.gmail.com
The COLUMNS list of a GRAPH_TABLE query is parsed as an ordinary select
target list, which permits aggregate functions, window functions, and
set-returning functions. GRAPH_TABLE has no machinery to evaluate them,
though: the rewriter copies the COLUMNS target list verbatim into a
freshly built subquery whose hasAggs/hasWindowFuncs/hasTargetSRFs flags
are never set, so the planner builds no Agg/WindowAgg node (and no SRF
expansion) and the Aggref/WindowFunc/SRF reaches the executor. This
triggers an assertion failure ("ecxt_aggvalues != NULL"), or "Aggref
found in non-Agg plan node" on a non-assert build, for otherwise
parser-accepted SQL such as
SELECT max(c) FROM GRAPH_TABLE
(g MATCH (x IS v) COLUMNS (count(*) AS c));
Reject these constructs in transformRangeGraphTable() the same way
subqueries are already handled: save and clear pstate->p_hasAggs,
p_hasWindowFuncs, and p_hasTargetSRFs around the transformation of the
COLUMNS list, and raise a "not supported" error if any of them got set.
This is deliberately a blanket prohibition for now. Once quantified
element patterns such as (a)->{1,5} are supported, aggregates over
property references of higher degree (e.g. count(a) or sum(a.val)) can
be allowed; at that point the check will need to inspect the aggregate
arguments rather than reject all aggregates outright.
Author: Ewan Young <kdbase.hack@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAON2xHOYAmYLkB2jGi6g77d6Fqv8YgOrfV-riQVf0K_7AdxD3w@mail.gmail.com
get_graph_pattern_def() emitted the pattern-level WHERE keyword as
"WHERE " with no leading space, so reverse-parsing produced output
like "(o IS orders)WHERE (...)". The element-level WHERE deparse in
get_path_pattern_expr_def() already prepends a separating space; the
pattern-level branch was inconsistent with it. Emit " WHERE " to
match.
The output still re-parses to the same tree, so this is cosmetic.
For test coverage, add a whole-pattern WHERE clause to the existing
customers_us view, which is already reverse-parsed with
pg_get_viewdef().
Author: Dhruv Chauhan <chauhandhruv351@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CANWwWcpHb0h7tg6otRnL-FV83jwQpAiyw1bhvv8T78kpwZ-0ow%40mail.gmail.com
replace_property_refs() called expression_tree_mutator() with the root
of the expression tree as the input node. But
expression_tree_mutator() does not call the mutator function on the
root node, so the root node remains unchanged. If the root node is a
property reference or a lateral reference -- the two node kinds that
replace_property_refs_mutator() rewrites -- it is returned unchanged.
Modules after the rewriter do not know about property reference nodes,
resulting in "ERROR: unrecognized node type: 63". Since varlevelsup
of lateral references is not incremented, they are not resolved
correctly in the planner, leading to many different symptoms. Fix
this by calling replace_property_refs_mutator() directly from
replace_property_refs(), similar to how other mutator functions do.
The only case when a property reference or a lateral reference can be
the root of a GRAPH_TABLE expression tree is when it is a bare
property reference or a bare lateral reference in the WHERE clause.
The COLUMNS clause is passed to replace_property_refs() as a
targetlist. Every other expression has at least one expression node
covering the property reference or a lateral reference in the
expression tree. That explains why this bug was not seen so far.
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reported-by: Noah Misch <noah@leadboat.com>
Discussion: https://www.postgresql.org/message-id/flat/20260630173053.51.noahmisch%40microsoft.com
A view definition with GRAPH_TABLE depends upon the property graph it
references as well as the properties and labels referenced in it. We
recorded the dependency on the property graph, but did not record
dependency on labels and properties. This allowed properties or
labels referenced by a view to be dropped, resulting in a cache lookup
error when such a view was accessed. Fix this bug by handling
GraphPropertyRef and GraphLabelRef in find_expr_references_walker().
The dependency on the data type of property does not need to be
recorded separately as it is recorded indirectly via a dependency on
the property graph property itself.
Note that a property or a label associated with individual elements
can still be dropped as long as there are other elements that are
associated with that property or label, since they do not lead to
dropping the property or the label from the property graph altogether.
Reported-by: Man Zeng <zengman@halodbtech.com>
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/tencent_43D9888041FA4FDE498C7BF1%40qq.com
When rewriting a GRAPH_TABLE into a subquery,
replace_property_refs_mutator() bumps levelsup of lateral references
by one so that they reference outside the subquery. This works for
path patterns that result in only one path query. Patterns that
produce multiple path queries are rewritten as a UNION of path
queries. Since every path query becomes a subquery of the UNION
statement, the levelsup of lateral references in those path queries
need an additional bump. This adjustment was missing resulting in the
lateral references being interpreted as references in the UNION query
itself. This caused different symptoms like a crash in
create_lateral_join_info() or error "plan should not reference
subplan's variable". The symptoms varied depending on the number of
RangeTblEntries in the UNION statement.
This commit adds the missing adjustment.
Author: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Author: Satya Narlapuram <satyanarlapuram@gmail.com>
Reviewed-by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAHg%2BQDfnLzsgjaQ_CiKSpP4JH3MKOiwoawEcCzXa9uYr45yiWw%40mail.gmail.com
expression_tree_mutator_impl() did not handle T_GraphPattern,
T_GraphElementPattern, and T_GraphPropertyRef. The corresponding
expression_tree_walker_impl() already handles all three node types.
This causes an "unrecognized node type" error whenever a GRAPH_TABLE
appeared in an expression tree.
While at it, also update raw_expression_tree_walker() and
expression_tree_walker() to handle missing nodes that may appear in
GraphPattern expression trees. When raw_expression_tree_walker() is
called, GraphElementPattern::labelexpr contains ColumnRefs instead of
GraphLabelRefs. Hence those are not handled in
raw_expression_tree_walker().
Author: Satyanarayana Narlapuram <satyanarlapuram@gmail.com>
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Robert Haas <robertmhaas@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAHg%2BQDc97WFTSkXg%3Dg_ZAH8GnY2gJrvq72cs%2BYjqEAuZgXnkAQ%40mail.gmail.com
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 <ashutosh.bapat.oss@gmail.com>
Reported-by: Man Zeng <zengman@halodbtech.com>
Reviewed-by: Henson Choi <assam258@gmail.com>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Discussion: https://www.postgresql.org/message-id/CAExHW5u6AoDfNg4%3DR5eVJn_bJn%3DC%3DwVPrto02P_06fxy39fniA%40mail.gmail.com
Implementation of SQL property graph queries, according to SQL/PGQ
standard (ISO/IEC 9075-16:2023).
This adds:
- GRAPH_TABLE table function for graph pattern matching
- DDL commands CREATE/ALTER/DROP PROPERTY GRAPH
- several new system catalogs and information schema views
- psql \dG command
- pg_get_propgraphdef() function for pg_dump and psql
A property graph is a relation with a new relkind RELKIND_PROPGRAPH.
It acts like a view in many ways. It is rewritten to a standard
relational query in the rewriter. Access privileges act similar to a
security invoker view. (The security definer variant is not currently
implemented.)
Starting documentation can be found in doc/src/sgml/ddl.sgml and
doc/src/sgml/queries.sgml.
Author: Peter Eisentraut <peter@eisentraut.org>
Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
Reviewed-by: Junwang Zhao <zhjwpku@gmail.com>
Reviewed-by: Ajay Pal <ajay.pal.k@gmail.com>
Reviewed-by: Henson Choi <assam258@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/a855795d-e697-4fa5-8698-d20122126567@eisentraut.org