PostgreSQL Functions – How to Pass Collation to UDF

functionspostgresql

How can we pass the collation to a user-defined function?

e.g. I can use a hardcoded collation (e.g. "de-AT-x-icu") like this:

CREATE OR REPLACE FUNCTION test(agg_1 jsonb, agg_2 jsonb) RETURNS jsonb
    LANGUAGE SQL
AS
$$
SELECT  jsonb_build_object(
  'count', (agg_1 -> 'count')::int8 + (agg_2 -> 'count')::int8
, 'max', greatest(agg_1 ->> 'max' collate "de-AT-x-icu", agg_2 ->> 'max' collate "de-AT-x-icu")
)
$$;

and the test works:

select test(
  jsonb_build_object('count', 2 , 'max', 'H'),
  jsonb_build_object('count', 0, 'max', 'i')
);

We tried to use a text-argument,

CREATE OR REPLACE FUNCTION test2(agg_1 jsonb, agg_2 jsonb, text_collation text) RETURNS jsonb
    LANGUAGE SQL
AS
$$
SELECT  jsonb_build_object(
                'count', (agg_1 -> 'count')::int8 + (agg_2 -> 'count')::int8
            , 'max', greatest(agg_1 ->> 'max' collate text_collation, agg_2 ->> 'max' collate text_collation)
            )
$$;

but this fails with:

ERROR: collation "text_collation" for encoding "UTF8" does not exist

What is the best way to pass/use a collation in a UDF in such a case?

Best Answer

Collations are database objects, so their name is an identifier.

You cannot use a parameter for an identifier, you'd have to use dynamic SQL in a PL/pgSQL function:

RETURN QUERY EXECUTE
   format(
      'SELECT ... COLLATE %I ...'
      text_collation
   );