mirror of
https://github.com/postgres/postgres.git
synced 2025-07-05 07:21:24 +03:00
When index recurses to a partition, map columns numbers
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
This commit is contained in:
@ -993,7 +993,32 @@ DefineIndex(Oid relationId,
|
|||||||
{
|
{
|
||||||
IndexStmt *childStmt = copyObject(stmt);
|
IndexStmt *childStmt = copyObject(stmt);
|
||||||
bool found_whole_row;
|
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 =
|
childStmt->whereClause =
|
||||||
map_variable_attnos(stmt->whereClause, 1, 0,
|
map_variable_attnos(stmt->whereClause, 1, 0,
|
||||||
attmap, maplen,
|
attmap, maplen,
|
||||||
|
@ -631,17 +631,21 @@ alter table idxpart2 drop column col1, drop column col2;
|
|||||||
create index on idxpart2 (abs(b));
|
create index on idxpart2 (abs(b));
|
||||||
alter table idxpart attach partition idxpart2 for values from (0) to (1);
|
alter table idxpart attach partition idxpart2 for values from (0) to (1);
|
||||||
create index on idxpart (abs(b));
|
create index on idxpart (abs(b));
|
||||||
|
create index on idxpart ((b + 1));
|
||||||
alter table idxpart attach partition idxpart1 for values from (1) to (2);
|
alter table idxpart attach partition idxpart1 for values from (1) to (2);
|
||||||
select c.relname, pg_get_indexdef(indexrelid)
|
select c.relname, pg_get_indexdef(indexrelid)
|
||||||
from pg_class c join pg_index i on c.oid = i.indexrelid
|
from pg_class c join pg_index i on c.oid = i.indexrelid
|
||||||
where indrelid::regclass::text like 'idxpart%'
|
where indrelid::regclass::text like 'idxpart%'
|
||||||
order by indexrelid::regclass::text collate "C";
|
order by indexrelid::regclass::text collate "C";
|
||||||
relname | pg_get_indexdef
|
relname | pg_get_indexdef
|
||||||
------------------+--------------------------------------------------------------------------
|
-------------------+------------------------------------------------------------------------------
|
||||||
idxpart1_abs_idx | CREATE INDEX idxpart1_abs_idx ON public.idxpart1 USING btree (abs(b))
|
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))
|
idxpart1_expr_idx | CREATE INDEX idxpart1_expr_idx ON public.idxpart1 USING btree (((b + 1)))
|
||||||
idxpart_abs_idx | CREATE INDEX idxpart_abs_idx ON ONLY public.idxpart USING btree (abs(b))
|
idxpart2_abs_idx | CREATE INDEX idxpart2_abs_idx ON public.idxpart2 USING btree (abs(b))
|
||||||
(3 rows)
|
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;
|
drop table idxpart;
|
||||||
-- Verify that columns are mapped correctly for WHERE in a partial index
|
-- Verify that columns are mapped correctly for WHERE in a partial index
|
||||||
|
@ -326,6 +326,7 @@ alter table idxpart2 drop column col1, drop column col2;
|
|||||||
create index on idxpart2 (abs(b));
|
create index on idxpart2 (abs(b));
|
||||||
alter table idxpart attach partition idxpart2 for values from (0) to (1);
|
alter table idxpart attach partition idxpart2 for values from (0) to (1);
|
||||||
create index on idxpart (abs(b));
|
create index on idxpart (abs(b));
|
||||||
|
create index on idxpart ((b + 1));
|
||||||
alter table idxpart attach partition idxpart1 for values from (1) to (2);
|
alter table idxpart attach partition idxpart1 for values from (1) to (2);
|
||||||
select c.relname, pg_get_indexdef(indexrelid)
|
select c.relname, pg_get_indexdef(indexrelid)
|
||||||
from pg_class c join pg_index i on c.oid = i.indexrelid
|
from pg_class c join pg_index i on c.oid = i.indexrelid
|
||||||
|
Reference in New Issue
Block a user