]> granicus.if.org Git - postgresql/commitdiff
When index recurses to a partition, map columns numbers
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 22 Jun 2018 19:12:53 +0000 (15:12 -0400)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 22 Jun 2018 20:45:48 +0000 (16:45 -0400)
Two out of three code paths were mapping column numbers correctly if a
partition had different column numbers than parent table, but the most
commonly used one (recursing in CREATE INDEX to a new index on a
partition) failed to map attribute numbers in expressions.  Oddly
enough, attnums in WHERE clauses are already handled correctly
everywhere.

Reported-by: Amit Langote
Author: Amit Langote
Discussion: https://postgr.es/m/dce1fda4-e0f0-94c9-6abb-f5956a98c057@lab.ntt.co.jp
Reviewed-by: Álvaro Herrera
src/backend/commands/indexcmds.c
src/test/regress/expected/indexing.out
src/test/regress/sql/indexing.sql

index 3a3223bffb53d3dd6d1ec0e5a615db2fbd8b2498..3b82876c909ad04e4ff2d9934eeb2920ae7a0ddf 100644 (file)
@@ -993,7 +993,32 @@ DefineIndex(Oid relationId,
                                {
                                        IndexStmt  *childStmt = copyObject(stmt);
                                        bool            found_whole_row;
+                                       ListCell   *lc;
+
+                                       /*
+                                        * 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, 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,
index 2c2bf44aa87d823fe73fd23dcd8814256392ba50..f183317fbe8179e7c54c20e50281a71702175369 100644 (file)
@@ -631,17 +631,21 @@ alter table idxpart2 drop column col1, drop column col2;
 create index on idxpart2 (abs(b));
 alter table idxpart attach partition idxpart2 for values from (0) to (1);
 create index on idxpart (abs(b));
+create index on idxpart ((b + 1));
 alter table idxpart attach partition idxpart1 for values from (1) to (2);
 select c.relname, pg_get_indexdef(indexrelid)
   from pg_class c join pg_index i on c.oid = i.indexrelid
   where indrelid::regclass::text like 'idxpart%'
   order by indexrelid::regclass::text collate "C";
-     relname      |                             pg_get_indexdef                              
-------------------+--------------------------------------------------------------------------
- idxpart1_abs_idx | CREATE INDEX idxpart1_abs_idx ON public.idxpart1 USING btree (abs(b))
- idxpart2_abs_idx | CREATE INDEX idxpart2_abs_idx ON public.idxpart2 USING btree (abs(b))
- idxpart_abs_idx  | CREATE INDEX idxpart_abs_idx ON ONLY public.idxpart USING btree (abs(b))
-(3 rows)
+      relname      |                               pg_get_indexdef                                
+-------------------+------------------------------------------------------------------------------
+ idxpart1_abs_idx  | CREATE INDEX idxpart1_abs_idx ON public.idxpart1 USING btree (abs(b))
+ idxpart1_expr_idx | CREATE INDEX idxpart1_expr_idx ON public.idxpart1 USING btree (((b + 1)))
+ idxpart2_abs_idx  | CREATE INDEX idxpart2_abs_idx ON public.idxpart2 USING btree (abs(b))
+ idxpart2_expr_idx | CREATE INDEX idxpart2_expr_idx ON public.idxpart2 USING btree (((b + 1)))
+ idxpart_abs_idx   | CREATE INDEX idxpart_abs_idx ON ONLY public.idxpart USING btree (abs(b))
+ idxpart_expr_idx  | CREATE INDEX idxpart_expr_idx ON ONLY public.idxpart USING btree (((b + 1)))
+(6 rows)
 
 drop table idxpart;
 -- Verify that columns are mapped correctly for WHERE in a partial index
index 29333b31ef2067d962fab35d5b6ed984a059b423..1731fb4d5c39999297b5ff2aeb4676031faff726 100644 (file)
@@ -326,6 +326,7 @@ alter table idxpart2 drop column col1, drop column col2;
 create index on idxpart2 (abs(b));
 alter table idxpart attach partition idxpart2 for values from (0) to (1);
 create index on idxpart (abs(b));
+create index on idxpart ((b + 1));
 alter table idxpart attach partition idxpart1 for values from (1) to (2);
 select c.relname, pg_get_indexdef(indexrelid)
   from pg_class c join pg_index i on c.oid = i.indexrelid