From f0640472cfabc960d1c07a6f596cccaaddbb9d41 Mon Sep 17 00:00:00 2001 From: satyanarayana narlapuram Date: Tue, 21 Apr 2026 05:15:43 +0000 Subject: [PATCH] Block ALTER TABLE RENAME COLUMN when column is used by property graph When a table column is referenced by a property graph, the property name stored in pg_propgraph_property.pgpname would become stale after a column rename. This caused GRAPH_TABLE queries to fail with the new column name ("property does not exist") while the old (dead) name continued to work. pg_get_propgraphdef() would also emit confusing output like "new_col AS old_col". Fix by checking pg_depend in renameatt_internal() for PropgraphLabelPropertyRelationId entries that reference the column being renamed. If any exist, raise an error directing the user to drop the property graph first. This is consistent with how DROP COLUMN already blocks when a property graph depends on the column. --- src/backend/commands/tablecmds.c | 53 +++++++++++++++++++ .../expected/create_property_graph.out | 17 ++++++ .../regress/sql/create_property_graph.sql | 16 ++++++ 3 files changed, 86 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index eec09ba1..78b6e467 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -48,6 +48,7 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_policy.h" #include "catalog/pg_proc.h" +#include "catalog/pg_propgraph_label_property.h" #include "catalog/pg_publication_rel.h" #include "catalog/pg_rewrite.h" #include "catalog/pg_statistic_ext.h" @@ -3997,6 +3998,58 @@ renameatt_internal(Oid myrelid, /* new name should not already exist */ (void) check_for_column_name_collision(targetrelation, newattname, false); + /* + * Disallow renaming columns that are used by a property graph. The + * property graph catalog stores the property name in + * pg_propgraph_property.pgpname, which would become stale after a + * rename, causing GRAPH_TABLE queries using the new column name to fail + * while the old (dead) name would still work. + */ + { + Relation depRel; + ScanKeyData key[3]; + SysScanDesc depScan; + HeapTuple depTup; + + depRel = table_open(DependRelationId, AccessShareLock); + + ScanKeyInit(&key[0], + Anum_pg_depend_refclassid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(RelationRelationId)); + ScanKeyInit(&key[1], + Anum_pg_depend_refobjid, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(myrelid)); + ScanKeyInit(&key[2], + Anum_pg_depend_refobjsubid, + BTEqualStrategyNumber, F_INT4EQ, + Int32GetDatum((int32) attnum)); + + depScan = systable_beginscan(depRel, DependReferenceIndexId, true, + NULL, 3, key); + + while (HeapTupleIsValid(depTup = systable_getnext(depScan))) + { + Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(depTup); + + if (depForm->classid == PropgraphLabelPropertyRelationId) + { + systable_endscan(depScan); + table_close(depRel, AccessShareLock); + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST), + errmsg("cannot rename column \"%s\" of table \"%s\" because a property graph depends on it", + oldattname, + RelationGetRelationName(targetrelation)), + errhint("Drop the property graph first, then rename the column."))); + } + } + + systable_endscan(depScan); + table_close(depRel, AccessShareLock); + } + /* apply the update */ namestrcpy(&(attform->attname), newattname); diff --git a/src/test/regress/expected/create_property_graph.out b/src/test/regress/expected/create_property_graph.out index bc9a596e..a1d3e6a0 100644 --- a/src/test/regress/expected/create_property_graph.out +++ b/src/test/regress/expected/create_property_graph.out @@ -901,6 +901,23 @@ ERROR: cannot add temporary element table to non-temporary property graph LINE 2: ADD VERTEX TABLES (v2tmp KEY (m)); ^ DETAIL: Table "v2tmp" is a temporary table. +-- ALTER TABLE RENAME COLUMN should be blocked when column is used by +-- a property graph (the property graph catalog stores property names +-- that would become stale after the rename) +CREATE TABLE rename_test (id int PRIMARY KEY, val text); +CREATE PROPERTY GRAPH g_rename VERTEX TABLES (rename_test KEY (id)); +ALTER TABLE rename_test RENAME COLUMN val TO new_val; -- error +ERROR: cannot rename column "val" of table "rename_test" because a property graph depends on it +HINT: Drop the property graph first, then rename the column. +ALTER TABLE rename_test RENAME COLUMN id TO new_id; -- error (KEY column) +ERROR: cannot rename column "id" of table "rename_test" because a property graph depends on it +HINT: Drop the property graph first, then rename the column. +-- renaming a column not used by the graph should still work +ALTER TABLE rename_test ADD COLUMN extra int; +ALTER TABLE rename_test RENAME COLUMN extra TO extra2; -- ok +ALTER TABLE rename_test DROP COLUMN extra2; +DROP PROPERTY GRAPH g_rename; +DROP TABLE rename_test; -- DROP, ALTER SET SCHEMA, ALTER PROPERTY GRAPH RENAME TO DROP TABLE g2; -- error: wrong object type ERROR: "g2" is not a table diff --git a/src/test/regress/sql/create_property_graph.sql b/src/test/regress/sql/create_property_graph.sql index 241f93df..03096f5d 100644 --- a/src/test/regress/sql/create_property_graph.sql +++ b/src/test/regress/sql/create_property_graph.sql @@ -347,6 +347,22 @@ ALTER PROPERTY GRAPH g1 ADD VERTEX TABLES (v2tmp KEY (m)); -- error +-- ALTER TABLE RENAME COLUMN should be blocked when column is used by +-- a property graph (the property graph catalog stores property names +-- that would become stale after the rename) + +CREATE TABLE rename_test (id int PRIMARY KEY, val text); +CREATE PROPERTY GRAPH g_rename VERTEX TABLES (rename_test KEY (id)); +ALTER TABLE rename_test RENAME COLUMN val TO new_val; -- error +ALTER TABLE rename_test RENAME COLUMN id TO new_id; -- error (KEY column) +-- renaming a column not used by the graph should still work +ALTER TABLE rename_test ADD COLUMN extra int; +ALTER TABLE rename_test RENAME COLUMN extra TO extra2; -- ok +ALTER TABLE rename_test DROP COLUMN extra2; +DROP PROPERTY GRAPH g_rename; +DROP TABLE rename_test; + + -- DROP, ALTER SET SCHEMA, ALTER PROPERTY GRAPH RENAME TO DROP TABLE g2; -- error: wrong object type -- 2.43.0