@@ -104,7 +104,7 @@ static Node *resolve_column_ref(ParseState *pstate, PLpgSQL_expr *expr,
104104static Node * make_datum_param (PLpgSQL_expr * expr ,int dno ,int location );
105105static PLpgSQL_row * build_row_from_class (Oid classOid );
106106static 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 );
108108static void compute_function_hashkey (FunctionCallInfo fcinfo ,
109109Form_pg_proc procStruct ,
110110PLpgSQL_func_hashkey * hashkey ,
@@ -348,6 +348,7 @@ do_compile(FunctionCallInfo fcinfo,
348348function -> fn_xmin = HeapTupleHeaderGetXmin (procTup -> t_data );
349349function -> fn_tid = procTup -> t_self ;
350350function -> fn_is_trigger = is_trigger ;
351+ function -> fn_input_collation = fcinfo -> flinfo -> fn_collation ;
351352function -> fn_cxt = func_cxt ;
352353function -> out_param_varno = -1 ;/* set up for no OUT param */
353354function -> resolve_option = plpgsql_variable_conflict ;
@@ -411,7 +412,9 @@ do_compile(FunctionCallInfo fcinfo,
411412snprintf (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,
556559num_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 */
589594var = plpgsql_build_variable ("tg_name" ,0 ,
590- plpgsql_build_datatype (NAMEOID ,-1 ),
595+ plpgsql_build_datatype (NAMEOID ,
596+ -1 ,
597+ InvalidOid ),
591598 true);
592599function -> tg_name_varno = var -> dno ;
593600
594601/* Add the variable tg_when */
595602var = 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);
598607function -> tg_when_varno = var -> dno ;
599608
600609/* Add the variable tg_level */
601610var = 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);
604615function -> tg_level_varno = var -> dno ;
605616
606617/* Add the variable tg_op */
607618var = 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);
610623function -> tg_op_varno = var -> dno ;
611624
612625/* Add the variable tg_relid */
613626var = plpgsql_build_variable ("tg_relid" ,0 ,
614- plpgsql_build_datatype (OIDOID ,-1 ),
627+ plpgsql_build_datatype (OIDOID ,
628+ -1 ,
629+ InvalidOid ),
615630 true);
616631function -> tg_relid_varno = var -> dno ;
617632
618633/* Add the variable tg_relname */
619634var = plpgsql_build_variable ("tg_relname" ,0 ,
620- plpgsql_build_datatype (NAMEOID ,-1 ),
635+ plpgsql_build_datatype (NAMEOID ,
636+ -1 ,
637+ InvalidOid ),
621638 true);
622639function -> tg_relname_varno = var -> dno ;
623640
624641/* tg_table_name is now preferred to tg_relname */
625642var = plpgsql_build_variable ("tg_table_name" ,0 ,
626- plpgsql_build_datatype (NAMEOID ,-1 ),
643+ plpgsql_build_datatype (NAMEOID ,
644+ -1 ,
645+ InvalidOid ),
627646 true);
628647function -> tg_table_name_varno = var -> dno ;
629648
630649/* add the variable tg_table_schema */
631650var = plpgsql_build_variable ("tg_table_schema" ,0 ,
632- plpgsql_build_datatype (NAMEOID ,-1 ),
651+ plpgsql_build_datatype (NAMEOID ,
652+ -1 ,
653+ InvalidOid ),
633654 true);
634655function -> tg_table_schema_varno = var -> dno ;
635656
636657/* Add the variable tg_nargs */
637658var = plpgsql_build_variable ("tg_nargs" ,0 ,
638- plpgsql_build_datatype (INT4OID ,-1 ),
659+ plpgsql_build_datatype (INT4OID ,
660+ -1 ,
661+ InvalidOid ),
639662 true);
640663function -> tg_nargs_varno = var -> dno ;
641664
642665/* Add the variable tg_argv */
643666var = 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);
646671function -> tg_argv_varno = var -> dno ;
647672
@@ -659,7 +684,9 @@ do_compile(FunctionCallInfo fcinfo,
659684 * Create the magic FOUND variable.
660685 */
661686var = plpgsql_build_variable ("found" ,0 ,
662- plpgsql_build_datatype (BOOLOID ,-1 ),
687+ plpgsql_build_datatype (BOOLOID ,
688+ -1 ,
689+ InvalidOid ),
663690 true);
664691function -> found_varno = var -> dno ;
665692
@@ -777,6 +804,7 @@ plpgsql_compile_inline(char *proc_source)
777804
778805function -> fn_name = pstrdup (func_name );
779806function -> fn_is_trigger = false;
807+ function -> fn_input_collation = InvalidOid ;
780808function -> fn_cxt = func_cxt ;
781809function -> out_param_varno = -1 ;/* set up for no OUT param */
782810function -> resolve_option = plpgsql_variable_conflict ;
@@ -810,7 +838,9 @@ plpgsql_compile_inline(char *proc_source)
810838 * Create the magic FOUND variable.
811839 */
812840var = plpgsql_build_variable ("found" ,0 ,
813- plpgsql_build_datatype (BOOLOID ,-1 ),
841+ plpgsql_build_datatype (BOOLOID ,
842+ -1 ,
843+ InvalidOid ),
814844 true);
815845function -> found_varno = var -> dno ;
816846
@@ -1218,13 +1248,14 @@ static Node *
12181248make_datum_param (PLpgSQL_expr * expr ,int dno ,int location )
12191249{
12201250PLpgSQL_execstate * estate ;
1251+ PLpgSQL_datum * datum ;
12211252Param * param ;
12221253MemoryContext oldcontext ;
12231254
12241255/* see comment in resolve_column_ref */
12251256estate = expr -> func -> cur_estate ;
1226-
12271257Assert (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)
12361267param = makeNode (Param );
12371268param -> paramkind = PARAM_EXTERN ;
12381269param -> paramid = dno + 1 ;
1239- param -> paramtype = exec_get_datum_type (estate ,estate -> datums [ dno ] );
1270+ param -> paramtype = exec_get_datum_type (estate ,datum );
12401271param -> paramtypmod = -1 ;
1241- param -> paramcollid = get_typcollation ( param -> paramtype );
1272+ param -> paramcollid = exec_get_datum_collation ( estate , datum );
12421273param -> location = location ;
12431274
12441275return (Node * )param ;
@@ -1578,7 +1609,8 @@ plpgsql_parse_wordtype(char *ident)
15781609return NULL ;
15791610}
15801611
1581- dtype = build_datatype (typeTup ,-1 );
1612+ dtype = build_datatype (typeTup ,-1 ,
1613+ plpgsql_curr_compile -> fn_input_collation );
15821614
15831615ReleaseSysCache (typeTup );
15841616return dtype ;
@@ -1687,7 +1719,9 @@ plpgsql_parse_cwordtype(List *idents)
16871719 * return it
16881720 */
16891721MemoryContextSwitchTo (oldCxt );
1690- dtype = build_datatype (typetup ,attrStruct -> atttypmod );
1722+ dtype = build_datatype (typetup ,
1723+ attrStruct -> atttypmod ,
1724+ attrStruct -> attcollation );
16911725MemoryContextSwitchTo (compile_tmp_cxt );
16921726
16931727done :
@@ -1720,7 +1754,7 @@ plpgsql_parse_wordrowtype(char *ident)
17201754errmsg ("relation \"%s\" does not exist" ,ident )));
17211755
17221756/* 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 );
17241758}
17251759
17261760/* ----------
@@ -1755,7 +1789,7 @@ plpgsql_parse_cwordrowtype(List *idents)
17551789MemoryContextSwitchTo (oldCxt );
17561790
17571791/* 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 );
17591793}
17601794
17611795/*
@@ -1935,7 +1969,8 @@ build_row_from_class(Oid classOid)
19351969 */
19361970var = plpgsql_build_variable (refname ,0 ,
19371971plpgsql_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 */
20182056PLpgSQL_type *
2019- plpgsql_build_datatype (Oid typeOid ,int32 typmod )
2057+ plpgsql_build_datatype (Oid typeOid ,int32 typmod , Oid collation )
20202058{
20212059HeapTuple typeTup ;
20222060PLpgSQL_type * typ ;
@@ -2025,7 +2063,7 @@ plpgsql_build_datatype(Oid typeOid, int32 typmod)
20252063if (!HeapTupleIsValid (typeTup ))
20262064elog (ERROR ,"cache lookup failed for type %u" ,typeOid );
20272065
2028- typ = build_datatype (typeTup ,typmod );
2066+ typ = build_datatype (typeTup ,typmod , collation );
20292067
20302068ReleaseSysCache (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 */
20382076static PLpgSQL_type *
2039- build_datatype (HeapTuple typeTup ,int32 typmod )
2077+ build_datatype (HeapTuple typeTup ,int32 typmod , Oid collation )
20402078{
20412079Form_pg_type typeStruct = (Form_pg_type )GETSTRUCT (typeTup );
20422080PLpgSQL_type * typ ;
@@ -2077,6 +2115,9 @@ build_datatype(HeapTuple typeTup, int32 typmod)
20772115typ -> typbyval = typeStruct -> typbyval ;
20782116typ -> typrelid = typeStruct -> typrelid ;
20792117typ -> typioparam = getTypeIOParam (typeTup );
2118+ typ -> collation = typeStruct -> typcollation ;
2119+ if (OidIsValid (collation )&& OidIsValid (typ -> collation ))
2120+ typ -> collation = collation ;
20802121fmgr_info (typeStruct -> typinput ,& (typ -> typinput ));
20812122typ -> atttypmod = typmod ;
20822123
@@ -2285,6 +2326,9 @@ compute_function_hashkey(FunctionCallInfo fcinfo,
22852326hashkey -> trigrelOid = RelationGetRelid (trigdata -> tg_relation );
22862327}
22872328
2329+ /* get input collation, if known */
2330+ hashkey -> inputCollation = fcinfo -> flinfo -> fn_collation ;
2331+
22882332if (procStruct -> pronargs > 0 )
22892333{
22902334/* get the argument types */