timescaledb/test/sql/truncate.sql
Fabrízio de Royes Mello 74ca546565 Fix memory context bug executing TRUNCATE
Inside the `process_truncate` function is created a new relations list
removing the distributed hypertables and this new list is assigned to
the current statement relation list. This new list is allocated into
the `PortalContext` that is destroyed at the end of the statement
execution.

The problem arise on the subsequent `TRUNCATE` call because the
compiled plpgsql code is cached into another memory context and the
elements of the relations inside this cache is pointing to an invalid
memory area because the `PortalContext` is destroyed.

Fixed it by allocating the new relations list to the same memory
context of the original list.

Fixes #3580, fixes #3622, fixes #3182
2021-10-06 16:13:21 -03:00

113 lines
3.2 KiB
PL/PgSQL

-- This file and its contents are licensed under the Apache License 2.0.
-- Please see the included NOTICE for copyright information and
-- LICENSE-APACHE for a copy of the license.
\o /dev/null
\ir include/insert_two_partitions.sql
\o
SELECT * FROM _timescaledb_catalog.hypertable;
SELECT * FROM _timescaledb_catalog.chunk;
SELECT * FROM test.show_subtables('"two_Partitions"');
SELECT * FROM "two_Partitions";
SET client_min_messages = WARNING;
TRUNCATE "two_Partitions";
SELECT * FROM _timescaledb_catalog.hypertable;
SELECT * FROM _timescaledb_catalog.chunk;
-- should be empty
SELECT * FROM test.show_subtables('"two_Partitions"');
SELECT * FROM "two_Partitions";
INSERT INTO public."two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES
(1257987600000000000, 'dev1', 1.5, 1),
(1257987600000000000, 'dev1', 1.5, 2),
(1257894000000000000, 'dev2', 1.5, 1),
(1257894002000000000, 'dev1', 2.5, 3);
SELECT * FROM _timescaledb_catalog.chunk;
CREATE VIEW dependent_view AS SELECT * FROM _timescaledb_internal._hyper_1_5_chunk;
CREATE OR REPLACE FUNCTION test_trigger()
RETURNS TRIGGER LANGUAGE PLPGSQL AS
$BODY$
DECLARE
cnt INTEGER;
BEGIN
RAISE WARNING 'FIRING trigger when: % level: % op: % cnt: % trigger_name %',
tg_when, tg_level, tg_op, cnt, tg_name;
IF TG_OP = 'DELETE' THEN
RETURN OLD;
END IF;
RETURN NEW;
END
$BODY$;
-- test truncate on a chunk
CREATE TRIGGER _test_truncate_before
BEFORE TRUNCATE ON _timescaledb_internal._hyper_1_5_chunk
FOR EACH STATEMENT EXECUTE FUNCTION test_trigger();
CREATE TRIGGER _test_truncate_after
AFTER TRUNCATE ON _timescaledb_internal._hyper_1_5_chunk
FOR EACH STATEMENT EXECUTE FUNCTION test_trigger();
\set ON_ERROR_STOP 0
TRUNCATE "two_Partitions";
-- cannot TRUNCATE ONLY a hypertable
TRUNCATE ONLY "two_Partitions" CASCADE;
\set ON_ERROR_STOP 1
-- create a regular table to make sure we can truncate it in the same call
CREATE TABLE truncate_normal (color int);
INSERT INTO truncate_normal VALUES (1);
SELECT * FROM truncate_normal;
-- fix for bug #3580
\set ON_ERROR_STOP 0
TRUNCATE nonexistentrelation;
\set ON_ERROR_STOP 1
CREATE TABLE truncate_nested (color int);
INSERT INTO truncate_nested VALUES (2);
SELECT * FROM truncate_normal, truncate_nested;
CREATE FUNCTION fn_truncate_nested()
RETURNS trigger LANGUAGE plpgsql
AS $$
BEGIN
TRUNCATE truncate_nested;
RETURN NEW;
END;
$$;
CREATE TRIGGER tg_truncate_nested
BEFORE TRUNCATE ON truncate_normal
FOR EACH STATEMENT EXECUTE FUNCTION fn_truncate_nested();
TRUNCATE truncate_normal;
SELECT * FROM truncate_normal, truncate_nested;
INSERT INTO truncate_normal VALUES (3);
INSERT INTO truncate_nested VALUES (4);
SELECT * FROM truncate_normal, truncate_nested;
TRUNCATE truncate_normal;
SELECT * FROM truncate_normal, truncate_nested;
INSERT INTO truncate_normal VALUES (5);
INSERT INTO truncate_nested VALUES (6);
SELECT * FROM truncate_normal, truncate_nested;
SELECT * FROM test.show_subtables('"two_Partitions"');
TRUNCATE "two_Partitions", truncate_normal CASCADE;
-- should be empty
SELECT * FROM test.show_subtables('"two_Partitions"');
SELECT * FROM "two_Partitions";
SELECT * FROM truncate_normal, truncate_nested;