pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
(SQL/PGQ) cache lookup failed for label
26+ messages / 7 participants
[nested] [flat]

Commits from this thread:
  2026-06-09 9d8cdcbe0c  Record dependencies on graph labels and properties
* (SQL/PGQ) cache lookup failed for label
@ 2026-05-08 08:39 =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: zengman @ 2026-05-08 08:39 UTC (permalink / raw)
  To: pgsql-hackers <pgsql-hackers@lists.postgresql.org>; +Cc: Peter Eisentraut <peter@eisentraut.org>; Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>

Hi all, 

I noticed that the following SQL statement triggers the error message `cache lookup failed for label`.

```sql
CREATE TABLE vt (id text PRIMARY KEY, name text, age int);
CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id));
INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25);
INSERT INTO et VALUES ('e1', 'a', 'b');

CREATE PROPERTY GRAPH g                
  VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age))
  EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id));                          

CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname));                                                                                     
                                                                                                                                                                                          
ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2;                                                                                                                                                                       
SELECT * FROM v1;
```

Here are the actual test results; it appears to be caused by missing dependency information.

```sql
test=# CREATE TABLE vt (id text PRIMARY KEY, name text, age int);
CREATE TABLE
test=# CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id));
CREATE TABLE
test=# INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25);
INSERT 0 2
test=# INSERT INTO et VALUES ('e1', 'a', 'b');
INSERT 0 1
test=# CREATE PROPERTY GRAPH g                
  VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age))
  EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id));
CREATE PROPERTY GRAPH
test=# CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname));
CREATE VIEW
test=# ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2; 
ALTER PROPERTY GRAPH
test=# SELECT * FROM v1;
2026-05-08 15:38:37.121 CST [175953] ERROR:  cache lookup failed for label 16472
2026-05-08 15:38:37.121 CST [175953] STATEMENT:  SELECT * FROM v1;
ERROR:  cache lookup failed for label 16472
test=# 
```

I've made some minor modifications; this is my diffs file. I'm not sure if anything is missing, so feel free to add to or supplement it.

```c
inline patch 1: src/backend/catalog/dependency.c (+38/-0 lines) download inline-1.patchdiff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..6a73b74fc9b 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2247,6 +2247,22 @@ find_expr_references_walker(Node *node, context->addrs); /* fall through to examine substructure */ } + if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *lref = (GraphLabelRef *) node; + + add_object_address(PropgraphLabelRelationId, lref->labelid, 0, + context->addrs); + return false; + } + if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + return false; + } else if (IsA(node, Query)) { /* Recurse into RTE subquery or not-yet-planned sublink subquery */ @@ -2277,9 +2293,31 @@ find_expr_references_walker(Node *node, switch (rte->rtekind) { case RTE_RELATION: + add_object_address(RelationRelationId, rte->relid, 0, + context->addrs); + break; case RTE_GRAPH_TABLE: add_object_address(RelationRelationId, rte->relid, 0, context->addrs); + + if (rte->graph_pattern) + { + GraphPattern *gp = rte->graph_pattern; + ListCell *lc1; + + foreach(lc1, gp->path_pattern_list) + { + List *path_term = lfirst_node(List, lc1); + ListCell *lc2; + + foreach(lc2, path_term) + { + GraphElementPattern *gep = lfirst_node(GraphElementPattern, lc2); + + find_expr_references_walker(gep->labelexpr, context); + } + } + } break; case RTE_JOIN:
``` Final running results ```sql test=# CREATE TABLE vt (id text PRIMARY KEY, name text, age int); CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id)); INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25); INSERT INTO et VALUES ('e1', 'a', 'b'); CREATE PROPERTY GRAPH g VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age)) EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id)); CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname)); ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2; SELECT * FROM v1; CREATE TABLE CREATE TABLE INSERT 0 2 INSERT 0 1 CREATE PROPERTY GRAPH CREATE VIEW 2026-05-08 16:24:59.938 CST [182833] ERROR: cannot drop label l2 of property graph g because other objects depend on it 2026-05-08 16:24:59.938 CST [182833] DETAIL: view v1 depends on label l2 of property graph g 2026-05-08 16:24:59.938 CST [182833] HINT: Use DROP ... CASCADE to drop the dependent objects too. 2026-05-08 16:24:59.938 CST [182833] STATEMENT: ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2; ERROR: cannot drop label l2 of property graph g because other objects depend on it DETAIL: view v1 depends on label l2 of property graph g HINT: Use DROP ... CASCADE to drop the dependent objects too. name | age | bname -------+-----+------- Alice | 30 | Bob (1 row) ``` -- regards, Man Zeng ^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
@ 2026-05-12 11:58 ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-05-12 11:58 UTC (permalink / raw)
  To: zengman <zengman@halodbtech.com>; +Cc: pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Fri, May 8, 2026 at 2:10 PM zengman <zengman@halodbtech.com> wrote:
>
> Hi all,
>
> I noticed that the following SQL statement triggers the error message `cache lookup failed for label`.
>
> ```sql
> CREATE TABLE vt (id text PRIMARY KEY, name text, age int);
> CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id));
> INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25);
> INSERT INTO et VALUES ('e1', 'a', 'b');
>
> CREATE PROPERTY GRAPH g
>   VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age))
>   EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id));
>
> CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname));
>
> ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2;
> SELECT * FROM v1;
> ```
>
> Here are the actual test results; it appears to be caused by missing dependency information.
>
> ```sql
> test=# CREATE TABLE vt (id text PRIMARY KEY, name text, age int);
> CREATE TABLE
> test=# CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id));
> CREATE TABLE
> test=# INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25);
> INSERT 0 2
> test=# INSERT INTO et VALUES ('e1', 'a', 'b');
> INSERT 0 1
> test=# CREATE PROPERTY GRAPH g
>   VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age))
>   EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id));
> CREATE PROPERTY GRAPH
> test=# CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname));
> CREATE VIEW
> test=# ALTER PROPERTY GRAPH g ALTER VERTEX TABLE vt DROP LABEL l2;
> ALTER PROPERTY GRAPH
> test=# SELECT * FROM v1;
> 2026-05-08 15:38:37.121 CST [175953] ERROR:  cache lookup failed for label 16472
> 2026-05-08 15:38:37.121 CST [175953] STATEMENT:  SELECT * FROM v1;
> ERROR:  cache lookup failed for label 16472
> test=#
> ```
>
> I've made some minor modifications; this is my diffs file. I'm not sure if anything is missing, so feel free to add to or supplement it.

Thanks for the report and the fix. Can you please create a patch/diff
file and attach it to the email please? It's easy to apply an
attachment than copying diff to a file and then applying it.

Please find some comments.

>
> ```c
> diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
> index fdb8e67e1f5..6a73b74fc9b 100644
> --- a/src/backend/catalog/dependency.c
> +++ b/src/backend/catalog/dependency.c
> @@ -2247,6 +2247,22 @@ find_expr_references_walker(Node *node,
>                                                            context->addrs);
>                 /* fall through to examine substructure */
>         }
> +       if (IsA(node, GraphLabelRef))
> +       {
> +               GraphLabelRef *lref = (GraphLabelRef *) node;
> +
> +               add_object_address(PropgraphLabelRelationId, lref->labelid, 0,
> +                                                  context->addrs);
> +               return false;
> +       }
> +       if (IsA(node, GraphPropertyRef))
> +       {
> +               GraphPropertyRef *gpr = (GraphPropertyRef *) node;
> +
> +               add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
> +                                                  context->addrs);
> +               return false;
> +       }
>         else if (IsA(node, Query))
>         {
>                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
> @@ -2277,9 +2293,31 @@ find_expr_references_walker(Node *node,
>                         switch (rte->rtekind)
>                         {
>                                 case RTE_RELATION:
> +                                       add_object_address(RelationRelationId, rte->relid, 0,
> +                                                                          context->addrs);
> +                                       break;
>                                 case RTE_GRAPH_TABLE:
>                                         add_object_address(RelationRelationId, rte->relid, 0,
>                                                                            context->addrs);
> +
> +                                       if (rte->graph_pattern)
> +                                       {
> +                                               GraphPattern *gp = rte->graph_pattern;
> +                                               ListCell   *lc1;
> +
> +                                               foreach(lc1, gp->path_pattern_list)
> +                                               {
> +                                                       List       *path_term = lfirst_node(List, lc1);
> +                                                       ListCell   *lc2;
> +
> +                                                       foreach(lc2, path_term)
> +                                                       {
> +                                                               GraphElementPattern *gep = lfirst_node(GraphElementPattern, lc2);
> +
> +                                                               find_expr_references_walker(gep->labelexpr, context);
> +                                                       }
> +                                               }
> +                                       }

You could use foreach_node() instead of foreach(). But I am wondering
whether we can directly call find_expr_references_walker() on
rte->graph_pattern. We need to walk rte->graph_table_columns as well.

>                                         break;
>                                 case RTE_JOIN:
>
> ```
>
>
> Final running results
>
> ```sql
> test=# CREATE TABLE vt (id text PRIMARY KEY, name text, age int);
> CREATE TABLE et (id text PRIMARY KEY, src text REFERENCES vt(id), dst text REFERENCES vt(id));
> INSERT INTO vt VALUES ('a', 'Alice', 30), ('b', 'Bob', 25);
> INSERT INTO et VALUES ('e1', 'a', 'b');
>
> CREATE PROPERTY GRAPH g
>   VERTEX TABLES (vt LABEL l1 PROPERTIES (name) LABEL l2 PROPERTIES (name, age))
>   EDGE TABLES (et SOURCE KEY (src) REFERENCES vt(id) DESTINATION KEY (dst) REFERENCES vt(id));
>
> CREATE VIEW v1 AS SELECT * FROM GRAPH_TABLE(g MATCH (a IS l2)-[e IS et]->(b IS l2) COLUMNS (a.name, a.age, b.name AS bname));

The patch needs a test. graph_table.sql already has some view
definitions, some of them using elements with multiple labels. Can you
please add a test using those views? For example after CREATE VIEW
customer_us, you could add a statement dropping label list_items from
all of the elements associated with that label. I guess
pg_get_viewdef() itself should throw an error with the fix, but you
could select from that view as well, if necessary. We also need a test
for drop property. Remember that the property is completely dropped
from a property graph only when it is dropped from all the labels
containing that property. Please apply patches from [1] before adding
tests to your patch. With those patches added your test queries above
will throw a different error.

[1] https://www.postgresql.org/message-id/CAExHW5tCCQhgDEfBTKWqe7bDqCUXhPpsqoGipL7Vpf0epcKkXA@mail.gmail...
-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-05-14 14:07   ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: zengman @ 2026-05-14 14:07 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

> The patch needs a test. graph_table.sql already has some view
> definitions, some of them using elements with multiple labels. Can you
> please add a test using those views? For example after CREATE VIEW
> customer_us, you could add a statement dropping label list_items from
> all of the elements associated with that label. I guess
> pg_get_viewdef() itself should throw an error with the fix, but you
> could select from that view as well, if necessary. We also need a test
> for drop property. Remember that the property is completely dropped
> from a property graph only when it is dropped from all the labels
> containing that property. Please apply patches from [1] before adding
> tests to your patch. With those patches added your test queries above
> will throw a different error.
> 
> [1] https://www.postgresql.org/message-id/CAExHW5tCCQhgDEfBTKWqe7bDqCUXhPpsqoGipL7Vpf0epcKkXA@mail.gmail...
> 

Hi Ashutosh,

Thank you for the review and sorry for the late reply. I'm currently busy with company projects and may not have time to work on this right now.
If this is urgent, would you mind handling it? If it can wait, I'll come back and fix it when I have more availability.

--
regards,
Man Zeng

^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
@ 2026-05-15 10:37     ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ayush Tiwari @ 2026-05-15 10:37 UTC (permalink / raw)
  To: zengman <zengman@halodbtech.com>; +Cc: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Thu, 14 May 2026 at 19:37, zengman <zengman@halodbtech.com> wrote:

> > The patch needs a test. graph_table.sql already has some view
> > definitions, some of them using elements with multiple labels. Can you
> > please add a test using those views? For example after CREATE VIEW
> > customer_us, you could add a statement dropping label list_items from
> > all of the elements associated with that label. I guess
> > pg_get_viewdef() itself should throw an error with the fix, but you
> > could select from that view as well, if necessary. We also need a test
> > for drop property. Remember that the property is completely dropped
> > from a property graph only when it is dropped from all the labels
> > containing that property. Please apply patches from [1] before adding
> > tests to your patch. With those patches added your test queries above
> > will throw a different error.
> >
> > [1]
> https://www.postgresql.org/message-id/CAExHW5tCCQhgDEfBTKWqe7bDqCUXhPpsqoGipL7Vpf0epcKkXA@mail.gmail...
> >
>
> Hi Ashutosh,
>
> Thank you for the review and sorry for the late reply. I'm currently busy
> with company projects and may not have time to work on this right now.
> If this is urgent, would you mind handling it? If it can wait, I'll come
> back and fix it when I have more availability.
>

Thanks for the report.

I went through the thread and have attached a small patch for this.

The issue is that views/rules over GRAPH_TABLE store GraphLabelRef and
GraphPropertyRef nodes in the pg_rewrite parsetree, but dependency.c did
not record dependencies for those node types.  So a view could depend on
label/property OIDs that were later removed by ALTER PROPERTY GRAPH, and
then fail at execution with "cache lookup failed for label".

The patch adds dependency walker cases for GraphLabelRef and
GraphPropertyRef.  I didn't add any special traversal for RTE_GRAPH_TABLE.
query_tree_walker() already descends into rte->graph_pattern and
rte->graph_table_columns, so recognizing those two leaf nodes should be
enough?

I also added regression coverage for both cases:

  DROP LABEL of a label used by a GRAPH_TABLE view
  DROP PROPERTIES of a property used by a GRAPH_TABLE view

Both now fail with the normal dependency error until the view is dropped.

Thoughts?

Regards,
Ayush

Attachments:

v1-0001-SQL-PGQ-Record-dependencies-on-graph-labels-and-p.patch (application/octet-stream, 6.5K) download From b3388d6aaa75c6a8e516af8a120f3479f18a4724 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari <ayushtiwari.slg01@gmail.com> Date: Fri, 15 May 2026 09:55:59 +0000 Subject: [PATCH v1] SQL/PGQ: Record dependencies on graph labels and properties When a view or rule references a property graph via a GRAPH_TABLE clause, the parsetree stored in pg_rewrite contains GraphLabelRef and GraphPropertyRef nodes that point at pg_propgraph_label and pg_propgraph_property entries. find_expr_references_walker() did not have cases for these nodes, so only the property graph relation itself acquired a pg_depend entry. Labels and properties used by the stored query could then be dropped via ALTER PROPERTY GRAPH ... DROP LABEL / DROP PROPERTIES, leaving the view to fail later at execution with "cache lookup failed for label NNN". Add cases for the two graph-table node types so that each referenced label and property gets a normal dependency on the view. No new traversal is needed: query_tree_walker() already descends into rte->graph_pattern and rte->graph_table_columns, and through them into GraphElementPattern->labelexpr and the GraphPropertyRef expressions in the COLUMNS list. Add a regression test in graph_table that creates a view referencing a multi-label vertex and then exercises DROP LABEL and DROP PROPERTIES. Both commands are now rejected with the standard dependency error, and succeed once the view is dropped. Reported-by: Man Zeng <zengman@halodbtech.com> Discussion: https://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 +++++++++++++++ src/test/regress/expected/graph_table.out | 29 +++++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 24 +++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..dc570e907f6 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* + * GRAPH_TABLE label reference: depend on the label catalog entry. + * No expression substructure to recurse into. + */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* GRAPH_TABLE property reference: depend on the property entry. */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cc6d80afd82..3346fd6e0e9 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -942,6 +942,35 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +CREATE TABLE depv (id int PRIMARY KEY, name text, addr text); +CREATE TABLE depe (id int PRIMARY KEY, + src int REFERENCES depv(id), + dst int REFERENCES depv(id)); +CREATE PROPERTY GRAPH depg + VERTEX TABLES (depv LABEL l1 PROPERTIES (name) + LABEL l2 PROPERTIES (name, addr)) + EDGE TABLES (depe + SOURCE KEY (src) REFERENCES depv (id) + DESTINATION KEY (dst) REFERENCES depv (id)); +CREATE VIEW depv_view AS + SELECT * FROM GRAPH_TABLE (depg MATCH (a IS l2)-[e IS depe]->(b IS l2) + COLUMNS (a.name, a.addr, b.name AS bname)); +ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2; -- error +ERROR: cannot drop label l2 of property graph depg because other objects depend on it +DETAIL: view depv_view depends on label l2 of property graph depg +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH depg + ALTER VERTEX TABLE depv ALTER LABEL l2 + DROP PROPERTIES (addr); -- error +ERROR: cannot drop property addr of property graph depg because other objects depend on it +DETAIL: view depv_view depends on property addr of property graph depg +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP VIEW depv_view; +ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2; +DROP PROPERTY GRAPH depg; +DROP TABLE depe, depv; -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0e381ec72bc..61ee148a879 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -536,6 +536,30 @@ SELECT g.* FROM x1, ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +CREATE TABLE depv (id int PRIMARY KEY, name text, addr text); +CREATE TABLE depe (id int PRIMARY KEY, + src int REFERENCES depv(id), + dst int REFERENCES depv(id)); +CREATE PROPERTY GRAPH depg + VERTEX TABLES (depv LABEL l1 PROPERTIES (name) + LABEL l2 PROPERTIES (name, addr)) + EDGE TABLES (depe + SOURCE KEY (src) REFERENCES depv (id) + DESTINATION KEY (dst) REFERENCES depv (id)); +CREATE VIEW depv_view AS + SELECT * FROM GRAPH_TABLE (depg MATCH (a IS l2)-[e IS depe]->(b IS l2) + COLUMNS (a.name, a.addr, b.name AS bname)); +ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2; -- error +ALTER PROPERTY GRAPH depg + ALTER VERTEX TABLE depv ALTER LABEL l2 + DROP PROPERTIES (addr); -- error +DROP VIEW depv_view; +ALTER PROPERTY GRAPH depg ALTER VERTEX TABLE depv DROP LABEL l2; +DROP PROPERTY GRAPH depg; +DROP TABLE depe, depv; + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; -- 2.43.0
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
@ 2026-05-15 10:55       ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ayush Tiwari @ 2026-05-15 10:55 UTC (permalink / raw)
  To: zengman <zengman@halodbtech.com>; +Cc: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi,


On Fri, 15 May 2026 at 16:07, Ayush Tiwari <ayushtiwari.slg01@gmail.com>
wrote:

> Hi,
>
> On Thu, 14 May 2026 at 19:37, zengman <zengman@halodbtech.com> wrote:
>
>> > The patch needs a test. graph_table.sql already has some view
>> > definitions, some of them using elements with multiple labels. Can you
>> > please add a test using those views? For example after CREATE VIEW
>> > customer_us, you could add a statement dropping label list_items from
>> > all of the elements associated with that label. I guess
>> > pg_get_viewdef() itself should throw an error with the fix, but you
>> > could select from that view as well, if necessary. We also need a test
>> > for drop property. Remember that the property is completely dropped
>> > from a property graph only when it is dropped from all the labels
>> > containing that property. Please apply patches from [1] before adding
>> > tests to your patch. With those patches added your test queries above
>> > will throw a different error.
>> >
>> > [1]
>> https://www.postgresql.org/message-id/CAExHW5tCCQhgDEfBTKWqe7bDqCUXhPpsqoGipL7Vpf0epcKkXA@mail.gmail...
>> >
>>
>> Hi Ashutosh,
>>
>> Thank you for the review and sorry for the late reply. I'm currently busy
>> with company projects and may not have time to work on this right now.
>> If this is urgent, would you mind handling it? If it can wait, I'll come
>> back and fix it when I have more availability.
>>
>
> Thanks for the report.
>
> I went through the thread and have attached a small patch for this.
>
> The issue is that views/rules over GRAPH_TABLE store GraphLabelRef and
> GraphPropertyRef nodes in the pg_rewrite parsetree, but dependency.c did
> not record dependencies for those node types.  So a view could depend on
> label/property OIDs that were later removed by ALTER PROPERTY GRAPH, and
> then fail at execution with "cache lookup failed for label".
>
> The patch adds dependency walker cases for GraphLabelRef and
> GraphPropertyRef.  I didn't add any special traversal for RTE_GRAPH_TABLE.
> query_tree_walker() already descends into rte->graph_pattern and
> rte->graph_table_columns, so recognizing those two leaf nodes should be
> enough?
>
> I also added regression coverage for both cases:
>
>   DROP LABEL of a label used by a GRAPH_TABLE view
>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
>
> Both now fail with the normal dependency error until the view is dropped.
>
> Thoughts?
>
>
Attaching v2 that uses existing views for test cases.

Regards,
Ayush

Attachments:

v2-0001-SQL-PGQ-Record-dependencies-on-graph-labels-and-p.patch (application/octet-stream, 5.4K) download From 1b811ab168cf6060985520724915141dbad80b75 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari <ayushtiwari.slg01@gmail.com> Date: Fri, 15 May 2026 10:51:39 +0000 Subject: [PATCH v2] SQL/PGQ: Record dependencies on graph labels and properties When a view or rule references a property graph via a GRAPH_TABLE clause, the parsetree stored in pg_rewrite contains GraphLabelRef and GraphPropertyRef nodes that point at pg_propgraph_label and pg_propgraph_property entries. find_expr_references_walker() did not have cases for these nodes, so only the property graph relation itself acquired a pg_depend entry. Labels and properties used by the stored query could then be dropped via ALTER PROPERTY GRAPH ... DROP LABEL / DROP PROPERTIES, leaving the view to fail later at execution with "cache lookup failed for label NNN". Add cases for the two graph-table node types so that each referenced label and property gets a normal dependency on the view. No new traversal is needed: query_tree_walker() already descends into rte->graph_pattern and rte->graph_table_columns, and through them into GraphElementPattern->labelexpr and the GraphPropertyRef expressions in the COLUMNS list. Add regression tests using the existing myshop property graph and customers_us view. The tests check that DROP LABEL and DROP PROPERTIES are rejected with the standard dependency error while the view depends on the referenced label/property. Reported-by: Man Zeng <zengman@halodbtech.com> Discussion: https://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 +++++++++++++++++++ src/test/regress/expected/graph_table.out | 15 +++++++++++++++ src/test/regress/sql/graph_table.sql | 10 ++++++++++ 3 files changed, 44 insertions(+) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..dc570e907f6 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* + * GRAPH_TABLE label reference: depend on the label catalog entry. + * No expression substructure to recurse into. + */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* GRAPH_TABLE property reference: depend on the property entry. */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cc6d80afd82..2b65530bf7f 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -942,6 +942,21 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items; +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items + DROP LABEL list_items; -- error +ERROR: cannot drop label list_items of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on label list_items of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ERROR: cannot drop property address of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property address of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0e381ec72bc..1a1a9fc0e14 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -536,6 +536,16 @@ SELECT g.* FROM x1, ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items; +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items + DROP LABEL list_items; -- error +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; -- 2.43.0
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
@ 2026-05-15 15:01         ` Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Junwang Zhao @ 2026-05-15 15:01 UTC (permalink / raw)
  To: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; +Cc: zengman <zengman@halodbtech.com>; Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi Ayush,

