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

Commita4425e3

Browse files
committed
Fix collation handling in plpgsql functions.
Make plpgsql treat the input collation as a polymorphism variable, sothat we cache separate plans for each input collation that's used in aparticular session, as per recent discussion. Propagate the inputcollation to all collatable input parameters.I chose to also propagate the input collation to all declared variables ofcollatable types, which is a bit more debatable but seems to be necessaryfor non-astonishing behavior. (Copying a parameter into a separate localvariable shouldn't result in a change of behavior, for example.) There isenough infrastructure here to support declaring a collation for each localvariable to override that default, but I thought we should wait to see whatthe field demand is before adding such a feature.In passing, remove exec_get_rec_fieldtype(), which wasn't used anywhere.Documentation patch to follow.
1 parentf6f0916 commita4425e3

File tree

6 files changed

+207
-102
lines changed

6 files changed

+207
-102
lines changed

‎src/pl/plpgsql/src/gram.y

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,8 @@ decl_statement: decl_varname decl_const decl_datatype decl_notnull decl_defval
487487
new = (PLpgSQL_var *)
488488
plpgsql_build_variable($1.name, $1.lineno,
489489
plpgsql_build_datatype(REFCURSOROID,
490-
-1),
490+
-1,
491+
InvalidOid),
491492
true);
492493

493494
curname_def = palloc0(sizeof(PLpgSQL_expr));
@@ -1248,7 +1249,8 @@ for_control: for_variable K_IN
12481249
plpgsql_build_variable($1.name,
12491250
$1.lineno,
12501251
plpgsql_build_datatype(INT4OID,
1251-
-1),
1252+
-1,
1253+
InvalidOid),
12521254
true);
12531255

12541256
new =palloc0(sizeof(PLpgSQL_stmt_fori));
@@ -1932,13 +1934,17 @@ exception_sect:
19321934
PLpgSQL_variable *var;
19331935

19341936
var =plpgsql_build_variable("sqlstate", lineno,
1935-
plpgsql_build_datatype(TEXTOID, -1),
1937+
plpgsql_build_datatype(TEXTOID,
1938+
-1,
1939+
plpgsql_curr_compile->fn_input_collation),
19361940
true);
19371941
((PLpgSQL_var *) var)->isconst =true;
19381942
new->sqlstate_varno = var->dno;
19391943

19401944
var =plpgsql_build_variable("sqlerrm", lineno,
1941-
plpgsql_build_datatype(TEXTOID, -1),
1945+
plpgsql_build_datatype(TEXTOID,
1946+
-1,
1947+
plpgsql_curr_compile->fn_input_collation),
19421948
true);
19431949
((PLpgSQL_var *) var)->isconst =true;
19441950
new->sqlerrm_varno = var->dno;
@@ -3227,7 +3233,8 @@ parse_datatype(const char *string, int location)
32273233
error_context_stack = syntax_errcontext.previous;
32283234

32293235
/* Okay, build a PLpgSQL_type data structure for it*/
3230-
return plpgsql_build_datatype(type_id, typmod);
3236+
return plpgsql_build_datatype(type_id, typmod,
3237+
plpgsql_curr_compile->fn_input_collation);
32313238
}
32323239

32333240
/*
@@ -3400,7 +3407,9 @@ make_case(int location, PLpgSQL_expr *t_expr,
34003407
*/
34013408
t_var = (PLpgSQL_var *)
34023409
plpgsql_build_variable(varname, new->lineno,
3403-
plpgsql_build_datatype(INT4OID, -1),
3410+
plpgsql_build_datatype(INT4OID,
3411+
-1,
3412+
InvalidOid),
34043413
true);
34053414
new->t_varno = t_var->dno;
34063415

‎src/pl/plpgsql/src/pl_comp.c

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
104104
staticNode*make_datum_param(PLpgSQL_expr*expr,intdno,intlocation);
105105
staticPLpgSQL_row*build_row_from_class(OidclassOid);
106106
staticPLpgSQL_row*build_row_from_vars(PLpgSQL_variable**vars,intnumvars);
107-
staticPLpgSQL_type*build_datatype(HeapTupletypeTup,int32typmod);
107+
staticPLpgSQL_type*build_datatype(HeapTupletypeTup,int32typmod,Oidcollation);
108108
staticvoidcompute_function_hashkey(FunctionCallInfofcinfo,
109109
Form_pg_procprocStruct,
110110
PLpgSQL_func_hashkey*hashkey,
@@ -348,6 +348,7 @@ do_compile(FunctionCallInfo fcinfo,
348348
function->fn_xmin=HeapTupleHeaderGetXmin(procTup->t_data);
349349
function->fn_tid=procTup->t_self;
350350
function->fn_is_trigger=is_trigger;
351+
function->fn_input_collation=fcinfo->flinfo->fn_collation;
351352
function->fn_cxt=func_cxt;
352353
function->out_param_varno=-1;/* set up for no OUT param */
353354
function->resolve_option=plpgsql_variable_conflict;
@@ -411,7 +412,9 @@ do_compile(FunctionCallInfo fcinfo,
411412
snprintf(buf,sizeof(buf),"$%d",i+1);
412413

413414
/* Create datatype info */
414-
argdtype=plpgsql_build_datatype(argtypeid,-1);
415+
argdtype=plpgsql_build_datatype(argtypeid,
416+
-1,
417+
function->fn_input_collation);
415418

416419
/* Disallow pseudotype argument */
417420
/* (note we already replaced polymorphic types) */
@@ -556,7 +559,9 @@ do_compile(FunctionCallInfo fcinfo,
556559
num_out_args==0)
557560
{
558561
(void)plpgsql_build_variable("$0",0,
559-
build_datatype(typeTup,-1),
562+
build_datatype(typeTup,
563+
-1,
564+
function->fn_input_collation),
560565
true);
561566
}
562567
}
@@ -587,61 +592,81 @@ do_compile(FunctionCallInfo fcinfo,
587592

588593
/* Add the variable tg_name */
589594
var=plpgsql_build_variable("tg_name",0,
590-
plpgsql_build_datatype(NAMEOID,-1),
595+
plpgsql_build_datatype(NAMEOID,
596+
-1,
597+
InvalidOid),
591598
true);
592599
function->tg_name_varno=var->dno;
593600

594601
/* Add the variable tg_when */
595602
var=plpgsql_build_variable("tg_when",0,
596-
plpgsql_build_datatype(TEXTOID,-1),
603+
plpgsql_build_datatype(TEXTOID,
604+
-1,
605+
function->fn_input_collation),
597606
true);
598607
function->tg_when_varno=var->dno;
599608

600609
/* Add the variable tg_level */
601610
var=plpgsql_build_variable("tg_level",0,
602-
plpgsql_build_datatype(TEXTOID,-1),
611+
plpgsql_build_datatype(TEXTOID,
612+
-1,
613+
function->fn_input_collation),
603614
true);
604615
function->tg_level_varno=var->dno;
605616

606617
/* Add the variable tg_op */
607618
var=plpgsql_build_variable("tg_op",0,
608-
plpgsql_build_datatype(TEXTOID,-1),
619+
plpgsql_build_datatype(TEXTOID,
620+
-1,
621+
function->fn_input_collation),
609622
true);
610623
function->tg_op_varno=var->dno;
611624

612625
/* Add the variable tg_relid */
613626
var=plpgsql_build_variable("tg_relid",0,
614-
plpgsql_build_datatype(OIDOID,-1),
627+
plpgsql_build_datatype(OIDOID,
628+
-1,
629+
InvalidOid),
615630
true);
616631
function->tg_relid_varno=var->dno;
617632

618633
/* Add the variable tg_relname */
619634
var=plpgsql_build_variable("tg_relname",0,
620-
plpgsql_build_datatype(NAMEOID,-1),
635+
plpgsql_build_datatype(NAMEOID,
636+
-1,
637+
InvalidOid),
621638
true);
622639
function->tg_relname_varno=var->dno;
623640

624641
/* tg_table_name is now preferred to tg_relname */
625642
var=plpgsql_build_variable("tg_table_name",0,
626-
plpgsql_build_datatype(NAMEOID,-1),
643+
plpgsql_build_datatype(NAMEOID,
644+
-1,
645+
InvalidOid),
627646
true);
628647
function->tg_table_name_varno=var->dno;
629648

630649
/* add the variable tg_table_schema */
631650
var=plpgsql_build_variable("tg_table_schema",0,
632-
plpgsql_build_datatype(NAMEOID,-1),
651+
plpgsql_build_datatype(NAMEOID,
652+
-1,
653+
InvalidOid),
633654
true);
634655
function->tg_table_schema_varno=var->dno;
635656

636657
/* Add the variable tg_nargs */
637658
var=plpgsql_build_variable("tg_nargs",0,
638-
plpgsql_build_datatype(INT4OID,-1),
659+
plpgsql_build_datatype(INT4OID,
660+
-1,
661+
InvalidOid),
639662
true);
640663
function->tg_nargs_varno=var->dno;
641664

642665
/* Add the variable tg_argv */
643666
var=plpgsql_build_variable("tg_argv",0,
644-
plpgsql_build_datatype(TEXTARRAYOID,-1),
667+
plpgsql_build_datatype(TEXTARRAYOID,
668+
-1,
669+
function->fn_input_collation),
645670
true);
646671
function->tg_argv_varno=var->dno;
647672

@@ -659,7 +684,9 @@ do_compile(FunctionCallInfo fcinfo,
659684
* Create the magic FOUND variable.
660685
*/
661686
var=plpgsql_build_variable("found",0,
662-
plpgsql_build_datatype(BOOLOID,-1),
687+
plpgsql_build_datatype(BOOLOID,
688+
-1,
689+
InvalidOid),
663690
true);
664691
function->found_varno=var->dno;
665692

@@ -777,6 +804,7 @@ plpgsql_compile_inline(char *proc_source)
777804

778805
function->fn_name=pstrdup(func_name);
779806
function->fn_is_trigger= false;
807+
function->fn_input_collation=InvalidOid;
780808
function->fn_cxt=func_cxt;
781809
function->out_param_varno=-1;/* set up for no OUT param */
782810
function->resolve_option=plpgsql_variable_conflict;
@@ -810,7 +838,9 @@ plpgsql_compile_inline(char *proc_source)
810838
* Create the magic FOUND variable.
811839
*/
812840
var=plpgsql_build_variable("found",0,
813-
plpgsql_build_datatype(BOOLOID,-1),
841+
plpgsql_build_datatype(BOOLOID,
842+
-1,
843+
InvalidOid),
814844
true);
815845
function->found_varno=var->dno;
816846

@@ -1218,13 +1248,14 @@ static Node *
12181248
make_datum_param(PLpgSQL_expr*expr,intdno,intlocation)
12191249
{
12201250
PLpgSQL_execstate*estate;
1251+
PLpgSQL_datum*datum;
12211252
Param*param;
12221253
MemoryContextoldcontext;
12231254

12241255
/* see comment in resolve_column_ref */
12251256
estate=expr->func->cur_estate;
1226-
12271257
Assert(dno >=0&&dno<estate->ndatums);
1258+
datum=estate->datums[dno];
12281259

12291260
/*
12301261
* Bitmapset must be allocated in function's permanent memory context
@@ -1236,9 +1267,9 @@ make_datum_param(PLpgSQL_expr *expr, int dno, int location)
12361267
param=makeNode(Param);
12371268
param->paramkind=PARAM_EXTERN;
12381269
param->paramid=dno+1;
1239-
param->paramtype=exec_get_datum_type(estate,estate->datums[dno]);
1270+
param->paramtype=exec_get_datum_type(estate,datum);
12401271
param->paramtypmod=-1;
1241-
param->paramcollid=get_typcollation(param->paramtype);
1272+
param->paramcollid=exec_get_datum_collation(estate,datum);
12421273
param->location=location;
12431274

12441275
return (Node*)param;
@@ -1578,7 +1609,8 @@ plpgsql_parse_wordtype(char *ident)
15781609
returnNULL;
15791610
}
15801611

1581-
dtype=build_datatype(typeTup,-1);
1612+
dtype=build_datatype(typeTup,-1,
1613+
plpgsql_curr_compile->fn_input_collation);
15821614

15831615
ReleaseSysCache(typeTup);
15841616
returndtype;
@@ -1687,7 +1719,9 @@ plpgsql_parse_cwordtype(List *idents)
16871719
* return it
16881720
*/
16891721
MemoryContextSwitchTo(oldCxt);
1690-
dtype=build_datatype(typetup,attrStruct->atttypmod);
1722+
dtype=build_datatype(typetup,
1723+
attrStruct->atttypmod,
1724+
attrStruct->attcollation);
16911725
MemoryContextSwitchTo(compile_tmp_cxt);
16921726

16931727
done:
@@ -1720,7 +1754,7 @@ plpgsql_parse_wordrowtype(char *ident)
17201754
errmsg("relation \"%s\" does not exist",ident)));
17211755

17221756
/* Build and return the row type struct */
1723-
returnplpgsql_build_datatype(get_rel_type_id(classOid),-1);
1757+
returnplpgsql_build_datatype(get_rel_type_id(classOid),-1,InvalidOid);
17241758
}
17251759

17261760
/* ----------
@@ -1755,7 +1789,7 @@ plpgsql_parse_cwordrowtype(List *idents)
17551789
MemoryContextSwitchTo(oldCxt);
17561790

17571791
/* Build and return the row type struct */
1758-
returnplpgsql_build_datatype(get_rel_type_id(classOid),-1);
1792+
returnplpgsql_build_datatype(get_rel_type_id(classOid),-1,InvalidOid);
17591793
}
17601794

17611795
/*
@@ -1935,7 +1969,8 @@ build_row_from_class(Oid classOid)
19351969
*/
19361970
var=plpgsql_build_variable(refname,0,
19371971
plpgsql_build_datatype(attrStruct->atttypid,
1938-
attrStruct->atttypmod),
1972+
attrStruct->atttypmod,
1973+
attrStruct->attcollation),
19391974
false);
19401975

19411976
/* Add the variable to the row */
@@ -2013,10 +2048,13 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
20132048

20142049
/*
20152050
* plpgsql_build_datatype
2016-
*Build PLpgSQL_type struct given type OID and typmod.
2051+
*Build PLpgSQL_type struct given type OID, typmod, and collation.
2052+
*
2053+
* If collation is not InvalidOid then it overrides the type's default
2054+
* collation. But collation is ignored if the datatype is non-collatable.
20172055
*/
20182056
PLpgSQL_type*
2019-
plpgsql_build_datatype(OidtypeOid,int32typmod)
2057+
plpgsql_build_datatype(OidtypeOid,int32typmod,Oidcollation)
20202058
{
20212059
HeapTupletypeTup;
20222060
PLpgSQL_type*typ;
@@ -2025,7 +2063,7 @@ plpgsql_build_datatype(Oid typeOid, int32 typmod)
20252063
if (!HeapTupleIsValid(typeTup))
20262064
elog(ERROR,"cache lookup failed for type %u",typeOid);
20272065

2028-
typ=build_datatype(typeTup,typmod);
2066+
typ=build_datatype(typeTup,typmod,collation);
20292067

20302068
ReleaseSysCache(typeTup);
20312069

@@ -2036,7 +2074,7 @@ plpgsql_build_datatype(Oid typeOid, int32 typmod)
20362074
* Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
20372075
*/
20382076
staticPLpgSQL_type*
2039-
build_datatype(HeapTupletypeTup,int32typmod)
2077+
build_datatype(HeapTupletypeTup,int32typmod,Oidcollation)
20402078
{
20412079
Form_pg_typetypeStruct= (Form_pg_type)GETSTRUCT(typeTup);
20422080
PLpgSQL_type*typ;
@@ -2077,6 +2115,9 @@ build_datatype(HeapTuple typeTup, int32 typmod)
20772115
typ->typbyval=typeStruct->typbyval;
20782116
typ->typrelid=typeStruct->typrelid;
20792117
typ->typioparam=getTypeIOParam(typeTup);
2118+
typ->collation=typeStruct->typcollation;
2119+
if (OidIsValid(collation)&&OidIsValid(typ->collation))
2120+
typ->collation=collation;
20802121
fmgr_info(typeStruct->typinput,&(typ->typinput));
20812122
typ->atttypmod=typmod;
20822123

@@ -2285,6 +2326,9 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
22852326
hashkey->trigrelOid=RelationGetRelid(trigdata->tg_relation);
22862327
}
22872328

2329+
/* get input collation, if known */
2330+
hashkey->inputCollation=fcinfo->flinfo->fn_collation;
2331+
22882332
if (procStruct->pronargs>0)
22892333
{
22902334
/* get the argument types */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp