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

Commit918854c

Browse files
committed
Fix handling of collations in multi-row VALUES constructs.
Per spec we ought to apply select_common_collation() across the expressionsin each column of the VALUES table. The original coding was just takingthe first row and assuming it was representative.This patch adds a field to struct RangeTblEntry to carry the resolvedcollations, so initdb is forced for changes in stored rule representation.
1 parent04db0fd commit918854c

File tree

13 files changed

+131
-53
lines changed

13 files changed

+131
-53
lines changed

‎src/backend/catalog/dependency.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,10 +1671,15 @@ find_expr_references_walker(Node *node,
16711671
/*
16721672
* Add whole-relation refs for each plain relation mentioned in the
16731673
* subquery's rtable, as well as refs for any datatypes and collations
1674-
* used in a RECORD function's output. (Note: query_tree_walker takes
1675-
* care of recursing into RTE_FUNCTION RTEs, subqueries, etc, so no
1676-
* need to do that here. But keep it from looking at join alias
1677-
* lists.)
1674+
* used in a RECORD function's output.
1675+
*
1676+
* Note: query_tree_walker takes care of recursing into RTE_FUNCTION
1677+
* RTEs, subqueries, etc, so no need to do that here. But keep it
1678+
* from looking at join alias lists.
1679+
*
1680+
* Note: we don't need to worry about collations mentioned in
1681+
* RTE_VALUES or RTE_CTE RTEs, because those must just duplicate
1682+
* collations referenced in other parts of the Query.
16781683
*/
16791684
foreach(lc,query->rtable)
16801685
{

‎src/backend/nodes/copyfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1951,6 +1951,7 @@ _copyRangeTblEntry(RangeTblEntry *from)
19511951
COPY_NODE_FIELD(funccoltypmods);
19521952
COPY_NODE_FIELD(funccolcollations);
19531953
COPY_NODE_FIELD(values_lists);
1954+
COPY_NODE_FIELD(values_collations);
19541955
COPY_STRING_FIELD(ctename);
19551956
COPY_SCALAR_FIELD(ctelevelsup);
19561957
COPY_SCALAR_FIELD(self_reference);

‎src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2310,6 +2310,7 @@ _equalRangeTblEntry(RangeTblEntry *a, RangeTblEntry *b)
23102310
COMPARE_NODE_FIELD(funccoltypmods);
23112311
COMPARE_NODE_FIELD(funccolcollations);
23122312
COMPARE_NODE_FIELD(values_lists);
2313+
COMPARE_NODE_FIELD(values_collations);
23132314
COMPARE_STRING_FIELD(ctename);
23142315
COMPARE_SCALAR_FIELD(ctelevelsup);
23152316
COMPARE_SCALAR_FIELD(self_reference);

‎src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,6 +2324,7 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
23242324
break;
23252325
caseRTE_VALUES:
23262326
WRITE_NODE_FIELD(values_lists);
2327+
WRITE_NODE_FIELD(values_collations);
23272328
break;
23282329
caseRTE_CTE:
23292330
WRITE_STRING_FIELD(ctename);

‎src/backend/nodes/readfuncs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,7 @@ _readRangeTblEntry(void)
12031203
break;
12041204
caseRTE_VALUES:
12051205
READ_NODE_FIELD(values_lists);
1206+
READ_NODE_FIELD(values_collations);
12061207
break;
12071208
caseRTE_CTE:
12081209
READ_STRING_FIELD(ctename);

‎src/backend/optimizer/plan/setrefs.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ set_plan_references(PlannerGlobal *glob, Plan *plan,
216216
newrte->funccoltypmods=NIL;
217217
newrte->funccolcollations=NIL;
218218
newrte->values_lists=NIL;
219+
newrte->values_collations=NIL;
219220
newrte->ctecoltypes=NIL;
220221
newrte->ctecoltypmods=NIL;
221222
newrte->ctecolcollations=NIL;

‎src/backend/parser/analyze.c

Lines changed: 85 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -536,7 +536,9 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
536536
* RTE.
537537
*/
538538
List*exprsLists=NIL;
539+
List*collations=NIL;
539540
intsublist_length=-1;
541+
inti;
540542

541543
foreach(lc,selectStmt->valuesLists)
542544
{
@@ -573,13 +575,26 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
573575
* We must assign collations now because assign_query_collations
574576
* doesn't process rangetable entries. We just assign all the
575577
* collations independently in each row, and don't worry about
576-
* whether they are consistent vertically either.
578+
* whether they are consistent vertically. The outer INSERT query
579+
* isn't going to care about the collations of the VALUES columns,
580+
* so it's not worth the effort to identify a common collation for
581+
* each one here. (But note this does have one user-visible
582+
* consequence: INSERT ... VALUES won't complain about conflicting
583+
* explicit COLLATEs in a column, whereas the same VALUES
584+
* construct in another context would complain.)
577585
*/
578586
assign_list_collations(pstate,sublist);
579587

580588
exprsLists=lappend(exprsLists,sublist);
581589
}
582590

591+
/*
592+
* Although we don't really need collation info, let's just make sure
593+
* we provide a correctly-sized list in the VALUES RTE.
594+
*/
595+
for (i=0;i<sublist_length;i++)
596+
collations=lappend_oid(collations,InvalidOid);
597+
583598
/*
584599
* There mustn't have been any table references in the expressions,
585600
* else strange things would happen, like Cartesian products of those
@@ -610,7 +625,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
610625
/*
611626
* Generate the VALUES RTE
612627
*/
613-
rte=addRangeTableEntryForValues(pstate,exprsLists,NULL, true);
628+
rte=addRangeTableEntryForValues(pstate,exprsLists,collations,
629+
NULL, true);
614630
rtr=makeNode(RangeTblRef);
615631
/* assume new rte is at end */
616632
rtr->rtindex=list_length(pstate->p_rtable);
@@ -989,11 +1005,10 @@ static Query *
9891005
transformValuesClause(ParseState*pstate,SelectStmt*stmt)
9901006
{
9911007
Query*qry=makeNode(Query);
992-
List*exprsLists=NIL;
1008+
List*exprsLists;
1009+
List*collations;
9931010
List**colexprs=NULL;
994-
Oid*coltypes=NULL;
9951011
intsublist_length=-1;
996-
List*newExprsLists;
9971012
RangeTblEntry*rte;
9981013
RangeTblRef*rtr;
9991014
ListCell*lc;
@@ -1021,9 +1036,13 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
10211036
}
10221037

10231038
/*
1024-
* For each row of VALUES, transform the raw expressions and gather type
1025-
* information. This is also a handy place to reject DEFAULT nodes, which
1026-
* the grammar allows for simplicity.
1039+
* For each row of VALUES, transform the raw expressions. This is also a
1040+
* handy place to reject DEFAULT nodes, which the grammar allows for
1041+
* simplicity.
1042+
*
1043+
* Note that the intermediate representation we build is column-organized
1044+
* not row-organized. That simplifies the type and collation processing
1045+
* below.
10271046
*/
10281047
foreach(lc,stmt->valuesLists)
10291048
{
@@ -1041,9 +1060,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
10411060
{
10421061
/* Remember post-transformation length of first sublist */
10431062
sublist_length=list_length(sublist);
1044-
/* and allocatearrays for per-columninfo */
1063+
/* and allocatearray for per-columnlists */
10451064
colexprs= (List**)palloc0(sublist_length*sizeof(List*));
1046-
coltypes= (Oid*)palloc0(sublist_length*sizeof(Oid));
10471065
}
10481066
elseif (sublist_length!=list_length(sublist))
10491067
{
@@ -1054,8 +1072,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
10541072
exprLocation((Node*)sublist))));
10551073
}
10561074

1057-
exprsLists=lappend(exprsLists,sublist);
1058-
10591075
/* Check for DEFAULT and build per-column expression lists */
10601076
i=0;
10611077
foreach(lc2,sublist)
@@ -1070,48 +1086,77 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
10701086
colexprs[i]=lappend(colexprs[i],col);
10711087
i++;
10721088
}
1089+
1090+
/* Release sub-list's cells to save memory */
1091+
list_free(sublist);
10731092
}
10741093

