@@ -104,7 +104,7 @@ static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
104
104
static Node * make_datum_param (PLpgSQL_expr * expr , int dno , int location );
105
105
static PLpgSQL_row * build_row_from_class (Oid classOid );
106
106
static PLpgSQL_row * build_row_from_vars (PLpgSQL_variable * * vars , int numvars );
107
- static PLpgSQL_type * build_datatype (HeapTuple typeTup , int32 typmod );
107
+ static PLpgSQL_type * build_datatype (HeapTuple typeTup , int32 typmod , Oid collation );
108
108
static void compute_function_hashkey (FunctionCallInfo fcinfo ,
109
109
Form_pg_proc procStruct ,
110
110
PLpgSQL_func_hashkey * hashkey ,
@@ -348,6 +348,7 @@ do_compile(FunctionCallInfo fcinfo,
348
348
function -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
349
349
function -> fn_tid = procTup -> t_self ;
350
350
function -> fn_is_trigger = is_trigger ;
351
+ function -> fn_input_collation = fcinfo -> flinfo -> fn_collation ;
351
352
function -> fn_cxt = func_cxt ;
352
353
function -> out_param_varno = -1 ; /* set up for no OUT param */
353
354
function -> resolve_option = plpgsql_variable_conflict ;
@@ -411,7 +412,9 @@ do_compile(FunctionCallInfo fcinfo,
411
412
snprintf (buf , sizeof (buf ), "$%d" , i + 1 );
412
413
413
414
/* Create datatype info */
414
- argdtype = plpgsql_build_datatype (argtypeid , -1 );
415
+ argdtype = plpgsql_build_datatype (argtypeid ,
416
+ -1 ,
417
+ function -> fn_input_collation );
415
418
416
419
/* Disallow pseudotype argument */
417
420
/* (note we already replaced polymorphic types) */
@@ -556,7 +559,9 @@ do_compile(FunctionCallInfo fcinfo,
556
559
num_out_args == 0 )
557
560
{
558
561
(void ) plpgsql_build_variable ("$0" , 0 ,
559
- build_datatype (typeTup , -1 ),
562
+ build_datatype (typeTup ,
563
+ -1 ,
564
+ function -> fn_input_collation ),
560
565
true);
561
566
}
562
567
}
@@ -587,61 +592,81 @@ do_compile(FunctionCallInfo fcinfo,
587
592
588
593
/* Add the variable tg_name */
589
594
var = plpgsql_build_variable ("tg_name" , 0 ,
590
- plpgsql_build_datatype (NAMEOID , -1 ),
595
+ plpgsql_build_datatype (NAMEOID ,
596
+ -1 ,
597
+ InvalidOid ),
591
598
true);
592
599
function -> tg_name_varno = var -> dno ;
593
600
594
601
/* Add the variable tg_when */
595
602
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 ),
597
606
true);
598
607
function -> tg_when_varno = var -> dno ;
599
608
600
609
/* Add the variable tg_level */
601
610
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 ),
603
614
true);
604
615
function -> tg_level_varno = var -> dno ;
605
616
606
617
/* Add the variable tg_op */
607
618
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 ),
609
622
true);
610
623
function -> tg_op_varno = var -> dno ;
611
624
612
625
/* Add the variable tg_relid */
613
626
var = plpgsql_build_variable ("tg_relid" , 0 ,
614
- plpgsql_build_datatype (OIDOID , -1 ),
627
+ plpgsql_build_datatype (OIDOID ,
628
+ -1 ,
629
+ InvalidOid ),
615
630
true);
616
631
function -> tg_relid_varno = var -> dno ;
617
632
618
633
/* Add the variable tg_relname */
619
634
var = plpgsql_build_variable ("tg_relname" , 0 ,
620
- plpgsql_build_datatype (NAMEOID , -1 ),
635
+ plpgsql_build_datatype (NAMEOID ,
636
+ -1 ,
637
+ InvalidOid ),
621
638
true);
622
639
function -> tg_relname_varno = var -> dno ;
623
640
624
641
/* tg_table_name is now preferred to tg_relname */
625
642
var = plpgsql_build_variable ("tg_table_name" , 0 ,
626
- plpgsql_build_datatype (NAMEOID , -1 ),
643
+ plpgsql_build_datatype (NAMEOID ,
644
+ -1 ,
645
+ InvalidOid ),
627
646
true);
628
647
function -> tg_table_name_varno = var -> dno ;
629
648
630
649
/* add the variable tg_table_schema */
631
650
var = plpgsql_build_variable ("tg_table_schema" , 0 ,
632
- plpgsql_build_datatype (NAMEOID , -1 ),
651
+ plpgsql_build_datatype (NAMEOID ,
652
+ -1 ,
653
+ InvalidOid ),
633
654
true);
634
655
function -> tg_table_schema_varno = var -> dno ;
635
656
636
657
/* Add the variable tg_nargs */
637
658
var = plpgsql_build_variable ("tg_nargs" , 0 ,
638
- plpgsql_build_datatype (INT4OID , -1 ),
659
+ plpgsql_build_datatype (INT4OID ,
660
+ -1 ,
661
+ InvalidOid ),
639
662
true);
640
663
function -> tg_nargs_varno = var -> dno ;
641
664
642
665
/* Add the variable tg_argv */
643
666
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 ),
645
670
true);
646
671
function -> tg_argv_varno = var -> dno ;
647
672
@@ -659,7 +684,9 @@ do_compile(FunctionCallInfo fcinfo,
659
684
* Create the magic FOUND variable.
660
685
*/
661
686
var = plpgsql_build_variable ("found" , 0 ,
662
- plpgsql_build_datatype (BOOLOID , -1 ),
687
+ plpgsql_build_datatype (BOOLOID ,
688
+ -1 ,
689
+ InvalidOid ),
663
690
true);
664
691
function -> found_varno = var -> dno ;
665
692
@@ -777,6 +804,7 @@ plpgsql_compile_inline(char *proc_source)
777
804
778
805
function -> fn_name = pstrdup (func_name );
779
806
function -> fn_is_trigger = false;
807
+ function -> fn_input_collation = InvalidOid ;
780
808
function -> fn_cxt = func_cxt ;
781
809
function -> out_param_varno = -1 ; /* set up for no OUT param */
782
810
function -> resolve_option = plpgsql_variable_conflict ;
@@ -810,7 +838,9 @@ plpgsql_compile_inline(char *proc_source)
810
838
* Create the magic FOUND variable.
811
839
*/
812
840
var = plpgsql_build_variable ("found" , 0 ,
813
- plpgsql_build_datatype (BOOLOID , -1 ),
841
+ plpgsql_build_datatype (BOOLOID ,
842
+ -1 ,
843
+ InvalidOid ),
814
844
true);
815
845
function -> found_varno = var -> dno ;
816
846
@@ -1218,13 +1248,14 @@ static Node *
1218
1248
make_datum_param (PLpgSQL_expr * expr , int dno , int location )
1219
1249
{
1220
1250
PLpgSQL_execstate * estate ;
1251
+ PLpgSQL_datum * datum ;
1221
1252
Param * param ;
1222
1253
MemoryContext oldcontext ;
1223
1254
1224
1255
/* see comment in resolve_column_ref */
1225
1256
estate = expr -> func -> cur_estate ;
1226
-
1227
1257
Assert (dno >= 0 && dno < estate -> ndatums );
1258
+ datum = estate -> datums [dno ];
1228
1259
1229
1260
/*
1230
1261
* Bitmapset must be allocated in function's permanent memory context
@@ -1236,9 +1267,9 @@ make_datum_param(PLpgSQL_expr *expr, int dno, int location)
1236
1267
param = makeNode (Param );
1237
1268
param -> paramkind = PARAM_EXTERN ;
1238
1269
param -> paramid = dno + 1 ;
1239
- param -> paramtype = exec_get_datum_type (estate , estate -> datums [ dno ] );
1270
+ param -> paramtype = exec_get_datum_type (estate , datum );
1240
1271
param -> paramtypmod = -1 ;
1241
- param -> paramcollid = get_typcollation ( param -> paramtype );
1272
+ param -> paramcollid = exec_get_datum_collation ( estate , datum );
1242
1273
param -> location = location ;
1243
1274
1244
1275
return (Node * ) param ;
@@ -1578,7 +1609,8 @@ plpgsql_parse_wordtype(char *ident)
1578
1609
return NULL ;
1579
1610
}
1580
1611
1581
- dtype = build_datatype (typeTup , -1 );
1612
+ dtype = build_datatype (typeTup , -1 ,
1613
+ plpgsql_curr_compile -> fn_input_collation );
1582
1614
1583
1615
ReleaseSysCache (typeTup );
1584
1616
return dtype ;
@@ -1687,7 +1719,9 @@ plpgsql_parse_cwordtype(List *idents)
1687
1719
* return it
1688
1720
*/
1689
1721
MemoryContextSwitchTo (oldCxt );
1690
- dtype = build_datatype (typetup , attrStruct -> atttypmod );
1722
+ dtype = build_datatype (typetup ,
1723
+ attrStruct -> atttypmod ,
1724
+ attrStruct -> attcollation );
1691
1725
MemoryContextSwitchTo (compile_tmp_cxt );
1692
1726
1693
1727
done :
@@ -1720,7 +1754,7 @@ plpgsql_parse_wordrowtype(char *ident)
1720
1754
errmsg ("relation \"%s\" does not exist" , ident )));
1721
1755
1722
1756
/* Build and return the row type struct */
1723
- return plpgsql_build_datatype (get_rel_type_id (classOid ), -1 );
1757
+ return plpgsql_build_datatype (get_rel_type_id (classOid ), -1 , InvalidOid );
1724
1758
}
1725
1759
1726
1760
/* ----------
@@ -1755,7 +1789,7 @@ plpgsql_parse_cwordrowtype(List *idents)
1755
1789
MemoryContextSwitchTo (oldCxt );
1756
1790
1757
1791
/* Build and return the row type struct */
1758
- return plpgsql_build_datatype (get_rel_type_id (classOid ), -1 );
1792
+ return plpgsql_build_datatype (get_rel_type_id (classOid ), -1 , InvalidOid );
1759
1793
}
1760
1794
1761
1795
/*
@@ -1935,7 +1969,8 @@ build_row_from_class(Oid classOid)
1935
1969
*/
1936
1970
var = plpgsql_build_variable (refname , 0 ,
1937
1971
plpgsql_build_datatype (attrStruct -> atttypid ,
1938
- attrStruct -> atttypmod ),
1972
+ attrStruct -> atttypmod ,
1973
+ attrStruct -> attcollation ),
1939
1974
false);
1940
1975
1941
1976
/* Add the variable to the row */
@@ -2013,10 +2048,13 @@ build_row_from_vars(PLpgSQL_variable **vars, int numvars)
2013
2048
2014
2049
/*
2015
2050
* 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.
2017
2055
*/
2018
2056
PLpgSQL_type *
2019
- plpgsql_build_datatype (Oid typeOid , int32 typmod )
2057
+ plpgsql_build_datatype (Oid typeOid , int32 typmod , Oid collation )
2020
2058
{
2021
2059
HeapTuple typeTup ;
2022
2060
PLpgSQL_type * typ ;
@@ -2025,7 +2063,7 @@ plpgsql_build_datatype(Oid typeOid, int32 typmod)
2025
2063
if (!HeapTupleIsValid (typeTup ))
2026
2064
elog (ERROR , "cache lookup failed for type %u" , typeOid );
2027
2065
2028
- typ = build_datatype (typeTup , typmod );
2066
+ typ = build_datatype (typeTup , typmod , collation );
2029
2067
2030
2068
ReleaseSysCache (typeTup );
2031
2069
@@ -2036,7 +2074,7 @@ plpgsql_build_datatype(Oid typeOid, int32 typmod)
2036
2074
* Utility subroutine to make a PLpgSQL_type struct given a pg_type entry
2037
2075
*/
2038
2076
static PLpgSQL_type *
2039
- build_datatype (HeapTuple typeTup , int32 typmod )
2077
+ build_datatype (HeapTuple typeTup , int32 typmod , Oid collation )
2040
2078
{
2041
2079
Form_pg_type typeStruct = (Form_pg_type ) GETSTRUCT (typeTup );
2042
2080
PLpgSQL_type * typ ;
@@ -2077,6 +2115,9 @@ build_datatype(HeapTuple typeTup, int32 typmod)
2077
2115
typ -> typbyval = typeStruct -> typbyval ;
2078
2116
typ -> typrelid = typeStruct -> typrelid ;
2079
2117
typ -> typioparam = getTypeIOParam (typeTup );
2118
+ typ -> collation = typeStruct -> typcollation ;
2119
+ if (OidIsValid (collation ) && OidIsValid (typ -> collation ))
2120
+ typ -> collation = collation ;
2080
2121
fmgr_info (typeStruct -> typinput , & (typ -> typinput ));
2081
2122
typ -> atttypmod = typmod ;
2082
2123
@@ -2285,6 +2326,9 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
2285
2326
hashkey -> trigrelOid = RelationGetRelid (trigdata -> tg_relation );
2286
2327
}
2287
2328
2329
+ /* get input collation, if known */
2330
+ hashkey -> inputCollation = fcinfo -> flinfo -> fn_collation ;
2331
+
2288
2332
if (procStruct -> pronargs > 0 )
2289
2333
{
2290
2334
/* get the argument types */
0 commit comments