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

Commit1015162

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 parent5ac3406 commit1015162

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
*/
@@ -1123,61 +1117,25 @@ transformTableLikeClause(CreateStmtContext *cxt, TableLikeClause *table_like_cla
11231117
}
11241118

11251119
/*
1126-
* We cannot yet deal with defaults, CHECK constraints, or indexes, since
1127-
* we don't yet know what column numbers the copied columns will have in
1128-
* the finished table. If any of those options are specified, add the
1129-
* LIKE clause to cxt->likeclauses so that expandTableLikeClause will be
1130-
* called after we do know that. Also, remember the relation OID so that
1131-
* expandTableLikeClause is certain to open the same table.
1120+
* We cannot yet deal with defaults, CHECK constraints, indexes, or
1121+
* statistics, since we don't yet know what column numbers the copied
1122+
* columns will have in the finished table. If any of those options are
1123+
* specified, add the LIKE clause to cxt->likeclauses so that
1124+
* expandTableLikeClause will be called after we do know that. Also,
1125+
* remember the relation OID so that expandTableLikeClause is certain to
1126+
* open the same table.
11321127
*/
11331128
if (table_like_clause->options&
11341129
(CREATE_TABLE_LIKE_DEFAULTS |
11351130
CREATE_TABLE_LIKE_GENERATED |
11361131
CREATE_TABLE_LIKE_CONSTRAINTS |
1137-
CREATE_TABLE_LIKE_INDEXES))
1132+
CREATE_TABLE_LIKE_INDEXES |
1133+
CREATE_TABLE_LIKE_STATISTICS))
11381134
{
11391135
table_like_clause->relationOid=RelationGetRelid(relation);
11401136
cxt->likeclauses=lappend(cxt->likeclauses,table_like_clause);
11411137
}
11421138

1143-
/*
1144-
* We may copy extended statistics if requested, since the representation
1145-
* of CreateStatsStmt doesn't depend on column numbers.
1146-
*/
1147-
if (table_like_clause->options&CREATE_TABLE_LIKE_STATISTICS)
1148-
{
1149-
List*parent_extstats;
1150-
ListCell*l;
1151-
1152-
parent_extstats=RelationGetStatExtList(relation);
1153-
1154-
foreach(l,parent_extstats)
1155-
{
1156-
Oidparent_stat_oid=lfirst_oid(l);
1157-
CreateStatsStmt*stats_stmt;
1158-
1159-
stats_stmt=generateClonedExtStatsStmt(cxt->relation,
1160-
RelationGetRelid(relation),
1161-
parent_stat_oid);
1162-
1163-
/* Copy comment on statistics object, if requested */
1164-
if (table_like_clause->options&CREATE_TABLE_LIKE_COMMENTS)
1165-
{
1166-
comment=GetComment(parent_stat_oid,StatisticExtRelationId,0);
1167-
1168-
/*
1169-
* We make use of CreateStatsStmt's stxcomment option, so as
1170-
* not to need to know now what name the statistics will have.
1171-
*/
1172-
stats_stmt->stxcomment=comment;
1173-
}
1174-
1175-
cxt->extstats=lappend(cxt->extstats,stats_stmt);
1176-
}
1177-
1178-
list_free(parent_extstats);
1179-
}
1180-
11811139
/*
11821140
* Close the parent rel, but keep our AccessShareLock on it until xact
11831141
* commit. That will prevent someone else from deleting or ALTERing the
@@ -1443,6 +1401,44 @@ expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
14431401
}
14441402
}
14451403

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

@@ -1876,10 +1872,12 @@ generateClonedIndexStmt(RangeVar *heapRel, Relation source_idx,
18761872
* Generate a CreateStatsStmt node using information from an already existing
18771873
* extended statistic "source_statsid", for the rel identified by heapRel and
18781874
* heapRelid.
1875+
*
1876+
* Attribute numbers in expression Vars are adjusted according to attmap.
18791877
*/
18801878
staticCreateStatsStmt*
18811879
generateClonedExtStatsStmt(RangeVar*heapRel,OidheapRelid,
1882-
Oidsource_statsid)
1880+
Oidsource_statsid,constAttrMap*attmap)
18831881
{
18841882
HeapTupleht_stats;
18851883
Form_pg_statistic_extstatsrec;
@@ -1963,10 +1961,19 @@ generateClonedExtStatsStmt(RangeVar *heapRel, Oid heapRelid,
19631961

19641962
foreach(lc,exprs)
19651963
{
1964+
Node*expr= (Node*)lfirst(lc);
19661965
StatsElem*selem=makeNode(StatsElem);
1966+
boolfound_whole_row;
1967+
1968+
/* Adjust Vars to match new table's column numbering */
1969+
expr=map_variable_attnos(expr,
1970+
1,0,
1971+
attmap,
1972+
InvalidOid,
1973+
&found_whole_row);
19671974

19681975
selem->name=NULL;
1969-
selem->expr=(Node*)lfirst(lc);
1976+
selem->expr=expr;
19701977

19711978
def_names=lappend(def_names,selem);
19721979
}
@@ -2691,19 +2698,6 @@ transformIndexConstraint(Constraint *constraint, CreateStmtContext *cxt)
26912698
returnindex;
26922699
}
26932700

2694-
/*
2695-
* transformExtendedStatistics
2696-
* Handle extended statistic objects
2697-
*
2698-
* Right now, there's nothing to do here, so we just append the list to
2699-
* the existing "after" list.
2700-
*/
2701-
staticvoid
2702-
transformExtendedStatistics(CreateStmtContext*cxt)
2703-
{
2704-
cxt->alist=list_concat(cxt->alist,cxt->extstats);
2705-
}
2706-
27072701
/*
27082702
* transformCheckConstraints
27092703
*handle CHECK constraints
@@ -3346,7 +3340,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
33463340
cxt.fkconstraints=NIL;
33473341
cxt.ixconstraints=NIL;
33483342
cxt.likeclauses=NIL;
3349-
cxt.extstats=NIL;
33503343
cxt.blist=NIL;
33513344
cxt.alist=NIL;
33523345
cxt.pkey=NULL;
@@ -3628,9 +3621,6 @@ transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
36283621
newcmds=lappend(newcmds,newcmd);
36293622
}
36303623

3631-
/* Append extended statistics objects */
3632-
transformExtendedStatistics(&cxt);
3633-
36343624
/* Close rel */
36353625
relation_close(rel,NoLock);
36363626

‎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