10751094
/*
10761095
* Now resolve the common types of the columns, and coerce everything to
1077-
* those types.
1096+
* those types. Then identify the common collation, if any, of each
1097+
* column.
1098+
*
1099+
* We must do collation processing now because (1) assign_query_collations
1100+
* doesn't process rangetable entries, and (2) we need to label the VALUES
1101+
* RTE with column collations for use in the outer query. We don't
1102+
* consider conflict of implicit collations to be an error here; instead
1103+
* the column will just show InvalidOid as its collation, and you'll get
1104+
* a failure later if that results in failure to resolve a collation.
1105+
*
1106+
* Note we modify the per-column expression lists in-place.
10781107
*/
1108+
collations=NIL;
10791109
for (i=0;i<sublist_length;i++)
10801110
{
1081-
coltypes[i]=select_common_type(pstate,colexprs[i],"VALUES",NULL);
1082-
}
1111+
Oidcoltype;
1112+
Oidcolcoll;
10831113

1084-
newExprsLists=NIL;
1085-
foreach(lc,exprsLists)
1086-
{
1087-
List*sublist= (List*)lfirst(lc);
1088-
List*newsublist=NIL;
1114+
coltype=select_common_type(pstate,colexprs[i],"VALUES",NULL);
10891115

1090-
i=0;
1091-
foreach(lc2,sublist)
1116+
foreach(lc,colexprs[i])
10921117
{
1093-
Node*col= (Node*)lfirst(lc2);
1118+
Node*col= (Node*)lfirst(lc);
10941119

1095-
col=coerce_to_common_type(pstate,col,coltypes[i],"VALUES");
1096-
newsublist=lappend(newsublist,col);
1097-
i++;
1120+
col=coerce_to_common_type(pstate,col,coltype,"VALUES");
1121+
lfirst(lc)= (void*)col;
10981122
}
10991123

1100-
/*
1101-
* We must assign collations now because assign_query_collations
1102-
* doesn't process rangetable entries. We just assign all the
1103-
* collations independently in each row, and don't worry about whether
1104-
* they are consistent vertically either.
1105-
*/
1106-
assign_list_collations(pstate,newsublist);
1124+
colcoll=select_common_collation(pstate,colexprs[i], true);
1125+
1126+
collations=lappend_oid(collations,colcoll);
1127+
}
11071128

1108-
newExprsLists=lappend(newExprsLists,newsublist);
1129+
/*
1130+
* Finally, rearrange the coerced expressions into row-organized lists.
1131+
*/
1132+
exprsLists=NIL;
1133+
foreach(lc,colexprs[0])
1134+
{
1135+
Node*col= (Node*)lfirst(lc);
1136+
List*sublist;
1137+
1138+
sublist=list_make1(col);
1139+
exprsLists=lappend(exprsLists,sublist);
1140+
}
1141+
list_free(colexprs[0]);
1142+
for (i=1;i<sublist_length;i++)
1143+
{
1144+
forboth(lc,colexprs[i],lc2,exprsLists)
1145+
{
1146+
Node*col= (Node*)lfirst(lc);
1147+
List*sublist=lfirst(lc2);
1148+
1149+
/* sublist pointer in exprsLists won't need adjustment */
1150+
(void)lappend(sublist,col);
1151+
}
1152+
list_free(colexprs[i]);
11091153
}
11101154

11111155
/*
11121156
* Generate the VALUES RTE
11131157
*/
1114-
rte=addRangeTableEntryForValues(pstate,newExprsLists,NULL, true);
1158+
rte=addRangeTableEntryForValues(pstate,exprsLists,collations,
1159+
NULL, true);
11151160
rtr=makeNode(RangeTblRef);
11161161
/* assume new rte is at end */
11171162
rtr->rtindex=list_length(pstate->p_rtable);
@@ -1164,7 +1209,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
11641209
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11651210
errmsg("VALUES must not contain table references"),
11661211
parser_errposition(pstate,
1167-
locate_var_of_level((Node*)newExprsLists,0))));
1212+
locate_var_of_level((Node*)exprsLists,0))));
11681213

11691214
/*
11701215
* Another thing we can't currently support is NEW/OLD references in rules
@@ -1173,13 +1218,13 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
11731218
* This is a shame. FIXME
11741219
*/
11751220
if (list_length(pstate->p_rtable)!=1&&
1176-
contain_vars_of_level((Node*)newExprsLists,0))
1221+
contain_vars_of_level((Node*)exprsLists,0))
11771222
ereport(ERROR,
11781223
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
11791224
errmsg("VALUES must not contain OLD or NEW references"),
11801225
errhint("Use SELECT ... UNION ALL ... instead."),
11811226
parser_errposition(pstate,
1182-
locate_var_of_level((Node*)newExprsLists,0))));
1227+
locate_var_of_level((Node*)exprsLists,0))));
11831228

11841229
qry->rtable=pstate->p_rtable;
11851230
qry->jointree=makeFromExpr(pstate->p_joinlist,NULL);
@@ -1191,13 +1236,13 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
11911236
(errcode(ERRCODE_GROUPING_ERROR),
11921237
errmsg("cannot use aggregate function in VALUES"),
11931238
parser_errposition(pstate,
1194-
locate_agg_of_level((Node*)newExprsLists,0))));
1239+
locate_agg_of_level((Node*)exprsLists,0))));
11951240
if (pstate->p_hasWindowFuncs)
11961241
ereport(ERROR,
11971242
(errcode(ERRCODE_WINDOWING_ERROR),
11981243
errmsg("cannot use window function in VALUES"),
11991244
parser_errposition(pstate,
1200-
locate_windowfunc((Node*)newExprsLists))));
1245+
locate_windowfunc((Node*)exprsLists))));
12011246

12021247
assign_query_collations(pstate,qry);
12031248

‎src/backend/parser/parse_relation.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,6 +1220,7 @@ addRangeTableEntryForFunction(ParseState *pstate,
12201220
RangeTblEntry*
12211221
addRangeTableEntryForValues(ParseState*pstate,
12221222
List*exprs,
1223+
List*collations,
12231224
Alias*alias,
12241225
boolinFromCl)
12251226
{
@@ -1233,6 +1234,7 @@ addRangeTableEntryForValues(ParseState *pstate,
12331234
rte->relid=InvalidOid;
12341235
rte->subquery=NULL;
12351236
rte->values_lists=exprs;
1237+
rte->values_collations=collations;
12361238
rte->alias=alias;
12371239

12381240
eref=alias ?copyObject(alias) :makeAlias(refname,NIL);
@@ -1657,7 +1659,9 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
16571659
ListCell*l3;
16581660
intattnum=0;
16591661

1660-
forthree(l1,rte->funccoltypes,l2,rte->funccoltypmods,l3,rte->funccolcollations)
1662+
forthree(l1,rte->funccoltypes,
1663+
l2,rte->funccoltypmods,
1664+
l3,rte->funccolcollations)
16611665
{
16621666
Oidattrtype=lfirst_oid(l1);
16631667
int32attrtypmod=lfirst_int(l2);
@@ -1687,12 +1691,15 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
16871691
{
16881692
/* Values RTE */
16891693
ListCell*aliasp_item=list_head(rte->eref->colnames);
1690-
ListCell*lc;
1694+
ListCell*lcv;
1695+
ListCell*lcc;
16911696

16921697
varattno=0;
1693-
foreach(lc, (List*)linitial(rte->values_lists))
1698+
forboth(lcv, (List*)linitial(rte->values_lists),
1699+
lcc,rte->values_collations)
16941700
{
1695-
Node*col= (Node*)lfirst(lc);
1701+
Node*col= (Node*)lfirst(lcv);
1702+
Oidcolcollation=lfirst_oid(lcc);
16961703

16971704
varattno++;
16981705
if (colnames)
@@ -1712,7 +1719,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
17121719
varnode=makeVar(rtindex,varattno,
17131720
exprType(col),
17141721
exprTypmod(col),
1715-
exprCollation(col),
1722+
colcollation,
17161723
sublevels_up);
17171724
varnode->location=location;
17181725
*colvars=lappend(*colvars,varnode);
@@ -1789,7 +1796,9 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up,
17891796
ListCell*lcc;
17901797

17911798
varattno=0;
1792-
forthree(lct,rte->ctecoltypes,lcm,rte->ctecoltypmods,lcc,rte->ctecolcollations)
1799+
forthree(lct,rte->ctecoltypes,
1800+
lcm,rte->ctecoltypmods,
1801+
lcc,rte->ctecolcollations)
17931802
{
17941803
Oidcoltype=lfirst_oid(lct);
17951804
int32coltypmod=lfirst_int(lcm);
@@ -2116,6 +2125,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
21162125
caseRTE_VALUES:
21172126
{
21182127
/* Values RTE --- get type info from first sublist */
2128+
/* collation is stored separately, though */
21192129
List*collist= (List*)linitial(rte->values_lists);
21202130
Node*col;
21212131

@@ -2125,7 +2135,7 @@ get_rte_attribute_type(RangeTblEntry *rte, AttrNumber attnum,
21252135
col= (Node*)list_nth(collist,attnum-1);
21262136
*vartype=exprType(col);
21272137
*vartypmod=exprTypmod(col);
2128-
*varcollid=exprCollation(col);
2138+
*varcollid=list_nth_oid(rte->values_collations,attnum-1);
21292139
}
21302140
break;
21312141
caseRTE_JOIN:

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/*yyyymmddN */
56-
#defineCATALOG_VERSION_NO201104051
56+
#defineCATALOG_VERSION_NO201104181
5757

5858
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp