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?
Here is a solution that works with psql
:
\set bucket_data_type date
SELECT '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
$$' \gexec
The SELECT
statement composes the statement that creates the function, and \gexec
executes the statement.