On 2023-Nov-07, jian he wrote:
> ----2.this will have errors.
> CREATE or replace PROCEDURE template_create() LANGUAGE SQL AS $proc$
> DROP TABLE if exists test cascade;
> CREATE TABLE test(id int4range,valid_at tsrange,name text);
> INSERT INTO test VALUES (NULL, tsrange('2018-01-01',
> '2019-01-01'), 'null key');
> $proc$;
This is because of check_function_bodies. You can get this procedure
created if you set it to 0.
However, it still won't run:
55493 16.0 1480547=# call template_create();
ERROR: relation "test" does not exist
LÍNEA 4: INSERT INTO test VALUES (NULL, tsrange('2018-01-01',
^
CONSULTA:
DROP TABLE if exists test cascade;
CREATE TABLE test(id int4range,valid_at tsrange,name text);
INSERT INTO test VALUES (NULL, tsrange('2018-01-01',
'2019-01-01'), 'null key');
CONTEXTO: SQL function "template_create" during startup
Duración: 0,278 ms
The problem seems to be that the procedure uses a single catalog
snapshot during execution, so the INSERT doesn't see the table that
CREATE has made. If you create the table beforehand, then DROP and
CREATE will both work, but the INSERT will fail claiming that the table
that existed before the DROP no longer exists:
55493 16.0 1480547=# CREATE TABLE test(id int4range,valid_at tsrange,name text);
CREATE TABLE
Duración: 1,251 ms
55493 16.0 1480547=# select 'test'::regclass::oid;
oid
────────
210427
(1 fila)
Duración: 0,461 ms
55493 16.0 1480547=# call template_create();
ERROR: relation with OID 210427 does not exist
CONTEXTO: SQL function "template_create" statement 3
Duración: 2,207 ms
Note we no longer get the "LINE 4" context item, but we do get
"statement 3", so we know it's still the insert.
(Of course, the table returns to life because the DROP is part of the
transaction that gets aborted by the failure).
--
Álvaro Herrera Breisgau, Deutschland — https://www.EnterpriseDB.com/