On Fri, May 15, 2026 at 6:55 PM Ayush Tiwari
<ayushtiwari.slg01@gmail.com> wrote:
>
> Hi,
>
>
> On Fri, 15 May 2026 at 16:07, Ayush Tiwari <ayushtiwari.slg01@gmail.com> wrote:
>>
>> Hi,
>>
>> On Thu, 14 May 2026 at 19:37, zengman <zengman@halodbtech.com> wrote:
>>>
>>> > The patch needs a test. graph_table.sql already has some view
>>> > definitions, some of them using elements with multiple labels. Can you
>>> > please add a test using those views? For example after CREATE VIEW
>>> > customer_us, you could add a statement dropping label list_items from
>>> > all of the elements associated with that label. I guess
>>> > pg_get_viewdef() itself should throw an error with the fix, but you
>>> > could select from that view as well, if necessary. We also need a test
>>> > for drop property. Remember that the property is completely dropped
>>> > from a property graph only when it is dropped from all the labels
>>> > containing that property. Please apply patches from [1] before adding
>>> > tests to your patch. With those patches added your test queries above
>>> > will throw a different error.
>>> >
>>> > [1] https://www.postgresql.org/message-id/CAExHW5tCCQhgDEfBTKWqe7bDqCUXhPpsqoGipL7Vpf0epcKkXA@mail.gmail...
>>> >
>>>
>>> Hi Ashutosh,
>>>
>>> Thank you for the review and sorry for the late reply. I'm currently busy with company projects and may not have time to work on this right now.
>>> If this is urgent, would you mind handling it? If it can wait, I'll come back and fix it when I have more availability.
>>
>>
>> Thanks for the report.
>>
>> I went through the thread and have attached a small patch for this.
>>
>> The issue is that views/rules over GRAPH_TABLE store GraphLabelRef and
>> GraphPropertyRef nodes in the pg_rewrite parsetree, but dependency.c did
>> not record dependencies for those node types.  So a view could depend on
>> label/property OIDs that were later removed by ALTER PROPERTY GRAPH, and
>> then fail at execution with "cache lookup failed for label".
>>
>> The patch adds dependency walker cases for GraphLabelRef and
>> GraphPropertyRef.  I didn't add any special traversal for RTE_GRAPH_TABLE.
>> query_tree_walker() already descends into rte->graph_pattern and
>> rte->graph_table_columns, so recognizing those two leaf nodes should be
>> enough?

WFM.

>>
>> I also added regression coverage for both cases:
>>
>>   DROP LABEL of a label used by a GRAPH_TABLE view
>>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
>>
>> Both now fail with the normal dependency error until the view is dropped.
>>
>> Thoughts?

I'd suggest adding two stmts to the regression that can cover that walk of
graph_table_columns is also working.

[local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
(name);
ALTER PROPERTY GRAPH
Time: 1.312 ms

[local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
(name);
ERROR:  cannot drop property name of property graph myshop because
other objects depend on it
DETAIL:  view customers_us depends on property name of property graph myshop
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
Time: 2.231 ms

>>
>
> Attaching v2 that uses existing views for test cases.
>
> Regards,
> Ayush



-- 
Regards
Junwang Zhao





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
@ 2026-05-15 15:13           ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ayush Tiwari @ 2026-05-15 15:13 UTC (permalink / raw)
  To: Junwang Zhao <zhjwpku@gmail.com>; +Cc: zengman <zengman@halodbtech.com>; Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi,


On Fri, 15 May 2026 at 20:31, Junwang Zhao <zhjwpku@gmail.com> wrote:

> Hi Ayush,
>
> >>
> >> I also added regression coverage for both cases:
> >>
> >>   DROP LABEL of a label used by a GRAPH_TABLE view
> >>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
> >>
> >> Both now fail with the normal dependency error until the view is
> dropped.
> >>
> >> Thoughts?
>
> I'd suggest adding two stmts to the regression that can cover that walk of
> graph_table_columns is also working.
>
> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
> (name);
> ALTER PROPERTY GRAPH
> Time: 1.312 ms
>
> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
> (name);
> ERROR:  cannot drop property name of property graph myshop because
> other objects depend on it
> DETAIL:  view customers_us depends on property name of property graph
> myshop
> HINT:  Use DROP ... CASCADE to drop the dependent objects too.
> Time: 2.231 ms
>
>
Good point, thanks.  I added that coverage in the attached v3.

The test now also drops customers.name first, which is allowed because the
graph-level property still exists via products.name, and then verifies that
dropping products.name is rejected with the dependency error from
customers_us.  That should cover GraphPropertyRef nodes reached through the
GRAPH_TABLE COLUMNS list, in addition to the existing label and
graph-pattern
property cases.

I re-added customers.name afterward so the existing myshop graph remains
unchanged for the following tests.

Regards,
Ayush

Attachments:

v3-0001-SQL-PGQ-Record-dependencies-on-graph-labels-and-p.patch (application/octet-stream, 6.4K) download From 984f5b8793fff4dc7d4c0ab089925b77923b4ef1 Mon Sep 17 00:00:00 2001 From: Ayush Tiwari <ayushtiwari.slg01@gmail.com> Date: Fri, 15 May 2026 15:08:37 +0000 Subject: [PATCH v3] SQL/PGQ: Record dependencies on graph labels and properties When a view or rule references a property graph via a GRAPH_TABLE clause, the parsetree stored in pg_rewrite contains GraphLabelRef and GraphPropertyRef nodes that point at pg_propgraph_label and pg_propgraph_property entries. find_expr_references_walker() did not have cases for these nodes, so only the property graph relation itself acquired a pg_depend entry. Labels and properties used by the stored query could then be dropped via ALTER PROPERTY GRAPH ... DROP LABEL / DROP PROPERTIES, leaving the view to fail later at execution with "cache lookup failed for label NNN". Add cases for the two graph-table node types so that each referenced label and property gets a normal dependency on the view. No new traversal is needed: query_tree_walker() already descends into rte->graph_pattern and rte->graph_table_columns, and through them into GraphElementPattern->labelexpr and the GraphPropertyRef expressions in the COLUMNS list. Add regression tests using the existing myshop property graph and customers_us view. The tests check that DROP LABEL and DROP PROPERTIES are rejected with the standard dependency error while the view depends on a referenced label, a property used in the graph pattern, or a property used in the GRAPH_TABLE COLUMNS list. Reported-by: Man Zeng <zengman@halodbtech.com> Discussion: https://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 ++++++++++++++++++ src/test/regress/expected/graph_table.out | 24 +++++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 16 +++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..dc570e907f6 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* + * GRAPH_TABLE label reference: depend on the label catalog entry. + * No expression substructure to recurse into. + */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* GRAPH_TABLE property reference: depend on the property entry. */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cc6d80afd82..70a2d474e26 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -942,6 +942,30 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items; +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items + DROP LABEL list_items; -- error +ERROR: cannot drop label list_items of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on label list_items of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ERROR: cannot drop property address of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property address of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (name); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (name); -- error +ERROR: cannot drop property name of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property name of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers ADD PROPERTIES (name); -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0e381ec72bc..0116b4216d9 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -536,6 +536,22 @@ SELECT g.* FROM x1, ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); +-- A view defined over GRAPH_TABLE should record dependencies on the labels +-- and properties it references, so they cannot be dropped from under it. +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items; +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items + DROP LABEL list_items; -- error +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (name); +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (name); -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers ADD PROPERTIES (name); + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; -- 2.43.0
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
@ 2026-05-17 23:29             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-05-17 23:29 UTC (permalink / raw)
  To: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Fri, May 15, 2026 at 8:43 PM Ayush Tiwari
<ayushtiwari.slg01@gmail.com> wrote:
>
> Hi,
>
>
> On Fri, 15 May 2026 at 20:31, Junwang Zhao <zhjwpku@gmail.com> wrote:
>>
>> Hi Ayush,
>>
>> >>
>> >> I also added regression coverage for both cases:
>> >>
>> >>   DROP LABEL of a label used by a GRAPH_TABLE view
>> >>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
>> >>
>> >> Both now fail with the normal dependency error until the view is dropped.
>> >>
>> >> Thoughts?
>>
>> I'd suggest adding two stmts to the regression that can cover that walk of
>> graph_table_columns is also working.
>>
>> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
>> ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
>> (name);
>> ALTER PROPERTY GRAPH
>> Time: 1.312 ms
>>
>> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
>> ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
>> (name);
>> ERROR:  cannot drop property name of property graph myshop because
>> other objects depend on it
>> DETAIL:  view customers_us depends on property name of property graph myshop
>> HINT:  Use DROP ... CASCADE to drop the dependent objects too.
>> Time: 2.231 ms
>>
>
> Good point, thanks.  I added that coverage in the attached v3.
>
> The test now also drops customers.name first, which is allowed because the
> graph-level property still exists via products.name, and then verifies that
> dropping products.name is rejected with the dependency error from
> customers_us.  That should cover GraphPropertyRef nodes reached through the
> GRAPH_TABLE COLUMNS list, in addition to the existing label and graph-pattern
> property cases.
>
> I re-added customers.name afterward so the existing myshop graph remains
> unchanged for the following tests.

Thanks Ayush for working on this and providing the patch. Thanks
Junwang for reviewing it.

I have some more comments.

}
+ else if (IsA(node, GraphLabelRef))
+ {
+ GraphLabelRef *glr = (GraphLabelRef *) node;
+
+ /*
+ * GRAPH_TABLE label reference: depend on the label catalog entry.
+ * No expression substructure to recurse into.

That comment is correct, however, the case doesn't return false,
giving an impression that we are recursing into the substructure.
expression_tree_walker() then returns false. But I am seeing an
inconsistency in when to "return false" and when not to. For example,
for some primitive nodes in expression_tree_walker() like Var, this
function returns false. But for other primitive nodes like Param it
doesn't. And there's not comment explaining this difference. I guess
newer additions to this function are relying on expression_tree_walker
to return false. So I just removed the misleading comment and let the
two new nodes rely on expression_tree_walker().

+ */
+ add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
+ context->addrs);
+ }
+ else if (IsA(node, GraphPropertyRef))
+ {
+ GraphPropertyRef *gpr = (GraphPropertyRef *) node;
+
+ /* GRAPH_TABLE property reference: depend on the property entry. */
+ add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
+ context->addrs);
+ }

@@ -536,6 +536,22 @@ SELECT g.* FROM x1,
ORDER BY customer_name, product_name;
SELECT pg_get_viewdef('customers_us'::regclass);
+-- A view defined over GRAPH_TABLE should record dependencies on the labels
+-- and properties it references, so they cannot be dropped from under it.
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items;
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
+ DROP LABEL list_items; -- error
+ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
+ ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+ ALTER LABEL customers DROP PROPERTIES (address); -- error
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+ ALTER LABEL customers DROP PROPERTIES (name);
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
+ ALTER LABEL products DROP PROPERTIES (name); -- error
+ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
+ ALTER LABEL customers ADD PROPERTIES (name);
+

Without the code changes, we do not see "cache lookup failed for label
" error, because there is nothing that uses this view after the drop.
In the attached patch, I have moved the DDL statements before
pg_get_viewdef() which throws "cache lookup failed" error without code
changes and for every DDL statement when we try it separately.

My earlier comment or the test by Man might have misled you into
thinking that we need to drop properties or labels which are defined
multiple times so that we test that the dependency error does not
trigger when a property or a label is not orphaned. Sorry if that's
the case. I don't think that's the goal here. Further, such tests
require additional DDL to restore property graph state and also change
the view definition produced by pg_get_viewdef(). So I used DDLs that
drop properties or labels which are defined only once.

I shortened the commit message by taking essential elements from your
commit message.

Please review the attached patch.


--
Best Wishes,
Ashutosh Bapat

Attachments:

v20260517-0001-Prevent-dropping-the-last-label-from-a-pro.patch (text/x-patch, 10.1K) download From e1493ab6f15a63b7261b41040a76772f0688713f Mon Sep 17 00:00:00 2001 From: satyanarayana narlapuram <satyanarlapuram@gmail.com> Date: Tue, 21 Apr 2026 07:52:56 +0000 Subject: [PATCH v20260517 1/5] Prevent dropping the last label from a property graph element Per SQL/PGQ standard, every graph element must have at least one label. When dropping a label from a graph element, ensure that there exists at least one other label on the element. If the label being dropped is the only label on the element, raise an error. Add a test to make sure that dropping labels concurrently from the same element has the same effect. Reported By: Satyanarayana Narlapuram <satyanarlapuram@gmail.com> Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Author: Satyanarayana Narlapuram <satyanarlapuram@gmail.com> Reviewed by: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/CAHg+QDeP=mTHTV48R23zKMy1SBmCKZ_L7-z5zKnYyw+K0x-gCg@mail.gmail.com --- doc/src/sgml/ref/alter_property_graph.sgml | 4 +- src/backend/commands/propgraphcmds.c | 54 +++++++++++++++++-- .../drop-propgraph-label-concurrently.out | 20 +++++++ src/test/isolation/isolation_schedule | 1 + .../drop-propgraph-label-concurrently.spec | 36 +++++++++++++ .../expected/create_property_graph.out | 6 +++ .../regress/sql/create_property_graph.sql | 4 ++ 7 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 src/test/isolation/expected/drop-propgraph-label-concurrently.out create mode 100644 src/test/isolation/specs/drop-propgraph-label-concurrently.spec diff --git a/doc/src/sgml/ref/alter_property_graph.sgml b/doc/src/sgml/ref/alter_property_graph.sgml index f517f2b2d7a..2fd0c138e12 100644 --- a/doc/src/sgml/ref/alter_property_graph.sgml +++ b/doc/src/sgml/ref/alter_property_graph.sgml @@ -99,7 +99,9 @@ ALTER PROPERTY GRAPH [ IF EXISTS ] <replaceable class="parameter">name</replacea <term><literal>ALTER {VERTEX|NODE|EDGE|RELATIONSHIP} TABLE ... DROP LABEL</literal></term> <listitem> <para> - This form removes a label from an existing vertex or edge table. + This form removes a label from an existing vertex or edge table. The + last label on an element table cannot be dropped; every vertex or edge + table must have at least one label. </para> </listitem> </varlistentry> diff --git a/src/backend/commands/propgraphcmds.c b/src/backend/commands/propgraphcmds.c index cc516e27020..59b2f76ca4f 100644 --- a/src/backend/commands/propgraphcmds.c +++ b/src/backend/commands/propgraphcmds.c @@ -1491,8 +1491,14 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt) { Oid peoid; Oid labeloid; - Oid ellabeloid; + Oid ellabeloid = InvalidOid; ObjectAddress obj; + Relation ellabelrel; + SysScanDesc ellabelscan; + ScanKeyData ellabelkey[1]; + int nlabels = 0; + HeapTuple tuple; + if (stmt->element_kind == PROPGRAPH_ELEMENT_KIND_VERTEX) peoid = get_vertex_oid(pstate, pgrelid, stmt->element_alias, -1); @@ -1510,11 +1516,38 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt) get_rel_name(pgrelid), stmt->element_alias, stmt->drop_label), parser_errposition(pstate, -1)); - ellabeloid = GetSysCacheOid2(PROPGRAPHELEMENTLABELELEMENTLABEL, - Anum_pg_propgraph_element_label_oid, - ObjectIdGetDatum(peoid), - ObjectIdGetDatum(labeloid)); + /* + * Is the given label associated with the element? Is this the only + * label associated with the element? + */ + ellabelrel = table_open(PropgraphElementLabelRelationId, AccessShareLock); + ScanKeyInit(&ellabelkey[0], + Anum_pg_propgraph_element_label_pgelelid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(peoid)); + ellabelscan = systable_beginscan(ellabelrel, PropgraphElementLabelElementLabelIndexId, + true, NULL, 1, ellabelkey); + while (HeapTupleIsValid(tuple = systable_getnext(ellabelscan))) + { + Form_pg_propgraph_element_label ellabelform = (Form_pg_propgraph_element_label) GETSTRUCT(tuple); + + nlabels++; + if (ellabelform->pgellabelid == labeloid) + ellabeloid = ellabelform->oid; + + /* + * If we find more than one label associated with the given + * element and also found the label we are going to drop, we are + * done. + */ + if (nlabels > 1 && ellabeloid) + break; + } + systable_endscan(ellabelscan); + table_close(ellabelrel, AccessShareLock); + + /* Given label is not associated with the element. */ if (!ellabeloid) ereport(ERROR, errcode(ERRCODE_UNDEFINED_OBJECT), @@ -1522,6 +1555,17 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt) get_rel_name(pgrelid), stmt->element_alias, stmt->drop_label), parser_errposition(pstate, -1)); + /* + * Prevent dropping the last label from an element. Every element must + * have at least one label. + */ + if (nlabels == 1) + ereport(ERROR, + (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("cannot drop the last label from element \"%s\"", + stmt->element_alias), + errhint("Every element must have at least one label."))); + ObjectAddressSet(obj, PropgraphElementLabelRelationId, ellabeloid); performDeletion(&obj, stmt->drop_behavior, 0); diff --git a/src/test/isolation/expected/drop-propgraph-label-concurrently.out b/src/test/isolation/expected/drop-propgraph-label-concurrently.out new file mode 100644 index 00000000000..a3fc89fbac1 --- /dev/null +++ b/src/test/isolation/expected/drop-propgraph-label-concurrently.out @@ -0,0 +1,20 @@ +Parsed test spec with 2 sessions + +starting permutation: s1b s1drop1 s2b s2drop2 s1c s2c +step s1b: BEGIN; +step s1drop1: ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl1; +step s2b: BEGIN; +step s2drop2: ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl2; <waiting ...> +step s1c: COMMIT; +step s2drop2: <... completed> +ERROR: cannot drop the last label from element "pgt1" +step s2c: COMMIT; + +starting permutation: s1b s1drop1 s2b s2drop2 s1r s2c +step s1b: BEGIN; +step s1drop1: ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl1; +step s2b: BEGIN; +step s2drop2: ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl2; <waiting ...> +step s1r: ROLLBACK; +step s2drop2: <... completed> +step s2c: COMMIT; diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 1578ba191c8..9c64ee43641 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -126,3 +126,4 @@ test: serializable-parallel-3 test: matview-write-skew test: lock-nowait test: for-portion-of +test: drop-propgraph-label-concurrently diff --git a/src/test/isolation/specs/drop-propgraph-label-concurrently.spec b/src/test/isolation/specs/drop-propgraph-label-concurrently.spec new file mode 100644 index 00000000000..ce8f4351364 --- /dev/null +++ b/src/test/isolation/specs/drop-propgraph-label-concurrently.spec @@ -0,0 +1,36 @@ +# ALTER PROPERTY GRAPH ... DROP LABEL - concurrent +# +# Verify that two concurrent transactions cannot both drop a label from +# the same element such that the element ends up with no labels. + +setup +{ + CREATE TABLE pgt1 (a int, b int); + CREATE PROPERTY GRAPH pgg1 + VERTEX TABLES (pgt1 KEY (a) + LABEL pgl1 PROPERTIES (b) + LABEL pgl2 PROPERTIES (a, b)); +} + +teardown +{ + DROP PROPERTY GRAPH IF EXISTS pgg1; + DROP TABLE pgt1; +} + +session s1 +step s1b { BEGIN; } +step s1drop1 { ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl1; } +step s1c { COMMIT; } +step s1r { ROLLBACK; } + +session s2 +step s2b { BEGIN; } +step s2drop2 { ALTER PROPERTY GRAPH pgg1 ALTER VERTEX TABLE pgt1 DROP LABEL pgl2; } +step s2c { COMMIT; } + +# s2drop2 fails since by then pgl2 is the only remaining label on pgt1 +permutation s1b s1drop1 s2b s2drop2 s1c s2c + +# s2drop2 succeeds since rollback leaves pgl1 behind +permutation s1b s1drop1 s2b s2drop2 s1r s2c diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index f625524abce..dd6c67167e5 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -57,6 +57,12 @@ ALTER PROPERTY GRAPH g3 ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3x; -- error ERROR: property graph "g3" element "t3" has no label "t3l3x" ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3; +-- Test that the last label on an element cannot be dropped +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l2; +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l1; -- error: last label +ERROR: cannot drop the last label from element "t3" +HINT: Every element must have at least one label. +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 ADD LABEL t3l2 PROPERTIES ALL COLUMNS; ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2); -- fail ERROR: cannot drop vertex t2 of property graph g3 because other objects depend on it DETAIL: edge e1 of property graph g3 depends on vertex t2 of property graph g3 diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index 241f93df302..4cf771596a8 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -52,6 +52,10 @@ ALTER PROPERTY GRAPH g3 ADD LABEL t3l3 PROPERTIES ALL COLUMNS; ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3x; -- error ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l3; +-- Test that the last label on an element cannot be dropped +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l2; +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 DROP LABEL t3l1; -- error: last label +ALTER PROPERTY GRAPH g3 ALTER VERTEX TABLE t3 ADD LABEL t3l2 PROPERTIES ALL COLUMNS; ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2); -- fail ALTER PROPERTY GRAPH g3 DROP VERTEX TABLES (t2) CASCADE; ALTER PROPERTY GRAPH g3 DROP EDGE TABLES (e2); base-commit: bf7d19be9b18f6f78bd95052a2704259021e6806 -- 2.34.1
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-05-18 00:12               ` Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Junwang Zhao @ 2026-05-18 00:12 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Regards
Junwang Zhao

On Mon, May 18, 2026 at 07:29 Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
wrote:

> On Fri, May 15, 2026 at 8:43 PM Ayush Tiwari
> <ayushtiwari.slg01@gmail.com> wrote:
> >
> > Hi,
> >
> >
> > On Fri, 15 May 2026 at 20:31, Junwang Zhao <zhjwpku@gmail.com> wrote:
> >>
> >> Hi Ayush,
> >>
> >> >>
> >> >> I also added regression coverage for both cases:
> >> >>
> >> >>   DROP LABEL of a label used by a GRAPH_TABLE view
> >> >>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
> >> >>
> >> >> Both now fail with the normal dependency error until the view is
> dropped.
> >> >>
> >> >> Thoughts?
> >>
> >> I'd suggest adding two stmts to the regression that can cover that walk
> of
> >> graph_table_columns is also working.
> >>
> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> >> ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
> >> (name);
> >> ALTER PROPERTY GRAPH
> >> Time: 1.312 ms
> >>
> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> >> ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
> >> (name);
> >> ERROR:  cannot drop property name of property graph myshop because
> >> other objects depend on it
> >> DETAIL:  view customers_us depends on property name of property graph
> myshop
> >> HINT:  Use DROP ... CASCADE to drop the dependent objects too.
> >> Time: 2.231 ms
> >>
> >
> > Good point, thanks.  I added that coverage in the attached v3.
> >
> > The test now also drops customers.name first, which is allowed because
> the
> > graph-level property still exists via products.name, and then verifies
> that
> > dropping products.name is rejected with the dependency error from
> > customers_us.  That should cover GraphPropertyRef nodes reached through
> the
> > GRAPH_TABLE COLUMNS list, in addition to the existing label and
> graph-pattern
> > property cases.
> >
> > I re-added customers.name afterward so the existing myshop graph remains
> > unchanged for the following tests.
>
> Thanks Ayush for working on this and providing the patch. Thanks
> Junwang for reviewing it.
>
> I have some more comments.
>
> }
> + else if (IsA(node, GraphLabelRef))
> + {
> + GraphLabelRef *glr = (GraphLabelRef *) node;
> +
> + /*
> + * GRAPH_TABLE label reference: depend on the label catalog entry.
> + * No expression substructure to recurse into.
>
> That comment is correct, however, the case doesn't return false,
> giving an impression that we are recursing into the substructure.
> expression_tree_walker() then returns false. But I am seeing an
> inconsistency in when to "return false" and when not to. For example,
> for some primitive nodes in expression_tree_walker() like Var, this
> function returns false. But for other primitive nodes like Param it
> doesn't. And there's not comment explaining this difference. I guess
> newer additions to this function are relying on expression_tree_walker
> to return false. So I just removed the misleading comment and let the
> two new nodes rely on expression_tree_walker().
>
> + */
> + add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
> + context->addrs);
> + }
> + else if (IsA(node, GraphPropertyRef))
> + {
> + GraphPropertyRef *gpr = (GraphPropertyRef *) node;
> +
> + /* GRAPH_TABLE property reference: depend on the property entry. */
> + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
> + context->addrs);
> + }
>
> @@ -536,6 +536,22 @@ SELECT g.* FROM x1,
> ORDER BY customer_name, product_name;
> SELECT pg_get_viewdef('customers_us'::regclass);
> +-- A view defined over GRAPH_TABLE should record dependencies on the
> labels
> +-- and properties it references, so they cannot be dropped from under it.
> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL
> list_items;
> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
> + DROP LABEL list_items; -- error
> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
> + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> + ALTER LABEL customers DROP PROPERTIES (address); -- error
> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> + ALTER LABEL customers DROP PROPERTIES (name);
> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
> + ALTER LABEL products DROP PROPERTIES (name); -- error
> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> + ALTER LABEL customers ADD PROPERTIES (name);
> +
>
> Without the code changes, we do not see "cache lookup failed for label
> " error, because there is nothing that uses this view after the drop.
> In the attached patch, I have moved the DDL statements before
> pg_get_viewdef() which throws "cache lookup failed" error without code
> changes and for every DDL statement when we try it separately.
>
> My earlier comment or the test by Man might have misled you into
> thinking that we need to drop properties or labels which are defined
> multiple times so that we test that the dependency error does not
> trigger when a property or a label is not orphaned. Sorry if that's
> the case. I don't think that's the goal here. Further, such tests
> require additional DDL to restore property graph state and also change
> the view definition produced by pg_get_viewdef(). So I used DDLs that
> drop properties or labels which are defined only once.
>
> I shortened the commit message by taking essential elements from your
> commit message.
>
> Please review the attached patch.


The attached patch seems not for this thread.


>
>
> --
> Best Wishes,
> Ashutosh Bapat
>

^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
@ 2026-05-18 00:22                 ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-05-18 00:22 UTC (permalink / raw)
  To: Junwang Zhao <zhjwpku@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Sun, May 17, 2026 at 5:12 PM Junwang Zhao <zhjwpku@gmail.com> wrote:
>
>
>
>
> Regards
> Junwang Zhao
>
> On Mon, May 18, 2026 at 07:29 Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> wrote:
>>
>> On Fri, May 15, 2026 at 8:43 PM Ayush Tiwari
>> <ayushtiwari.slg01@gmail.com> wrote:
>> >
>> > Hi,
>> >
>> >
>> > On Fri, 15 May 2026 at 20:31, Junwang Zhao <zhjwpku@gmail.com> wrote:
>> >>
>> >> Hi Ayush,
>> >>
>> >> >>
>> >> >> I also added regression coverage for both cases:
>> >> >>
>> >> >>   DROP LABEL of a label used by a GRAPH_TABLE view
>> >> >>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
>> >> >>
>> >> >> Both now fail with the normal dependency error until the view is dropped.
>> >> >>
>> >> >> Thoughts?
>> >>
>> >> I'd suggest adding two stmts to the regression that can cover that walk of
>> >> graph_table_columns is also working.
>> >>
>> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
>> >> ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
>> >> (name);
>> >> ALTER PROPERTY GRAPH
>> >> Time: 1.312 ms
>> >>
>> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
>> >> ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
>> >> (name);
>> >> ERROR:  cannot drop property name of property graph myshop because
>> >> other objects depend on it
>> >> DETAIL:  view customers_us depends on property name of property graph myshop
>> >> HINT:  Use DROP ... CASCADE to drop the dependent objects too.
>> >> Time: 2.231 ms
>> >>
>> >
>> > Good point, thanks.  I added that coverage in the attached v3.
>> >
>> > The test now also drops customers.name first, which is allowed because the
>> > graph-level property still exists via products.name, and then verifies that
>> > dropping products.name is rejected with the dependency error from
>> > customers_us.  That should cover GraphPropertyRef nodes reached through the
>> > GRAPH_TABLE COLUMNS list, in addition to the existing label and graph-pattern
>> > property cases.
>> >
>> > I re-added customers.name afterward so the existing myshop graph remains
>> > unchanged for the following tests.
>>
>> Thanks Ayush for working on this and providing the patch. Thanks
>> Junwang for reviewing it.
>>
>> I have some more comments.
>>
>> }
>> + else if (IsA(node, GraphLabelRef))
>> + {
>> + GraphLabelRef *glr = (GraphLabelRef *) node;
>> +
>> + /*
>> + * GRAPH_TABLE label reference: depend on the label catalog entry.
>> + * No expression substructure to recurse into.
>>
>> That comment is correct, however, the case doesn't return false,
>> giving an impression that we are recursing into the substructure.
>> expression_tree_walker() then returns false. But I am seeing an
>> inconsistency in when to "return false" and when not to. For example,
>> for some primitive nodes in expression_tree_walker() like Var, this
>> function returns false. But for other primitive nodes like Param it
>> doesn't. And there's not comment explaining this difference. I guess
>> newer additions to this function are relying on expression_tree_walker
>> to return false. So I just removed the misleading comment and let the
>> two new nodes rely on expression_tree_walker().
>>
>> + */
>> + add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
>> + context->addrs);
>> + }
>> + else if (IsA(node, GraphPropertyRef))
>> + {
>> + GraphPropertyRef *gpr = (GraphPropertyRef *) node;
>> +
>> + /* GRAPH_TABLE property reference: depend on the property entry. */
>> + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
>> + context->addrs);
>> + }
>>
>> @@ -536,6 +536,22 @@ SELECT g.* FROM x1,
>> ORDER BY customer_name, product_name;
>> SELECT pg_get_viewdef('customers_us'::regclass);
>> +-- A view defined over GRAPH_TABLE should record dependencies on the labels
>> +-- and properties it references, so they cannot be dropped from under it.
>> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items;
>> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
>> + DROP LABEL list_items; -- error
>> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
>> + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
>> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
>> + ALTER LABEL customers DROP PROPERTIES (address); -- error
>> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
>> + ALTER LABEL customers DROP PROPERTIES (name);
>> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
>> + ALTER LABEL products DROP PROPERTIES (name); -- error
>> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
>> + ALTER LABEL customers ADD PROPERTIES (name);
>> +
>>
>> Without the code changes, we do not see "cache lookup failed for label
>> " error, because there is nothing that uses this view after the drop.
>> In the attached patch, I have moved the DDL statements before
>> pg_get_viewdef() which throws "cache lookup failed" error without code
>> changes and for every DDL statement when we try it separately.
>>
>> My earlier comment or the test by Man might have misled you into
>> thinking that we need to drop properties or labels which are defined
>> multiple times so that we test that the dependency error does not
>> trigger when a property or a label is not orphaned. Sorry if that's
>> the case. I don't think that's the goal here. Further, such tests
>> require additional DDL to restore property graph state and also change
>> the view definition produced by pg_get_viewdef(). So I used DDLs that
>> drop properties or labels which are defined only once.
>>
>> I shortened the commit message by taking essential elements from your
>> commit message.
>>
>> Please review the attached patch.
>
>
> The attached patch seems not for this thread.

Thanks for noticing. Here's attached correct patch.

-- 
Best Wishes,
Ashutosh Bapat

Attachments:

v20260517-0001-Record-dependencies-on-graph-labels-and-pr.patch (text/x-patch, 11.4K) download From e2f8e1562a8e863fc896442175892e6a011a593b Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Sun, 17 May 2026 12:21:13 +0530 Subject: [PATCH v20260517 5/5] Record dependencies on graph labels and properties 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 is not needed to be recorded separately as it is recorded indirectly via dependency on the property graph property itself. Please note that a property or a label associated with individual elements can still be dropped as long as there are other elements which 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://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 ++++++++++++ src/test/regress/expected/graph_table.out | 37 +++++++++++++++++------ src/test/regress/sql/graph_table.sql | 14 +++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..c54774b3275 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* GRAPH_TABLE label reference depends on the property graph label */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* + * GRAPH_TABLE property reference depends on the property graph + * property + */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index e8d49fd5cd4..a5f9f0ac90a 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -929,7 +929,7 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e 30 | 300 | 10 (2 rows) --- ruleutils reverse parsing +-- GRAPH_TABLE in views -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -938,16 +938,35 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ERROR: cannot drop label orders of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on label orders of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ERROR: cannot drop property address of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property address of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +ERROR: cannot drop property price of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property price of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); - pg_get_viewdef ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - SELECT g.customer_name, + - g.product_name, + - g.a + - FROM x1, + - GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g+ + pg_get_viewdef +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT g.customer_name, + + g.product_name, + + g.price, + + g.a + + FROM x1, + + GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, p.price AS price, x1.a AS a)) g+ ORDER BY g.customer_name, g.product_name; (1 row) diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index e761f09e057..80576b2f9f4 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -525,7 +525,8 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s IS ptnv)-[e IS ptne]->(d IS ptnv) COLUMNS SELECT * FROM GRAPH_TABLE (g4 MATCH (s)-[e]-(d) WHERE s.id = 3 COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; --- ruleutils reverse parsing +-- GRAPH_TABLE in views + -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -534,8 +535,17 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); -- test view/graph nesting -- 2.34.1
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-05-18 02:07                   ` Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Junwang Zhao @ 2026-05-18 02:07 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Mon, May 18, 2026 at 8:22 AM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Sun, May 17, 2026 at 5:12 PM Junwang Zhao <zhjwpku@gmail.com> wrote:
> >
> >
> >
> >
> > Regards
> > Junwang Zhao
> >
> > On Mon, May 18, 2026 at 07:29 Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> wrote:
> >>
> >> On Fri, May 15, 2026 at 8:43 PM Ayush Tiwari
> >> <ayushtiwari.slg01@gmail.com> wrote:
> >> >
> >> > Hi,
> >> >
> >> >
> >> > On Fri, 15 May 2026 at 20:31, Junwang Zhao <zhjwpku@gmail.com> wrote:
> >> >>
> >> >> Hi Ayush,
> >> >>
> >> >> >>
> >> >> >> I also added regression coverage for both cases:
> >> >> >>
> >> >> >>   DROP LABEL of a label used by a GRAPH_TABLE view
> >> >> >>   DROP PROPERTIES of a property used by a GRAPH_TABLE view
> >> >> >>
> >> >> >> Both now fail with the normal dependency error until the view is dropped.
> >> >> >>
> >> >> >> Thoughts?
> >> >>
> >> >> I'd suggest adding two stmts to the regression that can cover that walk of
> >> >> graph_table_columns is also working.
> >> >>
> >> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> >> >> ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES
> >> >> (name);
> >> >> ALTER PROPERTY GRAPH
> >> >> Time: 1.312 ms
> >> >>
> >> >> [local] zhjwpku@postgres:5432-52789=# ALTER PROPERTY GRAPH myshop
> >> >> ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES
> >> >> (name);
> >> >> ERROR:  cannot drop property name of property graph myshop because
> >> >> other objects depend on it
> >> >> DETAIL:  view customers_us depends on property name of property graph myshop
> >> >> HINT:  Use DROP ... CASCADE to drop the dependent objects too.
> >> >> Time: 2.231 ms
> >> >>
> >> >
> >> > Good point, thanks.  I added that coverage in the attached v3.
> >> >
> >> > The test now also drops customers.name first, which is allowed because the
> >> > graph-level property still exists via products.name, and then verifies that
> >> > dropping products.name is rejected with the dependency error from
> >> > customers_us.  That should cover GraphPropertyRef nodes reached through the
> >> > GRAPH_TABLE COLUMNS list, in addition to the existing label and graph-pattern
> >> > property cases.
> >> >
> >> > I re-added customers.name afterward so the existing myshop graph remains
> >> > unchanged for the following tests.
> >>
> >> Thanks Ayush for working on this and providing the patch. Thanks
> >> Junwang for reviewing it.
> >>
> >> I have some more comments.
> >>
> >> }
> >> + else if (IsA(node, GraphLabelRef))
> >> + {
> >> + GraphLabelRef *glr = (GraphLabelRef *) node;
> >> +
> >> + /*
> >> + * GRAPH_TABLE label reference: depend on the label catalog entry.
> >> + * No expression substructure to recurse into.
> >>
> >> That comment is correct, however, the case doesn't return false,
> >> giving an impression that we are recursing into the substructure.
> >> expression_tree_walker() then returns false. But I am seeing an
> >> inconsistency in when to "return false" and when not to. For example,
> >> for some primitive nodes in expression_tree_walker() like Var, this
> >> function returns false. But for other primitive nodes like Param it
> >> doesn't. And there's not comment explaining this difference. I guess
> >> newer additions to this function are relying on expression_tree_walker
> >> to return false. So I just removed the misleading comment and let the
> >> two new nodes rely on expression_tree_walker().
> >>
> >> + */
> >> + add_object_address(PropgraphLabelRelationId, glr->labelid, 0,
> >> + context->addrs);
> >> + }
> >> + else if (IsA(node, GraphPropertyRef))
> >> + {
> >> + GraphPropertyRef *gpr = (GraphPropertyRef *) node;
> >> +
> >> + /* GRAPH_TABLE property reference: depend on the property entry. */
> >> + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0,
> >> + context->addrs);
> >> + }
> >>
> >> @@ -536,6 +536,22 @@ SELECT g.* FROM x1,
> >> ORDER BY customer_name, product_name;
> >> SELECT pg_get_viewdef('customers_us'::regclass);
> >> +-- A view defined over GRAPH_TABLE should record dependencies on the labels
> >> +-- and properties it references, so they cannot be dropped from under it.
> >> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items DROP LABEL list_items;
> >> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE wishlist_items
> >> + DROP LABEL list_items; -- error
> >> +ALTER PROPERTY GRAPH myshop ALTER EDGE TABLE order_items
> >> + ADD LABEL list_items PROPERTIES (order_id AS link_id, product_no);
> >> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> >> + ALTER LABEL customers DROP PROPERTIES (address); -- error
> >> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> >> + ALTER LABEL customers DROP PROPERTIES (name);
> >> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products
> >> + ALTER LABEL products DROP PROPERTIES (name); -- error
> >> +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers
> >> + ALTER LABEL customers ADD PROPERTIES (name);
> >> +
> >>
> >> Without the code changes, we do not see "cache lookup failed for label
> >> " error, because there is nothing that uses this view after the drop.
> >> In the attached patch, I have moved the DDL statements before
> >> pg_get_viewdef() which throws "cache lookup failed" error without code
> >> changes and for every DDL statement when we try it separately.
> >>
> >> My earlier comment or the test by Man might have misled you into
> >> thinking that we need to drop properties or labels which are defined
> >> multiple times so that we test that the dependency error does not
> >> trigger when a property or a label is not orphaned. Sorry if that's
> >> the case. I don't think that's the goal here. Further, such tests
> >> require additional DDL to restore property graph state and also change
> >> the view definition produced by pg_get_viewdef(). So I used DDLs that
> >> drop properties or labels which are defined only once.

+1 for this change, we don't need to re-add the label and property to myshop.

> >>
> >> I shortened the commit message by taking essential elements from your
> >> commit message.
> >>
> >> Please review the attached patch.
> >
> >
> > The attached patch seems not for this thread.
>
> Thanks for noticing. Here's attached correct patch.

The patch LGTM, thanks for taking care of this.

>
> --
> Best Wishes,
> Ashutosh Bapat



-- 
Regards
Junwang Zhao





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
@ 2026-05-18 06:26                     ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ayush Tiwari @ 2026-05-18 06:26 UTC (permalink / raw)
  To: Junwang Zhao <zhjwpku@gmail.com>; +Cc: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On Mon, 18 May 2026 at 07:37, Junwang Zhao <zhjwpku@gmail.com> wrote:

> On Mon, May 18, 2026 at 8:22 AM Ashutosh Bapat
> <ashutosh.bapat.oss@gmail.com> wrote:
>
> > >>
> > >> I shortened the commit message by taking essential elements from your
> > >> commit message.
> > >>
> > >> Please review the attached patch.
> > >
> > >
> > > The attached patch seems not for this thread.
> >
> > Thanks for noticing. Here's attached correct patch.
>
> The patch LGTM, thanks for taking care of this.


+1, LGTM

I've changed the status in CF entry status to Ready for Committer.
https://commitfest.postgresql.org/patch/6760/

Regards,
Ayush

^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
@ 2026-05-21 18:37                       ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-05-21 18:37 UTC (permalink / raw)
  To: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Sun, May 17, 2026 at 11:26 PM Ayush Tiwari
<ayushtiwari.slg01@gmail.com> wrote:
>
> Hi,
>
> On Mon, 18 May 2026 at 07:37, Junwang Zhao <zhjwpku@gmail.com> wrote:
>>
>> On Mon, May 18, 2026 at 8:22 AM Ashutosh Bapat
>> <ashutosh.bapat.oss@gmail.com> wrote:
>>
>> > >>
>> > >> I shortened the commit message by taking essential elements from your
>> > >> commit message.
>> > >>
>> > >> Please review the attached patch.
>> > >
>> > >
>> > > The attached patch seems not for this thread.
>> >
>> > Thanks for noticing. Here's attached correct patch.
>>
>> The patch LGTM, thanks for taking care of this.
>
>
> +1, LGTM
>
> I've changed the status in CF entry status to Ready for Committer.
> https://commitfest.postgresql.org/patch/6760/

Thanks Ayush.

While working on this, I found two other problems. Before we dive into
those, I think we should commit the current patch. It need not wait
for a solution to these problems.

I was checking whether we should be expanding an empty label during
the transformation stage instead of rewrite phase so that, in case the
graph pattern is part of a view definition, the set of labels the
empty label expression resolves to is stored in the catalogs. That
way, we can create a dependency of view on the set of labels at the
time of view. After discussing it with Peter Eisentraut, we feel that
doing so will be good for future-proofing pg_dump of views containing
graph patterns with empty labels. We will definitely need it before
supporting all properties reference since the properties that the all
properties reference expands to depends upon the set of labels in the
label expression. We need to create dependencies between those
properties and the view and hence need dependencies between labels
(that the empty label expression resolves to) and the view. I will
provide a patch for the same soon.

When trying different things which could lead to invalidation of view
if we don't add the dependency between labels (that the empty label
expression resolves to) and the view, I found another way to
invalidate the view.

To reproduce it, run the following statements after running
graph_table.sql tests.
CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v
WHERE v.vprop1 = 10) COLUMNS (v.elname));
BEGIN;
ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1;
ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1;
ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1;
SELECT * FROM v_empty_label;
ROLLBACK;

The three ALTER TABLE statements leave the label behind since it's
associated with the edge tables. The SELECT statement still throws
"ERROR:  property "elname" for element variable "v" not found". If we
expand the empty label reference in the transformation phase and
record dependencies between those labels and the view, we get a
different error "ERROR:  no property graph element of type "vertex"
has label "l1" associated with it in property graph "g1"". The first
error is a bit obscure compared to the second one. So there's relative
improvement. Myself and Peter thought that the second error is an
artifact of the term "vertex labels" in the standard; a term which is
not properly defined in the standard. There are two solutions

1. We create vertex label and edge label as separate objects and
record depdencies accordingly
2. We ignore the term "vertex/edge label" in the standard and handle
labels that exist in property graphs but have no associated element of
required type in the query. I think this will require some corrections
in standard to standardize the outcome of such queries.

I will provide patches once we decide which approach to take.

-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-01 11:37                         ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 11:21                           ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
  2026-06-04 14:07                           ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-06-09 11:06                           ` Re: (SQL/PGQ) cache lookup failed for label Peter Eisentraut <peter@eisentraut.org>
  0 siblings, 3 replies; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-01 11:37 UTC (permalink / raw)
  To: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Fri, May 22, 2026 at 12:07 AM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Sun, May 17, 2026 at 11:26 PM Ayush Tiwari
> <ayushtiwari.slg01@gmail.com> wrote:
> >
> > Hi,
> >
> > On Mon, 18 May 2026 at 07:37, Junwang Zhao <zhjwpku@gmail.com> wrote:
> >>
> >> On Mon, May 18, 2026 at 8:22 AM Ashutosh Bapat
> >> <ashutosh.bapat.oss@gmail.com> wrote:
> >>
> >> > >>
> >> > >> I shortened the commit message by taking essential elements from your
> >> > >> commit message.
> >> > >>
> >> > >> Please review the attached patch.
> >> > >
> >> > >
> >> > > The attached patch seems not for this thread.
> >> >
> >> > Thanks for noticing. Here's attached correct patch.
> >>
> >> The patch LGTM, thanks for taking care of this.
> >
> >
> > +1, LGTM
> >
> > I've changed the status in CF entry status to Ready for Committer.
> > https://commitfest.postgresql.org/patch/6760/
>
> Thanks Ayush.
>
> While working on this, I found two other problems. Before we dive into
> those, I think we should commit the current patch. It need not wait
> for a solution to these problems.
>
> I was checking whether we should be expanding an empty label during
> the transformation stage instead of rewrite phase so that, in case the
> graph pattern is part of a view definition, the set of labels the
> empty label expression resolves to is stored in the catalogs. That
> way, we can create a dependency of view on the set of labels at the
> time of view. After discussing it with Peter Eisentraut, we feel that
> doing so will be good for future-proofing pg_dump of views containing
> graph patterns with empty labels. We will definitely need it before
> supporting all properties reference since the properties that the all
> properties reference expands to depends upon the set of labels in the
> label expression. We need to create dependencies between those
> properties and the view and hence need dependencies between labels
> (that the empty label expression resolves to) and the view. I will
> provide a patch for the same soon.

While working on this I found another issue. An empty label expression
may turn into no label which does not have any syntax level support.
Hence we can't dump a view containing such an empty label expression.
For now I have prohibited empty label expressions which do not resolve
to any label as an unsupported feature. I doubt if there will be any
valid use case for such a label expression.

As a result a test which tests dependency between a view and the
property graph in create_property_graph.sql failed. Failure is
accidental as test uses an empty property graph for this purpose. I
fixed it by adding a vertex table to the property graph being
referenced in the view.

The commit message just mentions the label dependency asymmetry
between explicitly mentioned labels and labels resulting from empty
label expression. I haven't gone into the details of
all-properties-reference to keep it simple. The discussion link should
lead a curious reader to the complex discussion here.

I did reconsider whether to fix this right now or whether we can
postpone it till we support all-properties reference. If we don't fix
this, a query containing empty label expression will return different
result as the set of labels in the property graph changes. When we
will support all properties reference, we will have to fix this and
then the behaviour will change breaking backward compatibility. So I
think we have to fix this now.

>
> When trying different things which could lead to invalidation of view
> if we don't add the dependency between labels (that the empty label
> expression resolves to) and the view, I found another way to
> invalidate the view.
>
> To reproduce it, run the following statements after running
> graph_table.sql tests.
> CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v
> WHERE v.vprop1 = 10) COLUMNS (v.elname));
> BEGIN;
> ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1;
> ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1;
> ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1;
> SELECT * FROM v_empty_label;
> ROLLBACK;
>
> The three ALTER TABLE statements leave the label behind since it's
> associated with the edge tables. The SELECT statement still throws
> "ERROR:  property "elname" for element variable "v" not found". If we
> expand the empty label reference in the transformation phase and
> record dependencies between those labels and the view, we get a
> different error "ERROR:  no property graph element of type "vertex"
> has label "l1" associated with it in property graph "g1"". The first
> error is a bit obscure compared to the second one. So there's relative
> improvement. Myself and Peter thought that the second error is an
> artifact of the term "vertex labels" in the standard; a term which is
> not properly defined in the standard. There are two solutions
>
> 1. We create vertex label and edge label as separate objects and
> record depdencies accordingly
> 2. We ignore the term "vertex/edge label" in the standard and handle
> labels that exist in property graphs but have no associated element of
> required type in the query. I think this will require some corrections
> in standard to standardize the outcome of such queries.
>
> I will provide patches once we decide which approach to take.

For now I have added a test case exhibiting this behaviour. If we
commit the test, somebody who comes across this behaviour will know
why the current behaviour is the way it is and what's the way forward.
But if we don't commit it, which is ok, they will consider this as
buggy behaviour and report it. I am fine either way.

As I mentioned earlier, I am creating patches for all outstanding
issues from the same branch. So the patches attached here do not start
from 0001, but they apply with git am on the latest master for me
without any problem.
0005 - fixes `cache lookup failed for label`
0006 - fixes empty label expression and view behaviour
0007 - issue with labels shared by vertex and edges

-- 
Best Wishes,
Ashutosh Bapat

Attachments: download all (3 files, .tar.gz)

v20260601-0007-View-referencing-labels-shared-by-vertex-a.patch (text/x-patch, 4.6K) download From e72095baf87d7e28c162c0835e0f5f03854eeb63 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:47:33 +0530 Subject: [PATCH v20260601 7/7] View referencing labels shared by vertex and edge tables While at it 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 properties only associated with that label can not be resolved. The fix will need to wait for the SQL/PGQ standard to specify the behaviour in such a case. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> --- src/test/regress/expected/graph_table.out | 20 ++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 13 +++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cfee0626fdb..475ac20d376 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -973,6 +973,19 @@ ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it DETAIL: view v_empty_label depends on label vl2 of property graph g1 HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ERROR: no property graph element of type "vertex" has label "l1" associated with it in property graph "g1" +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -993,6 +1006,13 @@ SELECT pg_get_viewdef('v_empty_label'::regclass); FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); (1 row) +SELECT pg_get_viewdef('v_shared_label'::regclass); + pg_get_viewdef +------------------------------------------------------------------------ + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index c4cb7999857..5412f10ac3c 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -554,9 +554,22 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); SELECT pg_get_viewdef('v_empty_label'::regclass); +SELECT pg_get_viewdef('v_shared_label'::regclass); -- test view/graph nesting -- 2.34.1
v20260601-0005-Record-dependencies-on-graph-labels-and-pr.patch (text/x-patch, 11.4K) download From ba5614bcd38b96e0e455225bab3cb510ab7f151f Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Sun, 17 May 2026 12:21:13 +0530 Subject: [PATCH v20260601 5/7] Record dependencies on graph labels and properties 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 is not needed to be recorded separately as it is recorded indirectly via dependency on the property graph property itself. Please note that a property or a label associated with individual elements can still be dropped as long as there are other elements which 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://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 ++++++++++++ src/test/regress/expected/graph_table.out | 37 +++++++++++++++++------ src/test/regress/sql/graph_table.sql | 14 +++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..c54774b3275 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* GRAPH_TABLE label reference depends on the property graph label */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* + * GRAPH_TABLE property reference depends on the property graph + * property + */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index e8d49fd5cd4..a5f9f0ac90a 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -929,7 +929,7 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e 30 | 300 | 10 (2 rows) --- ruleutils reverse parsing +-- GRAPH_TABLE in views -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -938,16 +938,35 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ERROR: cannot drop label orders of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on label orders of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ERROR: cannot drop property address of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property address of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +ERROR: cannot drop property price of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property price of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); - pg_get_viewdef ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - SELECT g.customer_name, + - g.product_name, + - g.a + - FROM x1, + - GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g+ + pg_get_viewdef +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT g.customer_name, + + g.product_name, + + g.price, + + g.a + + FROM x1, + + GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, p.price AS price, x1.a AS a)) g+ ORDER BY g.customer_name, g.product_name; (1 row) diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index e761f09e057..80576b2f9f4 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -525,7 +525,8 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s IS ptnv)-[e IS ptne]->(d IS ptnv) COLUMNS SELECT * FROM GRAPH_TABLE (g4 MATCH (s)-[e]-(d) WHERE s.id = 3 COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; --- ruleutils reverse parsing +-- GRAPH_TABLE in views + -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -534,8 +535,17 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); -- test view/graph nesting -- 2.34.1
v20260601-0006-Empty-label-expression-in-view-definition.patch (text/x-patch, 20.1K) download From db93ea38da965fa2503ef528520076378da70cc7 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:45:58 +0530 Subject: [PATCH v20260601 6/7] Empty label expression in view definition A view definition depends on all the graph labels that are explicitly mentioned in the graph patterns in it so as to avoid it being rendered invalid when any of the labels is dropped. But when a view definition contains an empty label expression, we do not create any dependency between the view and the labels that the empty label expression resolves to. Resolve an empty label expression during transformation phase so that we can create dependency between those labels and the view. This will further help to avoid invalidation of a view containing all-properties references when we support it. An empty label expression may resolve to an empty set of labels if there are not labels associated with the elements matching the kind of element pattern containing the label expression. We do not have a syntax level support for a label expression containing no labels. Hence we can not dump a view containing such an empty label expression. Throw an error when a query contains such an empty label expression. There are possibly no real usecases which use such queries. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/CAExHW5twGP5Zuk4Zch4kz8XDrSpckWQipMs=ysAj8GmqNa2FCQ@mail.gmail.com --- src/backend/parser/parse_graphtable.c | 110 +++++++++++++++++- src/backend/rewrite/rewriteGraphTable.c | 78 ++++--------- src/include/nodes/parsenodes.h | 8 ++ .../expected/create_property_graph.out | 1 + src/test/regress/expected/graph_table.out | 29 ++++- .../regress/sql/create_property_graph.sql | 1 + src/test/regress/sql/graph_table.sql | 16 ++- 7 files changed, 178 insertions(+), 65 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index 73fbfb541f7..5c9da75c8cf 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -18,6 +18,8 @@ #include "access/genam.h" #include "access/htup_details.h" #include "access/table.h" +#include "catalog/pg_propgraph_element.h" +#include "catalog/pg_propgraph_element_label.h" #include "catalog/pg_propgraph_label.h" #include "catalog/pg_propgraph_property.h" #include "miscadmin.h" @@ -151,6 +153,51 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) return NULL; } +/* + * Given the OID of a label and the kind of graph element pattern, return true if + * there exists at least one element matching the given kind associated with the + * label. Otherwise return false. + */ +static bool +label_has_elements_of_kind(Oid labelid, GraphElementPatternKind gepkind) +{ + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + bool result = false; + + rel = table_open(PropgraphElementLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_element_label_pgellabelid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(labelid)); + scan = systable_beginscan(rel, PropgraphElementLabelLabelIndexId, + true, NULL, 1, key); + while (!result && HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_element_label element_label = (Form_pg_propgraph_element_label) GETSTRUCT(tup); + Oid element_oid = element_label->pgelelid; + HeapTuple element_tup = SearchSysCache1(PROPGRAPHELOID, ObjectIdGetDatum(element_oid)); + Form_pg_propgraph_element element_form; + + if (!HeapTupleIsValid(element_tup)) + elog(ERROR, "cache lookup failed for property graph element %u", element_oid); + + element_form = (Form_pg_propgraph_element) GETSTRUCT(element_tup); + + if ((element_form->pgekind == PGEKIND_VERTEX && gepkind == VERTEX_PATTERN) || + (element_form->pgekind == PGEKIND_EDGE && IS_EDGE_PATTERN(gepkind))) + result = true; + + ReleaseSysCache(element_tup); + } + + systable_endscan(scan); + table_close(rel, AccessShareLock); + return result; +} + /* * Transform a label expression. * @@ -161,14 +208,66 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) * GraphLabelRef nodes corresponding to the names of the labels appearing in the * expression. If any label name cannot be resolved to a label in the property * graph, an error is raised. + * + * An empty label expression is treated as a special case. According to section + * 9.2 "Contextual inference of a set of labels" subclause 2.a.ii of SQL/PGQ + * standard, element pattern which does not have a label expression is + * considered to have label expression equivalent to '%|!%' which is set of all + * labels which have at least one element of the given element kind associated with it. */ static Node * -transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) +transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr, GraphElementPatternKind gepkind) { Node *result; - if (labelexpr == NULL) - return NULL; + if (!labelexpr) + { + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + List *args = NIL; + + rel = table_open(PropgraphLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_label_pglpgid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(gpstate->graphid)); + scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, + true, NULL, 1, key); + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + GraphLabelRef *lref; + + if (!label_has_elements_of_kind(label->oid, gepkind)) + continue; + + lref = makeNode(GraphLabelRef); + lref->labelid = label->oid; + lref->location = -1; + args = lappend(args, lref); + } + systable_endscan(scan); + table_close(rel, AccessShareLock); + + /* + * If there are no labels with elements of the given kind, the set of + * labels that this label expression resolves to is empty. There is no + * way to represent an empty set of labels as a label expression since + * we do not support label conjunction as well as negation. So we can + * not dump a view containing such a label expression. Hence prohibit + * it for now. + */ + if (!args) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("empty label expression does not resolve to any label")); + + result = (Node *) makeBoolExpr(OR_EXPR, args, -1); + return result; + + } check_stack_depth(); @@ -208,7 +307,7 @@ transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) { Node *arg = (Node *) lfirst(lc); - arg = transformLabelExpr(gpstate, arg); + arg = transformLabelExpr(gpstate, arg, gepkind); args = lappend(args, arg); } @@ -249,7 +348,8 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) gpstate->cur_gep = gep; - gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr); + gep->has_empty_labelexpr = !gep->labelexpr; + gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr, gep->kind); gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE); diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 33d4e866d74..2292ca6dcee 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -58,6 +58,8 @@ struct path_factor { GraphElementPatternKind kind; const char *variable; + bool has_empty_labelexpr; /* Copied from the corresponding + * GraphElementPattern */ Node *labelexpr; Node *whereClause; int factorpos; /* Position of this path factor in the list of @@ -221,9 +223,12 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) * expression itself. Hence if only one of the two element * patterns has a label expression use that expression. */ - if (!other->labelexpr) + if (other->has_empty_labelexpr) + { other->labelexpr = gep->labelexpr; - else if (gep->labelexpr && !equal(other->labelexpr, gep->labelexpr)) + other->has_empty_labelexpr = gep->has_empty_labelexpr; + } + else if (!gep->has_empty_labelexpr && !equal(other->labelexpr, gep->labelexpr)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("element patterns with same variable name \"%s\" but different label expressions are not supported", @@ -250,6 +255,7 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) pf = palloc0_object(struct path_factor); pf->factorpos = factorpos++; pf->kind = gep->kind; + pf->has_empty_labelexpr = gep->has_empty_labelexpr; pf->labelexpr = gep->labelexpr; pf->variable = gep->variable; pf->whereClause = gep->whereClause; @@ -823,37 +829,9 @@ get_labels_for_expr(Oid propgraphid, Node *labelexpr) { List *label_oids; - if (!labelexpr) - { - Relation rel; - SysScanDesc scan; - ScanKeyData key[1]; - HeapTuple tup; - - /* - * According to section 9.2 "Contextual inference of a set of labels" - * subclause 2.a.ii of SQL/PGQ standard, element pattern which does - * not have a label expression is considered to have label expression - * equivalent to '%|!%' which is set of all labels. - */ - label_oids = NIL; - rel = table_open(PropgraphLabelRelationId, AccessShareLock); - ScanKeyInit(&key[0], - Anum_pg_propgraph_label_pglpgid, - BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(propgraphid)); - scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, - true, NULL, 1, key); - while (HeapTupleIsValid(tup = systable_getnext(scan))) - { - Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + Assert(labelexpr); - label_oids = lappend_oid(label_oids, label->oid); - } - systable_endscan(scan); - table_close(rel, AccessShareLock); - } - else if (IsA(labelexpr, GraphLabelRef)) + if (IsA(labelexpr, GraphLabelRef)) { GraphLabelRef *glr = castNode(GraphLabelRef, labelexpr); @@ -903,7 +881,6 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) List *elem_oids_seen = NIL; List *pf_elem_oids = NIL; List *path_elements = NIL; - List *unresolved_labels = NIL; Relation rel; SysScanDesc scan; ScanKeyData key[1]; @@ -970,33 +947,26 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) { /* * We did not find any qualified element associated with this - * label. The label or its properties can not be associated with - * the given element pattern. Throw an error if the label was - * explicitly specified in the element pattern. Otherwise remember - * it for later use. + * label. Throw an error. + * + * An empty label expression is replaced by all labels that are + * associated with at least one element of the required kind. We + * should not reach here in that case. */ - if (!pf->labelexpr) - unresolved_labels = lappend_oid(unresolved_labels, labeloid); - else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", - pf->kind == VERTEX_PATTERN ? "vertex" : "edge", - get_propgraph_label_name(labeloid), - get_rel_name(propgraphid)))); + Assert(!pf->has_empty_labelexpr); + + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", + pf->kind == VERTEX_PATTERN ? "vertex" : "edge", + get_propgraph_label_name(labeloid), + get_rel_name(propgraphid)))); } systable_endscan(scan); } table_close(rel, AccessShareLock); - - /* - * Remove the labels which were not explicitly mentioned in the label - * expression but do not have any qualified elements associated with them. - * Properties associated with such labels may not be referenced. See - * replace_property_refs_mutator() for more details. - */ - pf->labeloids = list_difference_oid(label_oids, unresolved_labels); + pf->labeloids = label_oids; return path_elements; } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 91377a6cde3..71040261375 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1048,7 +1048,15 @@ typedef struct GraphElementPattern NodeTag type; GraphElementPatternKind kind; const char *variable; + + /* + * If no label expression is specified, we will replace it with a non-NULL + * expression in transformLabelExpr(). This flag indicates whether the + * label expression was originally empty. + */ + bool has_empty_labelexpr; Node *labelexpr; + List *subexpr; Node *whereClause; List *quantifier; diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index 65508223f54..a1a5501dd52 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -939,6 +939,7 @@ DETAIL: Table "v2tmp" is a temporary table. DROP TABLE g2; -- error: wrong object type ERROR: "g2" is not a table HINT: Use DROP PROPERTY GRAPH to remove a property graph. +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ERROR: cannot drop property graph g1 because other objects depend on it diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index a5f9f0ac90a..cfee0626fdb 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -844,6 +844,8 @@ EXECUTE loopstmt; (2 rows) -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -873,7 +875,6 @@ SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.va 30 | 300 | 10 (3 rows) --- temporary property graph CREATE TEMPORARY PROPERTY GRAPH gtmp VERTEX TABLES ( pv KEY (id) @@ -900,8 +901,12 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ERROR: empty label expression does not resolve to any label +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -957,6 +962,17 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ERROR: cannot drop property price of property graph myshop because other objects depend on it DETAIL: view customers_us depends on property price of property graph myshop HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ERROR: cannot drop label vl1 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl1 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl2 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -970,6 +986,13 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +SELECT pg_get_viewdef('v_empty_label'::regclass); + pg_get_viewdef +---------------------------------------------------------------------------------------------------------- + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index e8b3b3ff94c..0c3aa81e9ca 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -364,6 +364,7 @@ ALTER PROPERTY GRAPH g1 -- DROP, ALTER SET SCHEMA, ALTER PROPERTY GRAPH RENAME TO DROP TABLE g2; -- error: wrong object type +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ALTER PROPERTY GRAPH g1 SET SCHEMA create_property_graph_tests_2; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 80576b2f9f4..c4cb7999857 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -471,6 +471,8 @@ ALTER PROPERTY GRAPH g1 ALTER EDGE TABLE e3_3 ALTER LABEL l2 ADD PROPERTIES ((en EXECUTE loopstmt; -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -493,7 +495,6 @@ CREATE PROPERTY GRAPH g3 DESTINATION KEY(dest) REFERENCES pv(id) ); SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; --- temporary property graph CREATE TEMPORARY PROPERTY GRAPH gtmp VERTEX TABLES ( pv KEY (id) @@ -514,8 +515,11 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -545,8 +549,14 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES (address); -- error ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES (price); -- error +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); +SELECT pg_get_viewdef('v_empty_label'::regclass); -- test view/graph nesting -- 2.34.1
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-04 11:21                           ` Ewan Young <kdbase.hack@gmail.com>
  2026-06-04 11:46                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-08 20:15                             ` Re: (SQL/PGQ) cache lookup failed for label Andres Freund <andres@anarazel.de>
  2 siblings, 2 replies; 26+ messages in thread

From: Ewan Young @ 2026-06-04 11:21 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Thu, Jun 4, 2026 at 6:45 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Fri, May 22, 2026 at 12:07 AM Ashutosh Bapat
> <ashutosh.bapat.oss@gmail.com> wrote:
> >
> > On Sun, May 17, 2026 at 11:26 PM Ayush Tiwari
> > <ayushtiwari.slg01@gmail.com> wrote:
> > >
> > > Hi,
> > >
> > > On Mon, 18 May 2026 at 07:37, Junwang Zhao <zhjwpku@gmail.com> wrote:
> > >>
> > >> On Mon, May 18, 2026 at 8:22 AM Ashutosh Bapat
> > >> <ashutosh.bapat.oss@gmail.com> wrote:
> > >>
> > >> > >>
> > >> > >> I shortened the commit message by taking essential elements from your
> > >> > >> commit message.
> > >> > >>
> > >> > >> Please review the attached patch.
> > >> > >
> > >> > >
> > >> > > The attached patch seems not for this thread.
> > >> >
> > >> > Thanks for noticing. Here's attached correct patch.
> > >>
> > >> The patch LGTM, thanks for taking care of this.
> > >
> > >
> > > +1, LGTM
> > >
> > > I've changed the status in CF entry status to Ready for Committer.
> > > https://commitfest.postgresql.org/patch/6760/
> >
> > Thanks Ayush.
> >
> > While working on this, I found two other problems. Before we dive into
> > those, I think we should commit the current patch. It need not wait
> > for a solution to these problems.
> >
> > I was checking whether we should be expanding an empty label during
> > the transformation stage instead of rewrite phase so that, in case the
> > graph pattern is part of a view definition, the set of labels the
> > empty label expression resolves to is stored in the catalogs. That
> > way, we can create a dependency of view on the set of labels at the
> > time of view. After discussing it with Peter Eisentraut, we feel that
> > doing so will be good for future-proofing pg_dump of views containing
> > graph patterns with empty labels. We will definitely need it before
> > supporting all properties reference since the properties that the all
> > properties reference expands to depends upon the set of labels in the
> > label expression. We need to create dependencies between those
> > properties and the view and hence need dependencies between labels
> > (that the empty label expression resolves to) and the view. I will
> > provide a patch for the same soon.
>
> While working on this I found another issue. An empty label expression
> may turn into no label which does not have any syntax level support.
> Hence we can't dump a view containing such an empty label expression.
> For now I have prohibited empty label expressions which do not resolve
> to any label as an unsupported feature. I doubt if there will be any
> valid use case for such a label expression.
>
> As a result a test which tests dependency between a view and the
> property graph in create_property_graph.sql failed. Failure is
> accidental as test uses an empty property graph for this purpose. I
> fixed it by adding a vertex table to the property graph being
> referenced in the view.
>
> The commit message just mentions the label dependency asymmetry
> between explicitly mentioned labels and labels resulting from empty
> label expression. I haven't gone into the details of
> all-properties-reference to keep it simple. The discussion link should
> lead a curious reader to the complex discussion here.
>
> I did reconsider whether to fix this right now or whether we can
> postpone it till we support all-properties reference. If we don't fix
> this, a query containing empty label expression will return different
> result as the set of labels in the property graph changes. When we
> will support all properties reference, we will have to fix this and
> then the behaviour will change breaking backward compatibility. So I
> think we have to fix this now.
>
> >
> > When trying different things which could lead to invalidation of view
> > if we don't add the dependency between labels (that the empty label
> > expression resolves to) and the view, I found another way to
> > invalidate the view.
> >
> > To reproduce it, run the following statements after running
> > graph_table.sql tests.
> > CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v
> > WHERE v.vprop1 = 10) COLUMNS (v.elname));
> > BEGIN;
> > ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1;
> > ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1;
> > ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1;
> > SELECT * FROM v_empty_label;
> > ROLLBACK;
> >
> > The three ALTER TABLE statements leave the label behind since it's
> > associated with the edge tables. The SELECT statement still throws
> > "ERROR:  property "elname" for element variable "v" not found". If we
> > expand the empty label reference in the transformation phase and
> > record dependencies between those labels and the view, we get a
> > different error "ERROR:  no property graph element of type "vertex"
> > has label "l1" associated with it in property graph "g1"". The first
> > error is a bit obscure compared to the second one. So there's relative
> > improvement. Myself and Peter thought that the second error is an
> > artifact of the term "vertex labels" in the standard; a term which is
> > not properly defined in the standard. There are two solutions
> >
> > 1. We create vertex label and edge label as separate objects and
> > record depdencies accordingly
> > 2. We ignore the term "vertex/edge label" in the standard and handle
> > labels that exist in property graphs but have no associated element of
> > required type in the query. I think this will require some corrections
> > in standard to standardize the outcome of such queries.
> >
> > I will provide patches once we decide which approach to take.
>
> For now I have added a test case exhibiting this behaviour. If we
> commit the test, somebody who comes across this behaviour will know
> why the current behaviour is the way it is and what's the way forward.
> But if we don't commit it, which is ok, they will consider this as
> buggy behaviour and report it. I am fine either way.
>
> As I mentioned earlier, I am creating patches for all outstanding
> issues from the same branch. So the patches attached here do not start
> from 0001, but they apply with git am on the latest master for me
> without any problem.
> 0005 - fixes `cache lookup failed for label`
> 0006 - fixes empty label expression and view behaviour
> 0007 - issue with labels shared by vertex and edges
>
> --
> Best Wishes,
> Ashutosh Bapat

Hi Ashutosh,

Following up here from [1], where I was redirected to this thread,
thanks.

I don't think these are the same bug. I applied v20260601-0005
through 0007 on top of master (90354030b8f) and my test case still
fails the same way:

    CREATE TABLE v1 (id int);
    CREATE TABLE v2 (id int);
    CREATE TABLE x (a int);
    CREATE PROPERTY GRAPH g VERTEX TABLES
      (v1 KEY (id) LABEL l1, v2 KEY (id) LABEL l2);
    SELECT 1 FROM x, GRAPH_TABLE (g MATCH (s IS l1|l2 WHERE s.id = x.a)
                                  COLUMNS (s.id));
    ERROR:  plan should not reference subplan's variable

I also tested the earlier v20260517 patches (which I understand are
what the unattached 0001-0004 of your series correspond to): same
result. That matches expectations, since everything posted in this
thread touches DDL-time code (dependency.c, propgraphcmds.c), while
this is a planner-time failure on a plain SELECT, with no views or
DDL involved.

The trigger is a lateral reference into the GRAPH_TABLE combined with
a label disjunction resolving to two different element tables. Two
labels on the same table don't trigger it, since that produces a
single path query and no UNION.

Root cause, as far as I can tell: replace_property_refs_mutator()
increments varlevelsup for lateral Vars, which is correct when the
path query becomes the subquery RTE directly. With a multi-table
label disjunction, generate_union_from_pathqueries() wraps the path
queries as subquery RTEs of a new UNION query -- one level deeper --
and nothing compensates, so varlevelsup ends up off by one.

The attached patch (same as in [1]) runs IncrementVarSublevelsUp()
over each path query in the multiple-pathquery branch of
generate_union_from_pathqueries(). It also adds a SELECT from the
existing customers_us view to graph_table.sql: that view's comment
says it exists to test exactly this lateral + disjunction
combination, but it is currently only passed to pg_get_viewdef and
never executed, which is why the regression tests don't catch this.

The patch is against master and passes make check. On top of your
v20260601 series only the test-file hunks conflict (both append to
graph_table.sql); the code hunk applies cleanly.

Given that, should this be tracked separately rather than in this
thread? Happy to go either way.

[1] https://www.postgresql.org/message-id/CAON2xHOYJ+dGZznY+oPyBHdLfRtzThQid5iEc-HOxODs3pb3AA@mail.gmail...

Attachments:

v1-0001-Fix-lateral-references-in-GRAPH_TABLE-with-label-.patch (application/octet-stream, 3.7K) download From 1c30243a8385d5ba3c977764d0d9ee493dcd8184 Mon Sep 17 00:00:00 2001 From: Ewan Young <kdbase.hack@gmail.com> Date: Fri, 5 Jun 2026 00:07:10 +0800 Subject: [PATCH v1] Fix lateral references in GRAPH_TABLE with label disjunction When a graph pattern's label disjunction resolves to more than one element table, the rewritten path queries are combined with a UNION query, which places them one query level deeper than the GRAPH_TABLE's own subquery level. replace_property_refs() had already adjusted the varlevelsup of lateral references on the assumption that the path query would itself become the GRAPH_TABLE subquery, so such references ended up off by one, making the planner fail with ERROR: plan should not reference subplan's variable Compensate by incrementing the level of outer references in each path query once more when wrapping them in a UNION query. Also add a regression test that actually executes the customers_us view, which was created to cover exactly this combination of lateral references and label disjunction but was previously only exercised by the ruleutils deparsing test. --- src/backend/rewrite/rewriteGraphTable.c | 10 ++++++++++ src/test/regress/expected/graph_table.out | 9 +++++++++ src/test/regress/sql/graph_table.sql | 4 ++++ 3 files changed, 23 insertions(+) diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 33d4e866d74..3d6c85a5ea8 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -638,6 +638,16 @@ generate_union_from_pathqueries(List **pathqueries) return sampleQuery; } + /* + * Each path query will be wrapped in a subquery RTE of the UNION query + * constructed below, which puts it one query level further away from the + * query containing the GRAPH_TABLE clause than replace_property_refs() + * assumed when it adjusted the levels of lateral references. Compensate + * by incrementing varlevelsup of any outer-query references once more. + */ + foreach_node(Query, pathquery, *pathqueries) + IncrementVarSublevelsUp((Node *) pathquery, 1, 1); + sostmt = castNode(SetOperationStmt, generate_setop_from_pathqueries(*pathqueries, &rtable, NULL)); diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cc6d80afd82..924f0cff6db 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -942,6 +942,15 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +-- exercises lateral references combined with label disjunction, where the +-- rewritten path queries are wrapped in an extra UNION query level +SELECT * FROM customers_us; + customer_name | product_name | a +---------------+--------------+--- + customer1 | product1 | 1 + customer1 | product2 | 1 +(2 rows) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 0e381ec72bc..f8207578d32 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -536,6 +536,10 @@ SELECT g.* FROM x1, ORDER BY customer_name, product_name; SELECT pg_get_viewdef('customers_us'::regclass); +-- exercises lateral references combined with label disjunction, where the +-- rewritten path queries are wrapped in an extra UNION query level +SELECT * FROM customers_us; + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; -- 2.47.3
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 11:21                           ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
@ 2026-06-04 11:46                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 12:44                               ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
  1 sibling, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-04 11:46 UTC (permalink / raw)
  To: Ewan Young <kdbase.hack@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi Ewan,

On Thu, Jun 4, 2026 at 4:52 PM Ewan Young <kdbase.hack@gmail.com> wrote:
>
>
> I don't think these are the same bug. I applied v20260601-0005
> through 0007 on top of master (90354030b8f) and my test case still
> fails the same way:

Sorry to redirect you to the wrong thread. Please check [1]. Hope I
have given you the right one this time :)

When submitting the next report, please check if the issue is already
covered by an existing email thread.

[1] https://www.postgresql.org/message-id/CAHg+QDfnLzsgjaQ_CiKSpP4JH3MKOiwoawEcCzXa9uYr45yiWw@mail.gmail...

-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 11:21                           ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
  2026-06-04 11:46                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-04 12:44                               ` Ewan Young <kdbase.hack@gmail.com>
  0 siblings, 0 replies; 26+ messages in thread

From: Ewan Young @ 2026-06-04 12:44 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi Ashutosh,

On Thu, Jun 4, 2026 at 7:46 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> Hi Ewan,
>
> On Thu, Jun 4, 2026 at 4:52 PM Ewan Young <kdbase.hack@gmail.com> wrote:
> >
> >
> > I don't think these are the same bug. I applied v20260601-0005
> > through 0007 on top of master (90354030b8f) and my test case still
> > fails the same way:
>
> Sorry to redirect you to the wrong thread. Please check [1]. Hope I
> have given you the right one this time :)
>
> When submitting the next report, please check if the issue is already
> covered by an existing email thread.
>
> [1] https://www.postgresql.org/message-id/CAHg+QDfnLzsgjaQ_CiKSpP4JH3MKOiwoawEcCzXa9uYr45yiWw@mail.gmail...

No problem, and thanks for the pointer — this time it is indeed the
same issue. I applied v20260602-0010 on top of master (90354030b8f)
and verified that it fixes my test case as well as an edge-label
variant of it; the graph_table regression test also passes. The fix
is essentially the same as the one I posted (adjusting varlevelsup of
the path queries when they get wrapped as subqueries of the UNION),
just placed in generate_setop_from_pathqueries instead, which also
looks cleaner to me. So please consider my report a duplicate of that
thread.

I will dig the archives more carefully before reporting next time :)

Regards,
Ewan Young

>
> --
> Best Wishes,
> Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 11:21                           ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
@ 2026-06-08 20:15                             ` Andres Freund <andres@anarazel.de>
  2026-06-09 03:51                               ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  1 sibling, 1 reply; 26+ messages in thread

From: Andres Freund @ 2026-06-08 20:15 UTC (permalink / raw)
  To: Ewan Young <kdbase.hack@gmail.com>; +Cc: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

Hi,

On 2026-06-04 19:21:48 +0800, Ewan Young wrote:
> The patch is against master and passes make check. On top of your
> v20260601 series only the test-file hunks conflict (both append to
> graph_table.sql); the code hunk applies cleanly.

Unfortunately this fails in CI:
https://github.com/postgresql-cfbot/postgresql/actions/runs/27163049887

#4  0x598104c3 in ExceptionalCondition (conditionName=0x59adcb6c "var->varlevelsup > 0 && var->varlevelsup < root->query_level", fileName=0x59adcb40 "../src/backend/optimizer/util/paramassign.c", lineNumber=126) at ../src/backend/utils/error/assert.c:65
No locals.
#5  0x592911f8 in replace_outer_var (root=0x5c92f418, var=0x5c92f708) at ../src/backend/optimizer/util/paramassign.c:126
        retval = <optimized out>
        i = <optimized out>
#6  0x59258569 in replace_correlation_vars_mutator (node=0x5c92f708, root=0x5c92f418) at ../src/backend/optimizer/plan/subselect.c:2168
No locals.
#7  0x59191152 in expression_tree_mutator_impl (node=<optimized out>, mutator=0x592584b0 <replace_correlation_vars_mutator>, context=0x5c92f418) at ../src/backend/nodes/nodeFuncs.c:3556
        targetentry = 0x5c92f6dc
        newnode = 0x5c92fa60
        __func__ = "expression_tree_mutator_impl"
#8  0x59258541 in replace_correlation_vars_mutator (node=0x5c92f6dc, root=0x5c92f418) at ../src/backend/optimizer/plan/subselect.c:2198
No locals.

For a full backtrace, see "Core backtraces" e.g. on
https://github.com/postgresql-cfbot/postgresql/actions/runs/27163049887/job/80183542083

Greetings,

Andres Freund





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 11:21                           ` Re: (SQL/PGQ) cache lookup failed for label Ewan Young <kdbase.hack@gmail.com>
  2026-06-08 20:15                             ` Re: (SQL/PGQ) cache lookup failed for label Andres Freund <andres@anarazel.de>
@ 2026-06-09 03:51                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 0 replies; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-09 03:51 UTC (permalink / raw)
  To: Andres Freund <andres@anarazel.de>; +Cc: Ewan Young <kdbase.hack@gmail.com>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>

On Tue, Jun 9, 2026 at 1:45 AM Andres Freund <andres@anarazel.de> wrote:
>
> Hi,
>
> On 2026-06-04 19:21:48 +0800, Ewan Young wrote:
> > The patch is against master and passes make check. On top of your
> > v20260601 series only the test-file hunks conflict (both append to
> > graph_table.sql); the code hunk applies cleanly.
>
> Unfortunately this fails in CI:
> https://github.com/postgresql-cfbot/postgresql/actions/runs/27163049887
>
> #4  0x598104c3 in ExceptionalCondition (conditionName=0x59adcb6c "var->varlevelsup > 0 && var->varlevelsup < root->query_level", fileName=0x59adcb40 "../src/backend/optimizer/util/paramassign.c", lineNumber=126) at ../src/backend/utils/error/assert.c:65
> No locals.
> #5  0x592911f8 in replace_outer_var (root=0x5c92f418, var=0x5c92f708) at ../src/backend/optimizer/util/paramassign.c:126
>         retval = <optimized out>
>         i = <optimized out>
> #6  0x59258569 in replace_correlation_vars_mutator (node=0x5c92f708, root=0x5c92f418) at ../src/backend/optimizer/plan/subselect.c:2168
> No locals.
> #7  0x59191152 in expression_tree_mutator_impl (node=<optimized out>, mutator=0x592584b0 <replace_correlation_vars_mutator>, context=0x5c92f418) at ../src/backend/nodes/nodeFuncs.c:3556
>         targetentry = 0x5c92f6dc
>         newnode = 0x5c92fa60
>         __func__ = "expression_tree_mutator_impl"
> #8  0x59258541 in replace_correlation_vars_mutator (node=0x5c92f6dc, root=0x5c92f418) at ../src/backend/optimizer/plan/subselect.c:2198
> No locals.
>
> For a full backtrace, see "Core backtraces" e.g. on
> https://github.com/postgresql-cfbot/postgresql/actions/runs/27163049887/job/80183542083

That failure is the result of posting the wrong patch to the wrong
thread. Here's the correct set of patches.

-- 
Best Wishes,
Ashutosh Bapat

Attachments: download all (3 files, .tar.gz)

v20260601-0007-View-referencing-labels-shared-by-vertex-a.patch (text/x-patch, 4.6K) download From e72095baf87d7e28c162c0835e0f5f03854eeb63 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:47:33 +0530 Subject: [PATCH v20260601 7/7] View referencing labels shared by vertex and edge tables While at it 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 properties only associated with that label can not be resolved. The fix will need to wait for the SQL/PGQ standard to specify the behaviour in such a case. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> --- src/test/regress/expected/graph_table.out | 20 ++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 13 +++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index cfee0626fdb..475ac20d376 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -973,6 +973,19 @@ ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it DETAIL: view v_empty_label depends on label vl2 of property graph g1 HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ERROR: no property graph element of type "vertex" has label "l1" associated with it in property graph "g1" +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -993,6 +1006,13 @@ SELECT pg_get_viewdef('v_empty_label'::regclass); FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); (1 row) +SELECT pg_get_viewdef('v_shared_label'::regclass); + pg_get_viewdef +------------------------------------------------------------------------ + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index c4cb7999857..5412f10ac3c 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -554,9 +554,22 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); SELECT pg_get_viewdef('v_empty_label'::regclass); +SELECT pg_get_viewdef('v_shared_label'::regclass); -- test view/graph nesting -- 2.34.1
v20260601-0006-Empty-label-expression-in-view-definition.patch (text/x-patch, 20.1K) download From db93ea38da965fa2503ef528520076378da70cc7 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:45:58 +0530 Subject: [PATCH v20260601 6/7] Empty label expression in view definition A view definition depends on all the graph labels that are explicitly mentioned in the graph patterns in it so as to avoid it being rendered invalid when any of the labels is dropped. But when a view definition contains an empty label expression, we do not create any dependency between the view and the labels that the empty label expression resolves to. Resolve an empty label expression during transformation phase so that we can create dependency between those labels and the view. This will further help to avoid invalidation of a view containing all-properties references when we support it. An empty label expression may resolve to an empty set of labels if there are not labels associated with the elements matching the kind of element pattern containing the label expression. We do not have a syntax level support for a label expression containing no labels. Hence we can not dump a view containing such an empty label expression. Throw an error when a query contains such an empty label expression. There are possibly no real usecases which use such queries. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/CAExHW5twGP5Zuk4Zch4kz8XDrSpckWQipMs=ysAj8GmqNa2FCQ@mail.gmail.com --- src/backend/parser/parse_graphtable.c | 110 +++++++++++++++++- src/backend/rewrite/rewriteGraphTable.c | 78 ++++--------- src/include/nodes/parsenodes.h | 8 ++ .../expected/create_property_graph.out | 1 + src/test/regress/expected/graph_table.out | 29 ++++- .../regress/sql/create_property_graph.sql | 1 + src/test/regress/sql/graph_table.sql | 16 ++- 7 files changed, 178 insertions(+), 65 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index 73fbfb541f7..5c9da75c8cf 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -18,6 +18,8 @@ #include "access/genam.h" #include "access/htup_details.h" #include "access/table.h" +#include "catalog/pg_propgraph_element.h" +#include "catalog/pg_propgraph_element_label.h" #include "catalog/pg_propgraph_label.h" #include "catalog/pg_propgraph_property.h" #include "miscadmin.h" @@ -151,6 +153,51 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) return NULL; } +/* + * Given the OID of a label and the kind of graph element pattern, return true if + * there exists at least one element matching the given kind associated with the + * label. Otherwise return false. + */ +static bool +label_has_elements_of_kind(Oid labelid, GraphElementPatternKind gepkind) +{ + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + bool result = false; + + rel = table_open(PropgraphElementLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_element_label_pgellabelid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(labelid)); + scan = systable_beginscan(rel, PropgraphElementLabelLabelIndexId, + true, NULL, 1, key); + while (!result && HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_element_label element_label = (Form_pg_propgraph_element_label) GETSTRUCT(tup); + Oid element_oid = element_label->pgelelid; + HeapTuple element_tup = SearchSysCache1(PROPGRAPHELOID, ObjectIdGetDatum(element_oid)); + Form_pg_propgraph_element element_form; + + if (!HeapTupleIsValid(element_tup)) + elog(ERROR, "cache lookup failed for property graph element %u", element_oid); + + element_form = (Form_pg_propgraph_element) GETSTRUCT(element_tup); + + if ((element_form->pgekind == PGEKIND_VERTEX && gepkind == VERTEX_PATTERN) || + (element_form->pgekind == PGEKIND_EDGE && IS_EDGE_PATTERN(gepkind))) + result = true; + + ReleaseSysCache(element_tup); + } + + systable_endscan(scan); + table_close(rel, AccessShareLock); + return result; +} + /* * Transform a label expression. * @@ -161,14 +208,66 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) * GraphLabelRef nodes corresponding to the names of the labels appearing in the * expression. If any label name cannot be resolved to a label in the property * graph, an error is raised. + * + * An empty label expression is treated as a special case. According to section + * 9.2 "Contextual inference of a set of labels" subclause 2.a.ii of SQL/PGQ + * standard, element pattern which does not have a label expression is + * considered to have label expression equivalent to '%|!%' which is set of all + * labels which have at least one element of the given element kind associated with it. */ static Node * -transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) +transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr, GraphElementPatternKind gepkind) { Node *result; - if (labelexpr == NULL) - return NULL; + if (!labelexpr) + { + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + List *args = NIL; + + rel = table_open(PropgraphLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_label_pglpgid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(gpstate->graphid)); + scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, + true, NULL, 1, key); + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + GraphLabelRef *lref; + + if (!label_has_elements_of_kind(label->oid, gepkind)) + continue; + + lref = makeNode(GraphLabelRef); + lref->labelid = label->oid; + lref->location = -1; + args = lappend(args, lref); + } + systable_endscan(scan); + table_close(rel, AccessShareLock); + + /* + * If there are no labels with elements of the given kind, the set of + * labels that this label expression resolves to is empty. There is no + * way to represent an empty set of labels as a label expression since + * we do not support label conjunction as well as negation. So we can + * not dump a view containing such a label expression. Hence prohibit + * it for now. + */ + if (!args) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("empty label expression does not resolve to any label")); + + result = (Node *) makeBoolExpr(OR_EXPR, args, -1); + return result; + + } check_stack_depth(); @@ -208,7 +307,7 @@ transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) { Node *arg = (Node *) lfirst(lc); - arg = transformLabelExpr(gpstate, arg); + arg = transformLabelExpr(gpstate, arg, gepkind); args = lappend(args, arg); } @@ -249,7 +348,8 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) gpstate->cur_gep = gep; - gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr); + gep->has_empty_labelexpr = !gep->labelexpr; + gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr, gep->kind); gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE); diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index 33d4e866d74..2292ca6dcee 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -58,6 +58,8 @@ struct path_factor { GraphElementPatternKind kind; const char *variable; + bool has_empty_labelexpr; /* Copied from the corresponding + * GraphElementPattern */ Node *labelexpr; Node *whereClause; int factorpos; /* Position of this path factor in the list of @@ -221,9 +223,12 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) * expression itself. Hence if only one of the two element * patterns has a label expression use that expression. */ - if (!other->labelexpr) + if (other->has_empty_labelexpr) + { other->labelexpr = gep->labelexpr; - else if (gep->labelexpr && !equal(other->labelexpr, gep->labelexpr)) + other->has_empty_labelexpr = gep->has_empty_labelexpr; + } + else if (!gep->has_empty_labelexpr && !equal(other->labelexpr, gep->labelexpr)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("element patterns with same variable name \"%s\" but different label expressions are not supported", @@ -250,6 +255,7 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) pf = palloc0_object(struct path_factor); pf->factorpos = factorpos++; pf->kind = gep->kind; + pf->has_empty_labelexpr = gep->has_empty_labelexpr; pf->labelexpr = gep->labelexpr; pf->variable = gep->variable; pf->whereClause = gep->whereClause; @@ -823,37 +829,9 @@ get_labels_for_expr(Oid propgraphid, Node *labelexpr) { List *label_oids; - if (!labelexpr) - { - Relation rel; - SysScanDesc scan; - ScanKeyData key[1]; - HeapTuple tup; - - /* - * According to section 9.2 "Contextual inference of a set of labels" - * subclause 2.a.ii of SQL/PGQ standard, element pattern which does - * not have a label expression is considered to have label expression - * equivalent to '%|!%' which is set of all labels. - */ - label_oids = NIL; - rel = table_open(PropgraphLabelRelationId, AccessShareLock); - ScanKeyInit(&key[0], - Anum_pg_propgraph_label_pglpgid, - BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(propgraphid)); - scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, - true, NULL, 1, key); - while (HeapTupleIsValid(tup = systable_getnext(scan))) - { - Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + Assert(labelexpr); - label_oids = lappend_oid(label_oids, label->oid); - } - systable_endscan(scan); - table_close(rel, AccessShareLock); - } - else if (IsA(labelexpr, GraphLabelRef)) + if (IsA(labelexpr, GraphLabelRef)) { GraphLabelRef *glr = castNode(GraphLabelRef, labelexpr); @@ -903,7 +881,6 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) List *elem_oids_seen = NIL; List *pf_elem_oids = NIL; List *path_elements = NIL; - List *unresolved_labels = NIL; Relation rel; SysScanDesc scan; ScanKeyData key[1]; @@ -970,33 +947,26 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) { /* * We did not find any qualified element associated with this - * label. The label or its properties can not be associated with - * the given element pattern. Throw an error if the label was - * explicitly specified in the element pattern. Otherwise remember - * it for later use. + * label. Throw an error. + * + * An empty label expression is replaced by all labels that are + * associated with at least one element of the required kind. We + * should not reach here in that case. */ - if (!pf->labelexpr) - unresolved_labels = lappend_oid(unresolved_labels, labeloid); - else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", - pf->kind == VERTEX_PATTERN ? "vertex" : "edge", - get_propgraph_label_name(labeloid), - get_rel_name(propgraphid)))); + Assert(!pf->has_empty_labelexpr); + + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", + pf->kind == VERTEX_PATTERN ? "vertex" : "edge", + get_propgraph_label_name(labeloid), + get_rel_name(propgraphid)))); } systable_endscan(scan); } table_close(rel, AccessShareLock); - - /* - * Remove the labels which were not explicitly mentioned in the label - * expression but do not have any qualified elements associated with them. - * Properties associated with such labels may not be referenced. See - * replace_property_refs_mutator() for more details. - */ - pf->labeloids = list_difference_oid(label_oids, unresolved_labels); + pf->labeloids = label_oids; return path_elements; } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 91377a6cde3..71040261375 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1048,7 +1048,15 @@ typedef struct GraphElementPattern NodeTag type; GraphElementPatternKind kind; const char *variable; + + /* + * If no label expression is specified, we will replace it with a non-NULL + * expression in transformLabelExpr(). This flag indicates whether the + * label expression was originally empty. + */ + bool has_empty_labelexpr; Node *labelexpr; + List *subexpr; Node *whereClause; List *quantifier; diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index 65508223f54..a1a5501dd52 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -939,6 +939,7 @@ DETAIL: Table "v2tmp" is a temporary table. DROP TABLE g2; -- error: wrong object type ERROR: "g2" is not a table HINT: Use DROP PROPERTY GRAPH to remove a property graph. +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ERROR: cannot drop property graph g1 because other objects depend on it diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index a5f9f0ac90a..cfee0626fdb 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -844,6 +844,8 @@ EXECUTE loopstmt; (2 rows) -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -873,7 +875,6 @@ SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.va 30 | 300 | 10 (3 rows) --- temporary property graph CREATE TEMPORARY PROPERTY GRAPH gtmp VERTEX TABLES ( pv KEY (id) @@ -900,8 +901,12 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ERROR: empty label expression does not resolve to any label +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -957,6 +962,17 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ERROR: cannot drop property price of property graph myshop because other objects depend on it DETAIL: view customers_us depends on property price of property graph myshop HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ERROR: cannot drop label vl1 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl1 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl2 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -970,6 +986,13 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +SELECT pg_get_viewdef('v_empty_label'::regclass); + pg_get_viewdef +---------------------------------------------------------------------------------------------------------- + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index e8b3b3ff94c..0c3aa81e9ca 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -364,6 +364,7 @@ ALTER PROPERTY GRAPH g1 -- DROP, ALTER SET SCHEMA, ALTER PROPERTY GRAPH RENAME TO DROP TABLE g2; -- error: wrong object type +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ALTER PROPERTY GRAPH g1 SET SCHEMA create_property_graph_tests_2; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 80576b2f9f4..c4cb7999857 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -471,6 +471,8 @@ ALTER PROPERTY GRAPH g1 ALTER EDGE TABLE e3_3 ALTER LABEL l2 ADD PROPERTIES ((en EXECUTE loopstmt; -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -493,7 +495,6 @@ CREATE PROPERTY GRAPH g3 DESTINATION KEY(dest) REFERENCES pv(id) ); SELECT * FROM GRAPH_TABLE (g3 MATCH (s IS pv)-[e IS pe]->(d IS pv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; --- temporary property graph CREATE TEMPORARY PROPERTY GRAPH gtmp VERTEX TABLES ( pv KEY (id) @@ -514,8 +515,11 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -545,8 +549,14 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES (address); -- error ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES (price); -- error +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); +SELECT pg_get_viewdef('v_empty_label'::regclass); -- test view/graph nesting -- 2.34.1
v20260601-0005-Record-dependencies-on-graph-labels-and-pr.patch (text/x-patch, 11.4K) download From ba5614bcd38b96e0e455225bab3cb510ab7f151f Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Sun, 17 May 2026 12:21:13 +0530 Subject: [PATCH v20260601 5/7] Record dependencies on graph labels and properties 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 is not needed to be recorded separately as it is recorded indirectly via dependency on the property graph property itself. Please note that a property or a label associated with individual elements can still be dropped as long as there are other elements which 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://postgr.es/m/tencent_43D9888041FA4FDE498C7BF1@qq.com --- src/backend/catalog/dependency.c | 19 ++++++++++++ src/test/regress/expected/graph_table.out | 37 +++++++++++++++++------ src/test/regress/sql/graph_table.sql | 14 +++++++-- 3 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..c54774b3275 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -2165,6 +2165,25 @@ find_expr_references_walker(Node *node, add_object_address(TypeRelationId, rowexpr->row_typeid, 0, context->addrs); } + else if (IsA(node, GraphLabelRef)) + { + GraphLabelRef *glr = (GraphLabelRef *) node; + + /* GRAPH_TABLE label reference depends on the property graph label */ + add_object_address(PropgraphLabelRelationId, glr->labelid, 0, + context->addrs); + } + else if (IsA(node, GraphPropertyRef)) + { + GraphPropertyRef *gpr = (GraphPropertyRef *) node; + + /* + * GRAPH_TABLE property reference depends on the property graph + * property + */ + add_object_address(PropgraphPropertyRelationId, gpr->propid, 0, + context->addrs); + } else if (IsA(node, RowCompareExpr)) { RowCompareExpr *rcexpr = (RowCompareExpr *) node; diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index e8d49fd5cd4..a5f9f0ac90a 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -929,7 +929,7 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e 30 | 300 | 10 (2 rows) --- ruleutils reverse parsing +-- GRAPH_TABLE in views -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -938,16 +938,35 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ERROR: cannot drop label orders of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on label orders of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ERROR: cannot drop property address of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property address of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +ERROR: cannot drop property price of property graph myshop because other objects depend on it +DETAIL: view customers_us depends on property price of property graph myshop +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); - pg_get_viewdef ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - SELECT g.customer_name, + - g.product_name, + - g.a + - FROM x1, + - GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g+ + pg_get_viewdef +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT g.customer_name, + + g.product_name, + + g.price, + + g.a + + FROM x1, + + GRAPH_TABLE (myshop MATCH (c IS customers WHERE (((c.address)::text = 'US'::text) AND (c.customer_id = x1.a)))-[IS customer_orders|customer_wishlists]->(l IS orders|wishlists)-[IS list_items]->(p IS products) COLUMNS (c.name AS customer_name, p.name AS product_name, p.price AS price, x1.a AS a)) g+ ORDER BY g.customer_name, g.product_name; (1 row) diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index e761f09e057..80576b2f9f4 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -525,7 +525,8 @@ SELECT * FROM GRAPH_TABLE (g4 MATCH (s IS ptnv)-[e IS ptne]->(d IS ptnv) COLUMNS SELECT * FROM GRAPH_TABLE (g4 MATCH (s)-[e]-(d) WHERE s.id = 3 COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; SELECT * FROM GRAPH_TABLE (g4 MATCH (s WHERE s.id = 3)-[e]-(d) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; --- ruleutils reverse parsing +-- GRAPH_TABLE in views + -- The query in the view definition is intentionally complex to test one view with many -- features like label disjunction, lateral references, WHERE clauses in graph -- patterns. @@ -534,8 +535,17 @@ SELECT g.* FROM x1, GRAPH_TABLE (myshop MATCH (c IS customers WHERE c.address = 'US' AND c.customer_id = x1.a) -[IS customer_orders | customer_wishlists ]-> (l IS orders | wishlists)-[ IS list_items]->(p IS products) - COLUMNS (c.name AS customer_name, p.name AS product_name, x1.a AS a)) g + COLUMNS (c.name AS customer_name, p.name AS product_name, p.price, x1.a AS a)) g ORDER BY customer_name, product_name; +-- Dropping properties or labels used by a view is not allowed +-- If these DDLs succeed, the pg_get_viewdef call below will throw cache lookup +-- error. +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE orders DROP LABEL orders; -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers + ALTER LABEL customers DROP PROPERTIES (address); -- error +ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products + ALTER LABEL products DROP PROPERTIES (price); -- error +-- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); -- test view/graph nesting -- 2.34.1
^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-04 14:07                           ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-06-04 15:04                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2 siblings, 1 reply; 26+ messages in thread

From: zengman @ 2026-06-04 14:07 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>

> For now I have added a test case exhibiting this behaviour. If we
> commit the test, somebody who comes across this behaviour will know
> why the current behaviour is the way it is and what's the way forward.
> But if we don't commit it, which is ok, they will consider this as
> buggy behaviour and report it. I am fine either way.
> 
> As I mentioned earlier, I am creating patches for all outstanding
> issues from the same branch. So the patches attached here do not start
> from 0001, but they apply with git am on the latest master for me
> without any problem.
> 0005 - fixes `cache lookup failed for label`
> 0006 - fixes empty label expression and view behaviour
> 0007 - issue with labels shared by vertex and edges

Hi Ashutosh,

I applied and tested the v20260601 patches on top of master, looks good.

One thing I noticed though -- RemoveRelations() in propgraphcmds.c
cleans up orphaned pg_propgraph_property entries, but the condition
doesn't include drop_label:

```diff
inline patch 1: src/backend/commands/propgraphcmds.c (+1/-1 lines) download inline-1.patchdiff --git a/src/backend/commands/propgraphcmds.c b/src/backend/commands/propgraphcmds.c index cc516e27020..7c8f397afbf 100644 --- a/src/backend/commands/propgraphcmds.c +++ b/src/backend/commands/propgraphcmds.c @@ -1638,7 +1638,7 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt) } /* Remove any orphaned pg_propgraph_property entries */ - if (stmt->drop_properties || stmt->drop_vertex_tables || stmt->drop_edge_tables) + if (stmt->drop_label || stmt->drop_properties || stmt->drop_vertex_tables || stmt->drop_edge_tables) { foreach_oid(propoid, get_graph_property_ids(pgrelid)) {
``` ```sql postgres@zxm-VMware-Virtual-Platform:~/code/postgres$ psql psql (19beta1) Type "help" for help. postgres=# CREATE PROPERTY GRAPH g1 VERTEX TABLES ( v1 LABEL vl1 PROPERTIES (a, b, c) LABEL vl2 PROPERTIES (a) LABEL vl3 PROPERTIES (a,b) ); CREATE PROPERTY GRAPH postgres=# ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; ALTER PROPERTY GRAPH postgres=# SELECT oid, pgpname FROM pg_propgraph_property WHERE pgppgid = 'g1'::regclass ORDER BY pgpname; oid | pgpname --------+--------- 111971 | a 111973 | b 111975 | c (3 rows) ``` After dropping vl1, b and c are still there even though no label references them anymore. Not sure if this is worth fixing -- thoughts? -- regards, Man Zeng ^ permalink raw reply [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 14:07                           ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
@ 2026-06-04 15:04                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-05 14:37                               ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  0 siblings, 1 reply; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-04 15:04 UTC (permalink / raw)
  To: zengman <zengman@halodbtech.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>

On Thu, Jun 4, 2026 at 7:37 PM zengman <zengman@halodbtech.com> wrote:
>
> > For now I have added a test case exhibiting this behaviour. If we
> > commit the test, somebody who comes across this behaviour will know
> > why the current behaviour is the way it is and what's the way forward.
> > But if we don't commit it, which is ok, they will consider this as
> > buggy behaviour and report it. I am fine either way.
> >
> > As I mentioned earlier, I am creating patches for all outstanding
> > issues from the same branch. So the patches attached here do not start
> > from 0001, but they apply with git am on the latest master for me
> > without any problem.
> > 0005 - fixes `cache lookup failed for label`
> > 0006 - fixes empty label expression and view behaviour
> > 0007 - issue with labels shared by vertex and edges
>
> Hi Ashutosh,
>
> I applied and tested the v20260601 patches on top of master, looks good.
>
> One thing I noticed though -- RemoveRelations() in propgraphcmds.c
> cleans up orphaned pg_propgraph_property entries, but the condition
> doesn't include drop_label:
>
> ```diff
> diff --git a/src/backend/commands/propgraphcmds.c b/src/backend/commands/propgraphcmds.c
> index cc516e27020..7c8f397afbf 100644
> --- a/src/backend/commands/propgraphcmds.c
> +++ b/src/backend/commands/propgraphcmds.c
> @@ -1638,7 +1638,7 @@ AlterPropGraph(ParseState *pstate, const AlterPropGraphStmt *stmt)
>         }
>
>         /* Remove any orphaned pg_propgraph_property entries */
> -       if (stmt->drop_properties || stmt->drop_vertex_tables || stmt->drop_edge_tables)
> +       if (stmt->drop_label || stmt->drop_properties || stmt->drop_vertex_tables || stmt->drop_edge_tables)
>         {
>                 foreach_oid(propoid, get_graph_property_ids(pgrelid))
>                 {
> ```
>
> ```sql
> postgres@zxm-VMware-Virtual-Platform:~/code/postgres$ psql
> psql (19beta1)
> Type "help" for help.
>
> postgres=# CREATE PROPERTY GRAPH g1
>     VERTEX TABLES (
>         v1
>             LABEL vl1 PROPERTIES (a, b, c)
>             LABEL vl2 PROPERTIES (a) LABEL vl3 PROPERTIES (a,b)
>     );
> CREATE PROPERTY GRAPH
> postgres=# ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1;
> ALTER PROPERTY GRAPH
> postgres=# SELECT oid, pgpname FROM pg_propgraph_property WHERE pgppgid = 'g1'::regclass ORDER BY pgpname;
>   oid   | pgpname
> --------+---------
>  111971 | a
>  111973 | b
>  111975 | c
> (3 rows)
> ```
>
> After dropping vl1, b and c are still there even though no label
> references them anymore. Not sure if this is worth fixing -- thoughts?

b won't be dropped since vl3 references it. But c should get dropped.
It will be interesting to see what happens if someone tries to add a
label with property c afterwards with a different data type - it will
fail, I guess. It's worth fixing for that case if nothing else.

We have gathered 3 issues in this thread, which depend upon each other
either because of code or the test queries. Can you please start a new
thread to discuss this and provide a patch fixing it?

-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-04 14:07                           ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-06-04 15:04                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-05 14:37                               ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  0 siblings, 0 replies; 26+ messages in thread

From: zengman @ 2026-06-05 14:37 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>; Peter Eisentraut <peter@eisentraut.org>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>

> b won't be dropped since vl3 references it. But c should get dropped.
> It will be interesting to see what happens if someone tries to add a
> label with property c afterwards with a different data type - it will
> fail, I guess. It's worth fixing for that case if nothing else.
> 
> We have gathered 3 issues in this thread, which depend upon each other
> either because of code or the test queries. Can you please start a new
> thread to discuss this and provide a patch fixing it?

Hi Ashutosh,

You're right, I pasted the wrong test case. I've started a new thread
for this issue with the correct repro and patch. Please see:

https://www.postgresql.org/message-id/tencent_76F6ACA2364EAA1E5DBD7A47%40qq.com

--
regards,
Man Zeng

^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-09 11:06                           ` Peter Eisentraut <peter@eisentraut.org>
  2026-06-09 15:37                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2 siblings, 1 reply; 26+ messages in thread

From: Peter Eisentraut @ 2026-06-09 11:06 UTC (permalink / raw)
  To: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>; Ayush Tiwari <ayushtiwari.slg01@gmail.com>; +Cc: Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>

On 01.06.26 13:37, Ashutosh Bapat wrote:
> As I mentioned earlier, I am creating patches for all outstanding
> issues from the same branch. So the patches attached here do not start
> from 0001, but they apply with git am on the latest master for me
> without any problem.
> 0005 - fixes `cache lookup failed for label`
> 0006 - fixes empty label expression and view behaviour
> 0007 - issue with labels shared by vertex and edges

I have committed 0005, which I think was the topic of this thread.






^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-09 11:06                           ` Re: (SQL/PGQ) cache lookup failed for label Peter Eisentraut <peter@eisentraut.org>
@ 2026-06-09 15:37                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-18 05:48                               ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-07-08 11:39                               ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  0 siblings, 2 replies; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-09 15:37 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>

On Tue, Jun 9, 2026 at 4:36 PM Peter Eisentraut <peter@eisentraut.org> wrote:
>
> On 01.06.26 13:37, Ashutosh Bapat wrote:
> > As I mentioned earlier, I am creating patches for all outstanding
> > issues from the same branch. So the patches attached here do not start
> > from 0001, but they apply with git am on the latest master for me
> > without any problem.
> > 0005 - fixes `cache lookup failed for label`
> > 0006 - fixes empty label expression and view behaviour
> > 0007 - issue with labels shared by vertex and edges
>
> I have committed 0005, which I think was the topic of this thread.
>

Thanks a lot.

-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-09 11:06                           ` Re: (SQL/PGQ) cache lookup failed for label Peter Eisentraut <peter@eisentraut.org>
  2026-06-09 15:37                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-06-18 05:48                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  1 sibling, 0 replies; 26+ messages in thread

From: Ashutosh Bapat @ 2026-06-18 05:48 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>

On Tue, Jun 9, 2026 at 9:07 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Tue, Jun 9, 2026 at 4:36 PM Peter Eisentraut <peter@eisentraut.org> wrote:
> >
> > On 01.06.26 13:37, Ashutosh Bapat wrote:
> > > As I mentioned earlier, I am creating patches for all outstanding
> > > issues from the same branch. So the patches attached here do not start
> > > from 0001, but they apply with git am on the latest master for me
> > > without any problem.
> > > 0005 - fixes `cache lookup failed for label`
> > > 0006 - fixes empty label expression and view behaviour
> > > 0007 - issue with labels shared by vertex and edges
> >
> > I have committed 0005, which I think was the topic of this thread.
> >
>
> Thanks a lot.

Moving this to resolved items since the original bug, which led to PG
19 open item is fixed.

-- 
Best Wishes,
Ashutosh Bapat





^ permalink  raw  reply  [nested|flat] 26+ messages in thread

* Re: (SQL/PGQ) cache lookup failed for label
  2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-12 11:58 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-14 14:07   ` Re: (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
  2026-05-15 10:37     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 10:55       ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-15 15:01         ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-15 15:13           ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-17 23:29             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 00:12               ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 00:22                 ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-05-18 02:07                   ` Re: (SQL/PGQ) cache lookup failed for label Junwang Zhao <zhjwpku@gmail.com>
  2026-05-18 06:26                     ` Re: (SQL/PGQ) cache lookup failed for label Ayush Tiwari <ayushtiwari.slg01@gmail.com>
  2026-05-21 18:37                       ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-01 11:37                         ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  2026-06-09 11:06                           ` Re: (SQL/PGQ) cache lookup failed for label Peter Eisentraut <peter@eisentraut.org>
  2026-06-09 15:37                             ` Re: (SQL/PGQ) cache lookup failed for label Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
@ 2026-07-08 11:39                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
  1 sibling, 0 replies; 26+ messages in thread

From: Ashutosh Bapat @ 2026-07-08 11:39 UTC (permalink / raw)
  To: Peter Eisentraut <peter@eisentraut.org>; +Cc: Ayush Tiwari <ayushtiwari.slg01@gmail.com>; Junwang Zhao <zhjwpku@gmail.com>; zengman <zengman@halodbtech.com>; pgsql-hackers <pgsql-hackers@lists.postgresql.org>

On Tue, Jun 9, 2026 at 9:07 PM Ashutosh Bapat
<ashutosh.bapat.oss@gmail.com> wrote:
>
> On Tue, Jun 9, 2026 at 4:36 PM Peter Eisentraut <peter@eisentraut.org> wrote:
> >
> > On 01.06.26 13:37, Ashutosh Bapat wrote:
> > > As I mentioned earlier, I am creating patches for all outstanding
> > > issues from the same branch. So the patches attached here do not start
> > > from 0001, but they apply with git am on the latest master for me
> > > without any problem.
> > > 0005 - fixes `cache lookup failed for label`
> > > 0006 - fixes empty label expression and view behaviour
> > > 0007 - issue with labels shared by vertex and edges
> >
> > I have committed 0005, which I think was the topic of this thread.
> >
>
> Thanks a lot.

Attaching rebased remaining two patches for the issues discussed in [1]


[1] https://www.postgresql.org/message-id/CAExHW5twGP5Zuk4Zch4kz8XDrSpckWQipMs=ysAj8GmqNa2FCQ@mail.gmail...
-- 
Best Wishes,
Ashutosh Bapat

Attachments: download all (2 files, .tar.gz)

v20260708-0003-View-referencing-labels-shared-by-vertex-a.patch (text/x-patch, 4.6K) download From 8e630ed6b73f5a0cd4031ac9747d3ffc0623501d Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:47:33 +0530 Subject: [PATCH v20260708 3/5] View referencing labels shared by vertex and edge tables While at it 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 properties only associated with that label can not be resolved. The fix will need to wait for the SQL/PGQ standard to specify the behaviour in such a case. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> --- src/test/regress/expected/graph_table.out | 20 ++++++++++++++++++++ src/test/regress/sql/graph_table.sql | 13 +++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index 869ef481c04..0ccebf1aea5 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -1008,6 +1008,19 @@ ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it DETAIL: view v_empty_label depends on label vl2 of property graph g1 HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ERROR: no property graph element of type "vertex" has label "l1" associated with it in property graph "g1" +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -1028,6 +1041,13 @@ SELECT pg_get_viewdef('v_empty_label'::regclass); FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); (1 row) +SELECT pg_get_viewdef('v_shared_label'::regclass); + pg_get_viewdef +------------------------------------------------------------------------ + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index b6a20db7a41..9e5817bb4ca 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -566,9 +566,22 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +-- l1 is shared by all vertex tables and edge tables. Dropping it from all +-- vertex tables only renders a view unusable. This is because the standard +-- differentiates between a vertex label and an edge label even though they +-- share the same name. Waiting for the standard to clarify the expected +-- behavior in this case. +CREATE VIEW v_shared_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v IS l1) COLUMNS (v.elname)); +BEGIN; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL l1; +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v3 DROP LABEL l1; +SELECT * FROM v_shared_label; +ROLLBACK; -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); SELECT pg_get_viewdef('v_empty_label'::regclass); +SELECT pg_get_viewdef('v_shared_label'::regclass); -- test view/graph nesting -- 2.34.1
v20260708-0002-Empty-label-expression-in-view-definition.patch (text/x-patch, 19.5K) download From 51aaa2f752f1b42d826603029000131361a6ee2e Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Date: Thu, 28 May 2026 02:45:58 +0530 Subject: [PATCH v20260708 2/5] Empty label expression in view definition A view definition depends on all the graph labels that are explicitly mentioned in the graph patterns in it so as to avoid it being rendered invalid when any of the labels is dropped. But when a view definition contains an empty label expression, we do not create any dependency between the view and the labels that the empty label expression resolves to. Resolve an empty label expression during transformation phase so that we can create dependency between those labels and the view. This will further help to avoid invalidation of a view containing all-properties references when we support it. An empty label expression may resolve to an empty set of labels if there are not labels associated with the elements matching the kind of element pattern containing the label expression. We do not have a syntax level support for a label expression containing no labels. Hence we can not dump a view containing such an empty label expression. Throw an error when a query contains such an empty label expression. There are possibly no real usecases which use such queries. Author: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Discussion: https://www.postgresql.org/message-id/CAExHW5twGP5Zuk4Zch4kz8XDrSpckWQipMs=ysAj8GmqNa2FCQ@mail.gmail.com --- src/backend/parser/parse_graphtable.c | 110 +++++++++++++++++- src/backend/rewrite/rewriteGraphTable.c | 78 ++++--------- src/include/nodes/parsenodes.h | 8 ++ .../expected/create_property_graph.out | 1 + src/test/regress/expected/graph_table.out | 28 ++++- .../regress/sql/create_property_graph.sql | 1 + src/test/regress/sql/graph_table.sql | 15 ++- 7 files changed, 178 insertions(+), 63 deletions(-) diff --git a/src/backend/parser/parse_graphtable.c b/src/backend/parser/parse_graphtable.c index 73fbfb541f7..5c9da75c8cf 100644 --- a/src/backend/parser/parse_graphtable.c +++ b/src/backend/parser/parse_graphtable.c @@ -18,6 +18,8 @@ #include "access/genam.h" #include "access/htup_details.h" #include "access/table.h" +#include "catalog/pg_propgraph_element.h" +#include "catalog/pg_propgraph_element_label.h" #include "catalog/pg_propgraph_label.h" #include "catalog/pg_propgraph_property.h" #include "miscadmin.h" @@ -151,6 +153,51 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) return NULL; } +/* + * Given the OID of a label and the kind of graph element pattern, return true if + * there exists at least one element matching the given kind associated with the + * label. Otherwise return false. + */ +static bool +label_has_elements_of_kind(Oid labelid, GraphElementPatternKind gepkind) +{ + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + bool result = false; + + rel = table_open(PropgraphElementLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_element_label_pgellabelid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(labelid)); + scan = systable_beginscan(rel, PropgraphElementLabelLabelIndexId, + true, NULL, 1, key); + while (!result && HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_element_label element_label = (Form_pg_propgraph_element_label) GETSTRUCT(tup); + Oid element_oid = element_label->pgelelid; + HeapTuple element_tup = SearchSysCache1(PROPGRAPHELOID, ObjectIdGetDatum(element_oid)); + Form_pg_propgraph_element element_form; + + if (!HeapTupleIsValid(element_tup)) + elog(ERROR, "cache lookup failed for property graph element %u", element_oid); + + element_form = (Form_pg_propgraph_element) GETSTRUCT(element_tup); + + if ((element_form->pgekind == PGEKIND_VERTEX && gepkind == VERTEX_PATTERN) || + (element_form->pgekind == PGEKIND_EDGE && IS_EDGE_PATTERN(gepkind))) + result = true; + + ReleaseSysCache(element_tup); + } + + systable_endscan(scan); + table_close(rel, AccessShareLock); + return result; +} + /* * Transform a label expression. * @@ -161,14 +208,66 @@ transformGraphTablePropertyRef(ParseState *pstate, ColumnRef *cref) * GraphLabelRef nodes corresponding to the names of the labels appearing in the * expression. If any label name cannot be resolved to a label in the property * graph, an error is raised. + * + * An empty label expression is treated as a special case. According to section + * 9.2 "Contextual inference of a set of labels" subclause 2.a.ii of SQL/PGQ + * standard, element pattern which does not have a label expression is + * considered to have label expression equivalent to '%|!%' which is set of all + * labels which have at least one element of the given element kind associated with it. */ static Node * -transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) +transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr, GraphElementPatternKind gepkind) { Node *result; - if (labelexpr == NULL) - return NULL; + if (!labelexpr) + { + Relation rel; + SysScanDesc scan; + ScanKeyData key[1]; + HeapTuple tup; + List *args = NIL; + + rel = table_open(PropgraphLabelRelationId, AccessShareLock); + ScanKeyInit(&key[0], + Anum_pg_propgraph_label_pglpgid, + BTEqualStrategyNumber, + F_OIDEQ, ObjectIdGetDatum(gpstate->graphid)); + scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, + true, NULL, 1, key); + while (HeapTupleIsValid(tup = systable_getnext(scan))) + { + Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + GraphLabelRef *lref; + + if (!label_has_elements_of_kind(label->oid, gepkind)) + continue; + + lref = makeNode(GraphLabelRef); + lref->labelid = label->oid; + lref->location = -1; + args = lappend(args, lref); + } + systable_endscan(scan); + table_close(rel, AccessShareLock); + + /* + * If there are no labels with elements of the given kind, the set of + * labels that this label expression resolves to is empty. There is no + * way to represent an empty set of labels as a label expression since + * we do not support label conjunction as well as negation. So we can + * not dump a view containing such a label expression. Hence prohibit + * it for now. + */ + if (!args) + ereport(ERROR, + errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("empty label expression does not resolve to any label")); + + result = (Node *) makeBoolExpr(OR_EXPR, args, -1); + return result; + + } check_stack_depth(); @@ -208,7 +307,7 @@ transformLabelExpr(GraphTableParseState *gpstate, Node *labelexpr) { Node *arg = (Node *) lfirst(lc); - arg = transformLabelExpr(gpstate, arg); + arg = transformLabelExpr(gpstate, arg, gepkind); args = lappend(args, arg); } @@ -249,7 +348,8 @@ transformGraphElementPattern(ParseState *pstate, GraphElementPattern *gep) gpstate->cur_gep = gep; - gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr); + gep->has_empty_labelexpr = !gep->labelexpr; + gep->labelexpr = transformLabelExpr(gpstate, gep->labelexpr, gep->kind); gep->whereClause = transformExpr(pstate, gep->whereClause, EXPR_KIND_WHERE); diff --git a/src/backend/rewrite/rewriteGraphTable.c b/src/backend/rewrite/rewriteGraphTable.c index cdb1f4c0dca..a5b1be77a0a 100644 --- a/src/backend/rewrite/rewriteGraphTable.c +++ b/src/backend/rewrite/rewriteGraphTable.c @@ -58,6 +58,8 @@ struct path_factor { GraphElementPatternKind kind; const char *variable; + bool has_empty_labelexpr; /* Copied from the corresponding + * GraphElementPattern */ Node *labelexpr; Node *whereClause; int factorpos; /* Position of this path factor in the list of @@ -221,9 +223,12 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) * expression itself. Hence if only one of the two element * patterns has a label expression use that expression. */ - if (!other->labelexpr) + if (other->has_empty_labelexpr) + { other->labelexpr = gep->labelexpr; - else if (gep->labelexpr && !equal(other->labelexpr, gep->labelexpr)) + other->has_empty_labelexpr = gep->has_empty_labelexpr; + } + else if (!gep->has_empty_labelexpr && !equal(other->labelexpr, gep->labelexpr)) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("element patterns with same variable name \"%s\" but different label expressions are not supported", @@ -250,6 +255,7 @@ generate_queries_for_path_pattern(RangeTblEntry *rte, List *path_pattern) pf = palloc0_object(struct path_factor); pf->factorpos = factorpos++; pf->kind = gep->kind; + pf->has_empty_labelexpr = gep->has_empty_labelexpr; pf->labelexpr = gep->labelexpr; pf->variable = gep->variable; pf->whereClause = gep->whereClause; @@ -830,37 +836,9 @@ get_labels_for_expr(Oid propgraphid, Node *labelexpr) { List *label_oids; - if (!labelexpr) - { - Relation rel; - SysScanDesc scan; - ScanKeyData key[1]; - HeapTuple tup; - - /* - * According to section 9.2 "Contextual inference of a set of labels" - * subclause 2.a.ii of SQL/PGQ standard, element pattern which does - * not have a label expression is considered to have label expression - * equivalent to '%|!%' which is set of all labels. - */ - label_oids = NIL; - rel = table_open(PropgraphLabelRelationId, AccessShareLock); - ScanKeyInit(&key[0], - Anum_pg_propgraph_label_pglpgid, - BTEqualStrategyNumber, - F_OIDEQ, ObjectIdGetDatum(propgraphid)); - scan = systable_beginscan(rel, PropgraphLabelGraphNameIndexId, - true, NULL, 1, key); - while (HeapTupleIsValid(tup = systable_getnext(scan))) - { - Form_pg_propgraph_label label = (Form_pg_propgraph_label) GETSTRUCT(tup); + Assert(labelexpr); - label_oids = lappend_oid(label_oids, label->oid); - } - systable_endscan(scan); - table_close(rel, AccessShareLock); - } - else if (IsA(labelexpr, GraphLabelRef)) + if (IsA(labelexpr, GraphLabelRef)) { GraphLabelRef *glr = castNode(GraphLabelRef, labelexpr); @@ -910,7 +888,6 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) List *elem_oids_seen = NIL; List *pf_elem_oids = NIL; List *path_elements = NIL; - List *unresolved_labels = NIL; Relation rel; SysScanDesc scan; ScanKeyData key[1]; @@ -977,33 +954,26 @@ get_path_elements_for_path_factor(Oid propgraphid, struct path_factor *pf) { /* * We did not find any qualified element associated with this - * label. The label or its properties can not be associated with - * the given element pattern. Throw an error if the label was - * explicitly specified in the element pattern. Otherwise remember - * it for later use. + * label. Throw an error. + * + * An empty label expression is replaced by all labels that are + * associated with at least one element of the required kind. We + * should not reach here in that case. */ - if (!pf->labelexpr) - unresolved_labels = lappend_oid(unresolved_labels, labeloid); - else - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", - pf->kind == VERTEX_PATTERN ? "vertex" : "edge", - get_propgraph_label_name(labeloid), - get_rel_name(propgraphid)))); + Assert(!pf->has_empty_labelexpr); + + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("no property graph element of type \"%s\" has label \"%s\" associated with it in property graph \"%s\"", + pf->kind == VERTEX_PATTERN ? "vertex" : "edge", + get_propgraph_label_name(labeloid), + get_rel_name(propgraphid)))); } systable_endscan(scan); } table_close(rel, AccessShareLock); - - /* - * Remove the labels which were not explicitly mentioned in the label - * expression but do not have any qualified elements associated with them. - * Properties associated with such labels may not be referenced. See - * replace_property_refs_mutator() for more details. - */ - pf->labeloids = list_difference_oid(label_oids, unresolved_labels); + pf->labeloids = label_oids; return path_elements; } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index e03556399ab..d6d0f7d170d 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -1051,7 +1051,15 @@ typedef struct GraphElementPattern NodeTag type; GraphElementPatternKind kind; const char *variable; + + /* + * If no label expression is specified, we will replace it with a non-NULL + * expression in transformLabelExpr(). This flag indicates whether the + * label expression was originally empty. + */ + bool has_empty_labelexpr; Node *labelexpr; + List *subexpr; Node *whereClause; List *quantifier; diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index 4a8b3d91219..3efcce046cf 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -974,6 +974,7 @@ DETAIL: Table "v2tmp" is a temporary table. DROP TABLE g2; -- error: wrong object type ERROR: "g2" is not a table HINT: Use DROP PROPERTY GRAPH to remove a property graph. +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ERROR: cannot drop property graph g1 because other objects depend on it diff --git a/src/test/regress/expected/graph_table.out b/src/test/regress/expected/graph_table.out index a3d78a7ac43..869ef481c04 100644 --- a/src/test/regress/expected/graph_table.out +++ b/src/test/regress/expected/graph_table.out @@ -865,6 +865,8 @@ EXECUTE loopstmt; (2 rows) -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -934,8 +936,12 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ERROR: empty label expression does not resolve to any label +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -991,6 +997,17 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ERROR: cannot drop property price of property graph myshop because other objects depend on it DETAIL: view customers_us depends on property price of property graph myshop HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ERROR: cannot drop label vl1 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl1 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error +ERROR: cannot drop label vl2 of property graph g1 because other objects depend on it +DETAIL: view v_empty_label depends on label vl2 of property graph g1 +HINT: Use DROP ... CASCADE to drop the dependent objects too. -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); pg_get_viewdef @@ -1004,6 +1021,13 @@ SELECT pg_get_viewdef('customers_us'::regclass); ORDER BY g.customer_name, g.product_name; (1 row) +SELECT pg_get_viewdef('v_empty_label'::regclass); + pg_get_viewdef +---------------------------------------------------------------------------------------------------------- + SELECT elname + + FROM GRAPH_TABLE (g1 MATCH (v IS l1|vl1|vl2|vl3 WHERE (v.vprop1 = 10)) COLUMNS (v.elname AS elname)); +(1 row) + -- test view/graph nesting CREATE VIEW customers_view AS SELECT customer_id, 'redacted' || customer_id AS name_redacted, address FROM customers; SELECT * FROM customers; diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index 1667896f558..f98a9187451 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -387,6 +387,7 @@ ALTER PROPERTY GRAPH g1 -- DROP, ALTER SET SCHEMA, ALTER PROPERTY GRAPH RENAME TO DROP TABLE g2; -- error: wrong object type +ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (t1 KEY (a)); -- to make a valid graph query CREATE VIEW vg1 AS SELECT * FROM GRAPH_TABLE(g1 MATCH () COLUMNS (1 AS one)); DROP PROPERTY GRAPH g1; -- error ALTER PROPERTY GRAPH g1 SET SCHEMA create_property_graph_tests_2; diff --git a/src/test/regress/sql/graph_table.sql b/src/test/regress/sql/graph_table.sql index 6aacc2d4aa5..b6a20db7a41 100644 --- a/src/test/regress/sql/graph_table.sql +++ b/src/test/regress/sql/graph_table.sql @@ -479,6 +479,8 @@ ALTER PROPERTY GRAPH g1 ALTER EDGE TABLE e3_3 ALTER LABEL l2 ADD PROPERTIES ((en EXECUTE loopstmt; -- inheritance and partitioning +-- +-- Also test temporary property graphs, keywords NODE and RELATIONSHIP CREATE TABLE pv (id int, val int); CREATE TABLE cv1 () INHERITS (pv); CREATE TABLE cv2 () INHERITS (pv); @@ -525,8 +527,11 @@ CREATE TABLE ptne1 PARTITION OF ptne FOR VALUES IN (1, 2); CREATE TABLE ptne2 PARTITION OF ptne FOR VALUES IN (3); INSERT INTO ptne VALUES (1, 1, 2, 100), (2, 2, 3, 200), (3, 3, 1, 300); CREATE PROPERTY GRAPH g4 - VERTEX TABLES (ptnv) - EDGE TABLES ( + VERTEX TABLES (ptnv); +-- empty label expression which resolves to no labels +SELECT * FROM GRAPH_TABLE (g4 MATCH (s is ptnv)-[e]-(d is ptnv) COLUMNS (s.val, e.val, d.val)) ORDER BY 1, 2, 3; -- error +ALTER PROPERTY GRAPH g4 + ADD EDGE TABLES ( ptne SOURCE KEY (src) REFERENCES ptnv(id) DESTINATION KEY (dest) REFERENCES ptnv(id) @@ -556,8 +561,14 @@ ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE customers ALTER LABEL customers DROP PROPERTIES (address); -- error ALTER PROPERTY GRAPH myshop ALTER VERTEX TABLE products ALTER LABEL products DROP PROPERTIES (price); -- error +-- Empty label expression creates a dependency between the view and the set of +-- labels it resolves to +CREATE VIEW v_empty_label AS SELECT * FROM GRAPH_TABLE (g1 MATCH (v WHERE v.vprop1 = 10) COLUMNS (v.elname)); +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v1 DROP LABEL vl1; -- error +ALTER PROPERTY GRAPH g1 ALTER VERTEX TABLE v2 DROP LABEL vl2; -- error -- ruleutils reverse parsing SELECT pg_get_viewdef('customers_us'::regclass); +SELECT pg_get_viewdef('v_empty_label'::regclass); -- test view/graph nesting -- 2.34.1
^ permalink raw reply [nested|flat] 26+ messages in thread


end of thread, other threads:[~2026-07-08 11:39 UTC | newest]

Thread overview: 26+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-05-08 08:39 (SQL/PGQ) cache lookup failed for label =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
2026-05-12 11:58 ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-05-14 14:07   ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
2026-05-15 10:37     ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
2026-05-15 10:55       ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
2026-05-15 15:01         ` Junwang Zhao <zhjwpku@gmail.com>
2026-05-15 15:13           ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
2026-05-17 23:29             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-05-18 00:12               ` Junwang Zhao <zhjwpku@gmail.com>
2026-05-18 00:22                 ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-05-18 02:07                   ` Junwang Zhao <zhjwpku@gmail.com>
2026-05-18 06:26                     ` Ayush Tiwari <ayushtiwari.slg01@gmail.com>
2026-05-21 18:37                       ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-01 11:37                         ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-04 11:21                           ` Ewan Young <kdbase.hack@gmail.com>
2026-06-04 11:46                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-04 12:44                               ` Ewan Young <kdbase.hack@gmail.com>
2026-06-08 20:15                             ` Andres Freund <andres@anarazel.de>
2026-06-09 03:51                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-04 14:07                           ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
2026-06-04 15:04                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-05 14:37                               ` =?ISO-8859-1?B?emVuZ21hbg==?= <zengman@halodbtech.com>
2026-06-09 11:06                           ` Peter Eisentraut <peter@eisentraut.org>
2026-06-09 15:37                             ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-06-18 05:48                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>
2026-07-08 11:39                               ` Ashutosh Bapat <ashutosh.bapat.oss@gmail.com>

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox