Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit2f3cfcf

Browse files
committed
Fix handling of extended expression statistics in CREATE TABLE LIKE.
transformTableLikeClause believed that it could process extendedstatistics immediately because "the representation of CreateStatsStmtdoesn't depend on column numbers". That was true when extended statswere first introduced, but it was falsified by the addition ofextended stats on expressions: the parsed expression tree is fedforward by the LIKE option, and that will contain Vars. So if thenew table doesn't have attnums identical to the old one's (typicallybecause there are some dropped columns in the old one), that doesn'twork. The CREATE goes through, but it emits invalid statisticsobjects that will cause problems later.Fortunately, we already have logic that can adapt expression treesto the possibly-new column numbering. To use it, we have to delayprocessing of CREATE_TABLE_LIKE_STATISTICS into expandTableLikeClause,just as for other LIKE options that involve expressions.Per bug #18468 from Alexander Lakhin. Back-patch to v14 whereextended statistics on expressions were added.Discussion:https://postgr.es/m/18468-f5add190e3fa5902@postgresql.org
1 parent4ac385a commit2f3cfcf

File tree

3 files changed

+86
-73
lines changed

3 files changed

+86
-73
lines changed

‎src/backend/parser/parse_utilcmd.c

Lines changed: 63 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ typedef struct
8484
List*fkconstraints;/* FOREIGN KEY constraints */
8585
List*ixconstraints;/* index-creating constraints */
8686
List*likeclauses;/* LIKE clauses that need post-processing */
87-
List*extstats;/* cloned extended statistics */
8887
List*blist;/* "before list" of things to do before
8988
* creating the table */
9089
List*alist;/* "after list" of things to do after creating
@@ -117,13 +116,14 @@ static void transformTableLikeClause(CreateStmtContext *cxt,
117116
staticvoidtransformOfType(CreateStmtContext*cxt,
118117
TypeName*ofTypename);
119118
staticCreateStatsStmt*generateClonedExtStatsStmt(RangeVar*heapRel,
120-
OidheapRelid,Oidsource_statsid);
119+
OidheapRelid,
120+
Oidsource_statsid,
121+
constAttrMap*attmap);
121122
staticList*get_collation(Oidcollation,Oidactual_datatype);
122123
staticList*get_opclass(Oidopclass,Oidactual_datatype);
123124
staticvoidtransformIndexConstraints(CreateStmtContext*cxt);
124125
staticIndexStmt*transformIndexConstraint(Constraint*constraint,
125126
CreateStmtContext*cxt);
126-
staticvoidtransformExtendedStatistics(CreateStmtContext*cxt);
127127
staticvoidtransformFKConstraints(CreateStmtContext*cxt,
128128
boolskipValidation,
129129
boolisAddConstraint);
@@ -243,7 +243,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
243243
cxt.fkconstraints=NIL;
244244
cxt.ixconstraints=NIL;
245245
cxt.likeclauses=NIL;
246-
cxt.extstats=NIL;
247246
cxt.blist=NIL;
248247
cxt.alist=NIL;
249248
cxt.pkey=NULL;
@@ -336,11 +335,6 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
336335
*/
337336
transformCheckConstraints(&cxt, !cxt.isforeign);
338337

339-
/*
340-
* Postprocess extended statistics.
341-
*/
342-
transformExtendedStatistics(&cxt);
343-
344338
/*
345339
* Output results.
346340
*/
@@ -1132,61 +1126,25 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
11321126
}
11331127

11341128
/*
1135-
* We cannot yet deal with defaults, CHECK constraints, or indexes, since
1136-
* we don't yet know what column numbers the copied columns will have in
1137-
* the finished table. If any of those options are specified, add the
1138-
* LIKE clause to cxt->likeclauses so that expandTableLikeClause will be
1139-
* called after we do know that. Also, remember the relation OID so that
1140-
* expandTableLikeClause is certain to open the same table.
1129+
* We cannot yet deal with defaults, CHECK constraints, indexes, or
1130+
* statistics, since we don't yet know what column numbers the copied
1131+
* columns will have in the finished table. If any of those options are
1132+
* specified, add the LIKE clause to cxt->likeclauses so that
1133+
* expandTableLikeClause will be called after we do know that. Also,
1134+
* remember the relation OID so that expandTableLikeClause is certain to
1135+
* open the same table.
11411136
*/
11421137
if (table_like_clause->options&
11431138
(CREATE_TABLE_LIKE_DEFAULTS |
11441139
CREATE_TABLE_LIKE_GENERATED |
11451140
CREATE_TABLE_LIKE_CONSTRAINTS |
1146-
CREATE_TABLE_LIKE_INDEXES))
1141+
CREATE_TABLE_LIKE_INDEXES |
1142+
CREATE_TABLE_LIKE_STATISTICS))
11471143
{
11481144
table_like_clause->relationOid=RelationGetRelid(relation);
11491145
cxt->likeclauses=lappend(cxt->likeclauses,table_like_clause);
11501146
}
11511147

1152-
/*
1153-
* We may copy extended statistics if requested, since the representation
1154-
* of CreateStatsStmt doesn't depend on column numbers.
1155-
*/
1156-
if (table_like_clause->options&CREATE_TABLE_LIKE_STATISTICS)
1157-
{
1158-
List*parent_extstats;
1159-
ListCell*l;
1160-
1161-
parent_extstats=RelationGetStatExtList(relation);
1162-
1163-
foreach(l,parent_extstats)
1164-
{
1165-
Oidparent_stat_oid=lfirst_oid(l);
1166-
CreateStatsStmt*stats_stmt;
1167-
1168-
stats_stmt=generateClonedExtStatsStmt(cxt->relation,
1169-
RelationGetRelid(relation),
1170-
parent_stat_oid);
1171-
1172-
/* Copy comment on statistics object, if requested */
1173-
if (table_like_clause->options&CREATE_TABLE_LIKE_COMMENTS)
1174-
{
1175-
comment=GetComment(parent_stat_oid,StatisticExtRelationId,0);
1176-
1177-
/*
1178-
* We make use of CreateStatsStmt's stxcomment option, so as
1179-
* not to need to know now what name the statistics will have.
1180-
*/
1181-
stats_stmt->stxcomment=comment;
1182-
}
1183-
1184-
cxt->extstats=lappend(cxt->extstats,stats_stmt);
1185-
}
1186-
1187-
list_free(parent_extstats);
1188-
}
1189-
11901148
/*
11911149
* Close the parent rel, but keep our AccessShareLock on it until xact
11921150
* commit. That will prevent someone else from deleting or ALTERing the
@@ -1452,6 +1410,44 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
14521410
}
14531411
}
14541412

1413+
/*
1414+
* Process extended statistics if required.
1415+
*/
1416+
if (table_like_clause->options&CREATE_TABLE_LIKE_STATISTICS)
1417+
{
1418+
List*parent_extstats;
1419+
ListCell*l;
1420+
1421+
parent_extstats=RelationGetStatExtList(relation);
1422+
1423+
foreach(l,parent_extstats)
1424+
{
1425+
Oidparent_stat_oid=lfirst_oid(l);
1426+
CreateStatsStmt*stats_stmt;
1427+
1428+
stats_stmt=generateClonedExtStatsStmt(heapRel,
1429+
RelationGetRelid(childrel),
1430+
parent_stat_oid,
1431+
attmap);
1432+
1433+
/* Copy comment on statistics object, if requested */
1434+
if (table_like_clause->options&CREATE_TABLE_LIKE_COMMENTS)
1435+
{
1436+
comment=GetComment(parent_stat_oid,StatisticExtRelationId,0);
1437+
1438+
/*
1439+
* We make use of CreateStatsStmt's stxcomment option, so as
1440+
* not to need to know now what name the statistics will have.
1441+
*/
1442+
stats_stmt->stxcomment=comment;
1443+
}
1444+
1445+
result=lappend(result,stats_stmt);
1446+
}
1447+
1448+
list_free(parent_extstats);
1449+
}
1450+
14551451
/* Done with child rel */
14561452
table_close(childrel,NoLock);
14571453

@@ -1886,10 +1882,12 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
18861882
* Generate a CreateStatsStmt node using information from an already existing
18871883
* extended statistic "source_statsid", for the rel identified by heapRel and
18881884
* heapRelid.
1885+
*
1886+
* Attribute numbers in expression Vars are adjusted according to attmap.
18891887
*/
18901888
staticCreateStatsStmt*
18911889
generateClonedExtStatsStmt(RangeVar*heapRel,OidheapRelid,
1892-
Oidsource_statsid)
1890+
Oidsource_statsid,constAttrMap*attmap)
18931891
{
18941892
HeapTupleht_stats;
18951893
Form_pg_statistic_extstatsrec;
@@ -1973,10 +1971,19 @@ generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid,
19731971

19741972
foreach(lc,exprs)
19751973
{
1974+
Node*expr= (Node*)lfirst(lc);
19761975
StatsElem*selem=makeNode(StatsElem);
1976+
boolfound_whole_row;
1977+
1978+
/* Adjust Vars to match new table's column numbering */
1979+
expr=map_variable_attnos(expr,
1980+
1,0,
1981+
attmap,
1982+
InvalidOid,
1983+
&found_whole_row);
19771984

19781985
selem->name=NULL;
1979-
selem->expr=(Node*)lfirst(lc);
1986+
selem->expr=expr;
19801987

19811988
def_names=lappend(def_names,selem);
19821989
}
@@ -2703,19 +2710,6 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
27032710
returnindex;
27042711
}
27052712

2706-
/*
2707-
* transformExtendedStatistics
2708-
* Handle extended statistic objects
2709-
*
2710-
* Right now, there's nothing to do here, so we just append the list to
2711-
* the existing "after" list.
2712-
*/
2713-
staticvoid
2714-
transformExtendedStatistics(CreateStmtContext*cxt)
2715-
{
2716-
cxt->alist=list_concat(cxt->alist,cxt->extstats);
2717-
}
2718-
27192713
/*
27202714
* transformCheckConstraints
27212715
*handle CHECK constraints
@@ -3358,7 +3352,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
33583352
cxt.fkconstraints=NIL;
33593353
cxt.ixconstraints=NIL;
33603354
cxt.likeclauses=NIL;
3361-
cxt.extstats=NIL;
33623355
cxt.blist=NIL;
33633356
cxt.alist=NIL;
33643357
cxt.pkey=NULL;
@@ -3640,9 +3633,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
36403633
newcmds=lappend(newcmds,newcmd);
36413634
}
36423635

3643-
/* Append extended statistics objects */
3644-
transformExtendedStatistics(&cxt);
3645-
36463636
/* Close rel */
36473637
relation_close(rel,NoLock);
36483638

‎src/test/regress/expected/create_table_like.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,23 @@ Check constraints:
261261
Inherits: test_like_5,
262262
test_like_5x
263263

264+
-- Test updating of column numbers in statistics expressions (bug #18468)
265+
CREATE TABLE test_like_6 (a int, c text, b text);
266+
CREATE STATISTICS ext_stat ON (a || b) FROM test_like_6;
267+
ALTER TABLE test_like_6 DROP COLUMN c;
268+
CREATE TABLE test_like_6c (LIKE test_like_6 INCLUDING ALL);
269+
\d+ test_like_6c
270+
Table "public.test_like_6c"
271+
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
272+
--------+---------+-----------+----------+---------+----------+--------------+-------------
273+
a | integer | | | | plain | |
274+
b | text | | | | extended | |
275+
Statistics objects:
276+
"public.test_like_6c_expr_stat" ON (a || b) FROM test_like_6c
277+
264278
DROP TABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
265279
DROP TABLE test_like_5, test_like_5x, test_like_5c;
280+
DROP TABLE test_like_6, test_like_6c;
266281
CREATE TABLE inhg (x text, LIKE inhx INCLUDING INDEXES, y text); /* copies indexes */
267282
INSERT INTO inhg VALUES (5, 10);
268283
INSERT INTO inhg VALUES (20, 10); -- should fail

‎src/test/regress/sql/create_table_like.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,16 @@ CREATE TABLE test_like_5c (LIKE test_like_4 INCLUDING ALL)
9595
INHERITS (test_like_5, test_like_5x);
9696
\d test_like_5c
9797

98+
-- Test updating of column numbers in statistics expressions (bug #18468)
99+
CREATETABLEtest_like_6 (aint, ctext, btext);
100+
CREATE STATISTICS ext_statON (a|| b)FROM test_like_6;
101+
ALTERTABLE test_like_6 DROP COLUMN c;
102+
CREATETABLEtest_like_6c (LIKE test_like_6 INCLUDING ALL);
103+
\d+ test_like_6c
104+
98105
DROPTABLE test_like_4, test_like_4a, test_like_4b, test_like_4c, test_like_4d;
99106
DROPTABLE test_like_5, test_like_5x, test_like_5c;
107+
DROPTABLE test_like_6, test_like_6c;
100108

101109
CREATETABLEinhg (xtext,LIKE inhx INCLUDING INDEXES, ytext);/* copies indexes*/
102110
INSERT INTO inhgVALUES (5,10);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp