summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2024-10-05 14:46:44 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2024-10-05 14:46:44 -0400
commitfee8cb9473462e023dcf0b41212ca3890ddc28d6 (patch)
tree6a9d4c0d263b57c1fcad92e4b5da2a2665e3d176 /src
parent9c7acc33307bf971ff5fe4b7f7431b7aa93052ac (diff)
Use generateClonedIndexStmt to propagate CREATE INDEX to partitions.
When instantiating an existing partitioned index for a new child partition, we use generateClonedIndexStmt to build a suitable IndexStmt to pass to DefineIndex. However, when DefineIndex needs to recurse to instantiate a newly created partitioned index on an existing child partition, it was doing copyObject on the given IndexStmt and then applying a bunch of ad-hoc fixups. This has a number of problems, primarily that it implies fresh lookups of referenced objects such as opclasses and collations. Since commit 2af07e2f7 caused DefineIndex to restrict search_path internally, those lookups could fail or deliver different results than the original one. We can avoid those problems and save a few dozen lines of code by using generateClonedIndexStmt in this code path too. Another thing this fixes is incorrect propagation of parent-index comments to child indexes (because the copyObject approach copies the idxcomment field while generateClonedIndexStmt doesn't). I had noticed this in connection with commit c01eb619a, but not run the problem to ground. I'm tempted to back-patch this further than v17, but the only thing it's known to fix in older branches is the comment issue, which is pretty minor and doesn't seem worth the risk of introducing new issues in stable branches. (If anyone does care about that, clearing idxcomment in the copied IndexStmt would be a safer fix.) Per bug #18637 from usamoi. Back-patch to v17 where the search_path change came in. Discussion: https://postgr.es/m/18637-f51e314546e3ba2a@postgresql.org
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/indexcmds.c56
-rw-r--r--src/test/regress/expected/alter_table.out5
-rw-r--r--src/test/regress/sql/alter_table.sql2
3 files changed, 13 insertions, 50 deletions
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 77fab0c72a1..3d8df046dad 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -50,6 +50,7 @@
#include "optimizer/optimizer.h"
#include "parser/parse_coerce.h"
#include "parser/parse_oper.h"
+#include "parser/parse_utilcmd.h"
#include "partitioning/partdesc.h"
#include "pgstat.h"
#include "rewrite/rewriteManip.h"
@@ -1445,55 +1446,20 @@ DefineIndex(Oid tableId,
*/
if (!found)
{
- IndexStmt *childStmt = copyObject(stmt);
- bool found_whole_row;
- ListCell *lc;
+ IndexStmt *childStmt;
ObjectAddress childAddr;
/*
- * We can't use the same index name for the child index,
- * so clear idxname to let the recursive invocation choose
- * a new name. Likewise, the existing target relation
- * field is wrong, and if indexOid or oldNumber are set,
- * they mustn't be applied to the child either.
+ * Build an IndexStmt describing the desired child index
+ * in the same way that we do during ATTACH PARTITION.
+ * Notably, we rely on generateClonedIndexStmt to produce
+ * a search-path-independent representation, which the
+ * original IndexStmt might not be.
*/
- childStmt->idxname = NULL;
- childStmt->relation = NULL;
- childStmt->indexOid = InvalidOid;
- childStmt->oldNumber = InvalidRelFileNumber;
- childStmt->oldCreateSubid = InvalidSubTransactionId;
- childStmt->oldFirstRelfilelocatorSubid = InvalidSubTransactionId;
-
- /*
- * Adjust any Vars (both in expressions and in the index's
- * WHERE clause) to match the partition's column numbering
- * in case it's different from the parent's.
- */
- foreach(lc, childStmt->indexParams)
- {
- IndexElem *ielem = lfirst(lc);
-
- /*
- * If the index parameter is an expression, we must
- * translate it to contain child Vars.
- */
- if (ielem->expr)
- {
- ielem->expr =
- map_variable_attnos((Node *) ielem->expr,
- 1, 0, attmap,
- InvalidOid,
- &found_whole_row);
- if (found_whole_row)
- elog(ERROR, "cannot convert whole-row table reference");
- }
- }
- childStmt->whereClause =
- map_variable_attnos(stmt->whereClause, 1, 0,
- attmap,
- InvalidOid, &found_whole_row);
- if (found_whole_row)
- elog(ERROR, "cannot convert whole-row table reference");
+ childStmt = generateClonedIndexStmt(NULL,
+ parentIndex,
+ attmap,
+ NULL);
/*
* Recurse as the starting user ID. Callee will use that
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 79cf82b5aed..6de74a26a95 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2215,7 +2215,6 @@ select conname, obj_description(oid, 'pg_constraint') as desc
(3 rows)
alter table at_partitioned alter column name type varchar(127);
--- Note: these tests currently show the wrong behavior for comments :-(
select relname,
c.oid = oldoid as orig_oid,
case relfilenode
@@ -2232,9 +2231,9 @@ select relname,
------------------------------+----------+---------+--------------
at_partitioned | t | none |
at_partitioned_0 | t | own |
- at_partitioned_0_id_name_key | f | own | parent index
+ at_partitioned_0_id_name_key | f | own |
at_partitioned_1 | t | own |
- at_partitioned_1_id_name_key | f | own | parent index
+ at_partitioned_1_id_name_key | f | own |
at_partitioned_id_name_key | f | none | parent index
(6 rows)
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 28cabc49e9f..da127244730 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1496,8 +1496,6 @@ select conname, obj_description(oid, 'pg_constraint') as desc
alter table at_partitioned alter column name type varchar(127);
--- Note: these tests currently show the wrong behavior for comments :-(
-
select relname,
c.oid = oldoid as orig_oid,
case relfilenode