On 2018/06/21 15:35, Amit Langote wrote:
> So, CompareIndexInfo and generateClonedIndexStmt are both doing the right
> thing, but DefineIndex is not.  Attached is a patch to fix DefineIndex so
> that it converts indexParams before recursing to create the index on a
> partition.

I noticed that while CompareIndexInfo and generateClonedIndexStmt would
reject the case where index expressions contain a whole-row Var, my patch
didn't teach to do the same to DefineIndex, causing asymmetric behavior.
So, whereas ATTACH PARTITION would error out when trying to clone a
parent's index that contains a whole-row Var, recursively creating an
index on partition won't.

I updated the patch so that even DefineIndex will check if any whole-row
Vars were encountered during conversion and error out if so.

Thanks,
Amit
From f28b5e4ab8aa2c41486ef9f64b2f52220cfbfcbf Mon Sep 17 00:00:00 2001
From: amit <amitlangot...@gmail.com>
Date: Thu, 21 Jun 2018 14:50:20 +0900
Subject: [PATCH v2] Convert indexParams to partition's attnos before recursing

---
 src/backend/commands/indexcmds.c       | 21 +++++++++++++
 src/test/regress/expected/indexing.out | 54 ++++++++++++++++++++++++++++++++++
 src/test/regress/sql/indexing.sql      | 34 +++++++++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 3a3223bffb..7bbdeb9e66 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -993,7 +993,28 @@ DefineIndex(Oid relationId,
                                {
                                        IndexStmt  *childStmt = 
copyObject(stmt);
                                        bool            found_whole_row;
+                                       ListCell   *lc;
 
+                                       /* Adjust Vars to match new table's 
column numbering */
+                                       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, maplen,
+                                                                               
                                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, maplen,
diff --git a/src/test/regress/expected/indexing.out 
b/src/test/regress/expected/indexing.out
index 2c2bf44aa8..02c5a8e5ed 100644
--- a/src/test/regress/expected/indexing.out
+++ b/src/test/regress/expected/indexing.out
@@ -1337,3 +1337,57 @@ insert into covidxpart values (4, 1);
 insert into covidxpart values (4, 1);
 ERROR:  duplicate key value violates unique constraint "covidxpart4_a_b_idx"
 DETAIL:  Key (a)=(4) already exists.
+-- tests covering expression indexes in a partition tree with differing 
attributes
+create table idx_part (a int) partition by hash (a);
+create table idx_part1 partition of idx_part for values with (modulus 2, 
remainder 0);
+create table idx_part2 partition of idx_part for values with (modulus 2, 
remainder 1);
+alter table idx_part detach partition idx_part2;
+alter table idx_part2 drop a, add a int;
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+create index idx_part_expr on idx_part ((a + 1));
+\d idx_part2
+             Table "public.idx_part2"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: idx_part FOR VALUES WITH (modulus 2, remainder 1)
+Indexes:
+    "idx_part2_expr_idx" btree ((a + 1))
+
+drop index idx_part_expr;
+alter table idx_part detach partition idx_part2;
+create index idx_part2_expr on idx_part2 ((a + 1));
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+create index idx_part_expr on idx_part ((a + 1));
+\d idx_part2
+             Table "public.idx_part2"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: idx_part FOR VALUES WITH (modulus 2, remainder 1)
+Indexes:
+    "idx_part2_expr" btree ((a + 1))
+
+drop table idx_part2;
+create table idx_part2 (b int, a int);
+alter table idx_part2 drop b;
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+\d idx_part2;
+             Table "public.idx_part2"
+ Column |  Type   | Collation | Nullable | Default 
+--------+---------+-----------+----------+---------
+ a      | integer |           |          | 
+Partition of: idx_part FOR VALUES WITH (modulus 2, remainder 1)
+Indexes:
+    "idx_part2_expr_idx" btree ((a + 1))
+
+-- whole-row Vars in expressions are detected when converting and reported as 
unsupported
+drop table idx_part;
+create table idx_part (a int) partition by hash (a);
+create table idx_part1 (a int);
+create index idx_part_wholerow on idx_part ((idx_part));
+alter table idx_part attach partition idx_part1 for values with (modulus 2, 
remainder 0); -- error
+ERROR:  cannot convert whole-row table reference
+DETAIL:  Index "idx_part_wholerow" contains a whole-row table reference.
+drop table idx_part1;
+drop table idx_part;
diff --git a/src/test/regress/sql/indexing.sql 
b/src/test/regress/sql/indexing.sql
index 29333b31ef..1b1b0af029 100644
--- a/src/test/regress/sql/indexing.sql
+++ b/src/test/regress/sql/indexing.sql
@@ -720,3 +720,37 @@ create unique index on covidxpart4 (a);
 alter table covidxpart attach partition covidxpart4 for values in (4);
 insert into covidxpart values (4, 1);
 insert into covidxpart values (4, 1);
+
+-- tests covering expression indexes in a partition tree with differing 
attributes
+create table idx_part (a int) partition by hash (a);
+create table idx_part1 partition of idx_part for values with (modulus 2, 
remainder 0);
+create table idx_part2 partition of idx_part for values with (modulus 2, 
remainder 1);
+
+alter table idx_part detach partition idx_part2;
+alter table idx_part2 drop a, add a int;
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+create index idx_part_expr on idx_part ((a + 1));
+\d idx_part2
+
+drop index idx_part_expr;
+alter table idx_part detach partition idx_part2;
+create index idx_part2_expr on idx_part2 ((a + 1));
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+create index idx_part_expr on idx_part ((a + 1));
+\d idx_part2
+
+drop table idx_part2;
+create table idx_part2 (b int, a int);
+alter table idx_part2 drop b;
+alter table idx_part attach partition idx_part2 for values with (modulus 2, 
remainder 1);
+\d idx_part2;
+
+-- whole-row Vars in expressions are detected when converting and reported as 
unsupported
+drop table idx_part;
+create table idx_part (a int) partition by hash (a);
+create table idx_part1 (a int);
+create index idx_part_wholerow on idx_part ((idx_part));
+alter table idx_part attach partition idx_part1 for values with (modulus 2, 
remainder 0); -- error
+drop table idx_part1;
+
+drop table idx_part;
-- 
2.11.0

Reply via email to