I would like to use a script variable to set the data type, so that I can generate a few functions with different types, like so:
\set bucket_data_type DATE
Then run a script to generate this function:
CREATE OR REPLACE FUNCTION insert(
ids BIGINT[],
types TEXT[],
buckets :bucket_data_type[]
) RETURNS VOID
LANGUAGE PLPGSQL
AS $$
BEGIN
EXECUTE
FORMAT('INSERT INTO myTable(id, type, buckets)
SELECT _.id, _.type, _.bucket
FROM(
SELECT unnest(%L::bigint[]) AS monitor_id,
unnest(%L::text[]) AS feature_type,
unnest(%L::'|| :bucket_data_type ||'[]) AS bucket
) _
ON CONFLICT DO NOTHING;',
ids, types, buckets);
END
$$;
and then again with \set bucket_data_type TIMESTAMP, for example.
It works for the parameter definitions, but not the SQL inside the FORMAT block.
I am expecting something like
\set bucket_data_type DATE
<run create script as per above>
to return
CREATE OR REPLACE FUNCTION insert(
ids BIGINT[],
types TEXT[],
buckets DATE[]
) RETURNS VOID
LANGUAGE PLPGSQL
AS $$
BEGIN
EXECUTE
FORMAT('INSERT INTO myTable(id, type, buckets)
SELECT _.id, _.type, _.bucket
FROM(
SELECT unnest(%L::bigint[]) AS monitor_id,
unnest(%L::text[]) AS feature_type,
unnest(%L::DATE[]) AS bucket
) _
ON CONFLICT DO NOTHING;',
ids, types, buckets);
END
$$;
but I'm unable to get unnest(%L::DATE[]) AS bucket to appear.
I either get format errors like:
ERROR: syntax error at or near ":"
LINE 15: unnest(%L::'|| :bucket_data_type ||'[]) AS bu...
or I simply get :bucket_data_type as a string inside the execute block.
I've tried SELECT set_config('tsp.bucket_data_type', :'bucket_data_type', false); as well (as this works in DO BLOCKS where things are string literals).
Is this even possible?
EXECUTEanyway, it seems unnecessaru. Just do a straightINSERT. And if you really do need to useEXECUTEthen pass parameters properly, not usingFORMATwhich leavs you at risk of injection.anyarrayoption? See postgresql.org/docs/current/… However, the real data type is determined by the table and column definition ofmyTable