diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c index dd582f97cbb..406c8c10e34 100644 --- a/src/backend/parser/parse_utilcmd.c +++ b/src/backend/parser/parse_utilcmd.c @@ -1911,7 +1911,10 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx, * extended statistic "source_statsid", for the rel identified by heapRel and * heapRelid. * - * Attribute numbers in expression Vars are adjusted according to attmap. + * stxkeys in the source statistic holds attribute numbers from the parent + * relation. Those attnums, along with the attribute numbers referenced by + * Vars inside the expression tree, are remapped to the new relation's + * numbering according to attmap. */ static CreateStatsStmt * generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid, @@ -1970,7 +1973,8 @@ generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid, StatsElem *selem = makeNode(StatsElem); AttrNumber attnum = statsrec->stxkeys.values[i]; - selem->name = get_attname(heapRelid, attnum, false); + selem->name = + get_attname(heapRelid, attmap->attnums[attnum - 1], false); selem->expr = NULL; def_names = lappend(def_names, selem); diff --git a/src/test/regress/expected/create_table_like.out b/src/test/regress/expected/create_table_like.out index 6bfc6d040ff..f49f2684a3a 100644 --- a/src/test/regress/expected/create_table_like.out +++ b/src/test/regress/expected/create_table_like.out @@ -533,3 +533,34 @@ DROP TYPE ctlty1; DROP VIEW ctlv1; DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12; NOTICE: table "ctlt10" does not exist, skipping +-- LIKE ... INCLUDING STATISTICS with dropped columns in the parent, +-- so stxkeys attnums are not contiguous. +CREATE TABLE ctl_stats3_parent (a int, b int, c int); +ALTER TABLE ctl_stats3_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats3_stat ON a, c FROM ctl_stats3_parent; +CREATE TABLE ctl_stats3_child (LIKE ctl_stats3_parent INCLUDING STATISTICS); +CREATE TABLE ctl_stats4_parent (a int, b int, c int, d int); +ALTER TABLE ctl_stats4_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats4_stat ON a, c FROM ctl_stats4_parent; +CREATE TABLE ctl_stats4_child (LIKE ctl_stats4_parent INCLUDING STATISTICS); +SELECT s.stxrelid::regclass AS relation, + array_agg(a.attname ORDER BY u.ord) AS stats_columns +FROM pg_statistic_ext s +CROSS JOIN LATERAL + unnest(s.stxkeys::int2[]) WITH ORDINALITY AS u(attnum, ord) +JOIN pg_attribute a + ON a.attrelid = s.stxrelid AND a.attnum = u.attnum +WHERE s.stxrelid IN ('ctl_stats3_child'::regclass, + 'ctl_stats4_child'::regclass) +GROUP BY s.stxrelid +ORDER BY s.stxrelid::regclass::text; + relation | stats_columns +------------------+--------------- + ctl_stats3_child | {a,c} + ctl_stats4_child | {a,c} +(2 rows) + +DROP TABLE ctl_stats3_parent; +DROP TABLE ctl_stats3_child; +DROP TABLE ctl_stats4_parent; +DROP TABLE ctl_stats4_child; diff --git a/src/test/regress/sql/create_table_like.sql b/src/test/regress/sql/create_table_like.sql index 04008a027b8..7c7206c66ee 100644 --- a/src/test/regress/sql/create_table_like.sql +++ b/src/test/regress/sql/create_table_like.sql @@ -223,3 +223,29 @@ DROP SEQUENCE ctlseq1; DROP TYPE ctlty1; DROP VIEW ctlv1; DROP TABLE IF EXISTS ctlt4, ctlt10, ctlt11, ctlt11a, ctlt12; + +-- LIKE ... INCLUDING STATISTICS with dropped columns in the parent, +-- so stxkeys attnums are not contiguous. +CREATE TABLE ctl_stats3_parent (a int, b int, c int); +ALTER TABLE ctl_stats3_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats3_stat ON a, c FROM ctl_stats3_parent; +CREATE TABLE ctl_stats3_child (LIKE ctl_stats3_parent INCLUDING STATISTICS); +CREATE TABLE ctl_stats4_parent (a int, b int, c int, d int); +ALTER TABLE ctl_stats4_parent DROP COLUMN b; +CREATE STATISTICS ctl_stats4_stat ON a, c FROM ctl_stats4_parent; +CREATE TABLE ctl_stats4_child (LIKE ctl_stats4_parent INCLUDING STATISTICS); +SELECT s.stxrelid::regclass AS relation, + array_agg(a.attname ORDER BY u.ord) AS stats_columns +FROM pg_statistic_ext s +CROSS JOIN LATERAL + unnest(s.stxkeys::int2[]) WITH ORDINALITY AS u(attnum, ord) +JOIN pg_attribute a + ON a.attrelid = s.stxrelid AND a.attnum = u.attnum +WHERE s.stxrelid IN ('ctl_stats3_child'::regclass, + 'ctl_stats4_child'::regclass) +GROUP BY s.stxrelid +ORDER BY s.stxrelid::regclass::text; +DROP TABLE ctl_stats3_parent; +DROP TABLE ctl_stats3_child; +DROP TABLE ctl_stats4_parent; +DROP TABLE ctl_stats4_child;