EXECUTE of SELECT ... INTO is not implemented
Instead of
execute 'select 1 into i' -- error
you should use
execute 'select 1' into i
The error message is the least of the problems in this function. Consider a complete rewrite.
Assuming the column date
is actually data type date
:
CREATE OR REPLACE FUNCTION create_partition_and_insert()
RETURNS trigger AS
$func$
DECLARE
_partition text := quote_ident(TG_RELNAME
|| to_char(NEW.date,'_YYYY_MM_DD"p"'));
BEGIN
IF NOT EXISTS(SELECT relname FROM pg_class WHERE relname = _partition) THEN
EXECUTE format('CREATE TABLE %s (CHECK (date = %L)) INHERITS (%I);'
, _partition, NEW.date, TG_RELNAME);
RAISE NOTICE 'A new partition has been created: %', _partition;
END IF;
EXECUTE format('INSERT INTO %s SELECT ($1).*', _partition)
USING NEW;
RETURN NULL;
END
$func$ LANGUAGE plpgsql;
Major points
You don't need dynamic SQL in your first statement at all (the source or your syntax error). Actually, you don't need the whole statement nor the variable. I radically simplified the name concatenation. Details for
to_char()
in the manual.Ignoring the typographical quotes in
‘p’
- those are probably just c/p artefacts.Assignments are comparatively expensive in plpgsql. Adapt your programming style and reduce variables and assignments.
Don't convert the whole row to its text representation, concatenate and then cast it back. That's needlessly expensive, convoluted and error-prone. Pass the value directly in a
USING
clause toEXECUTE
like demonstrated.Don't raise the notice before it's done.
RAISE
is not rolled back in the case of an exception leading to potentially misleading log entries.If you have more than one schema in your database (which is common), your code is still unsafe. You need to schema-qualify table names or
SET
thesearch_path
for the function.
Related answers with more details:
How to check if a table exists in a given schema
Creating a trigger for child table insertion returns confusing error
INSERT with dynamic table name in trigger function
How does the search_path influence identifier resolution and the "current schema"