-- 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
-- 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.
CREATE TABLE PUBLIC."two_Partitions" (
  "timeCustom" BIGINT NOT NULL,
  device_id TEXT NOT NULL,
  series_0 DOUBLE PRECISION NULL,
  series_1 DOUBLE PRECISION NULL,
  series_2 DOUBLE PRECISION NULL,
  series_bool BOOLEAN NULL
);
CREATE INDEX ON PUBLIC."two_Partitions" (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_1)  WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
CREATE INDEX ON PUBLIC."two_Partitions" ("timeCustom" DESC NULLS LAST, device_id);
SELECT * FROM create_hypertable('"public"."two_Partitions"'::regclass, 'timeCustom'::name, 'device_id'::name, associated_schema_name=>'_timescaledb_internal'::text, number_partitions => 2, chunk_time_interval=>_timescaledb_functions.interval_to_usec('1 month'));
\set QUIET off
BEGIN;
\COPY public."two_Partitions" FROM 'data/ds1_dev1_1.tsv' NULL AS '';
COMMIT;
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);
INSERT INTO "two_Partitions"("timeCustom", device_id, series_0, series_1) VALUES
(1257894000000000000, 'dev2', 1.5, 2);
\set QUIET on
\o
SELECT * FROM _timescaledb_catalog.hypertable;
 id | schema_name |   table_name   | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema |  chunk_sizing_func_name  | chunk_target_size | compression_state | compressed_hypertable_id | status 
----+-------------+----------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+-------------------+--------------------------+--------
  1 | public      | two_Partitions | _timescaledb_internal  | _hyper_1                |              2 | _timescaledb_functions   | calculate_chunk_interval |                 0 |                 0 |                          |      0

SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk;
 id | hypertable_id |      schema_name      |    table_name    | compressed_chunk_id | dropped | status | osm_chunk 
----+---------------+-----------------------+------------------+---------------------+---------+--------+-----------
  1 |             1 | _timescaledb_internal | _hyper_1_1_chunk |                     | f       |      0 | f
  2 |             1 | _timescaledb_internal | _hyper_1_2_chunk |                     | f       |      0 | f
  3 |             1 | _timescaledb_internal | _hyper_1_3_chunk |                     | f       |      0 | f
  4 |             1 | _timescaledb_internal | _hyper_1_4_chunk |                     | f       |      0 | f

SELECT * FROM test.show_subtables('"two_Partitions"');
                 Child                  | Tablespace 
----------------------------------------+------------
 _timescaledb_internal._hyper_1_1_chunk | 
 _timescaledb_internal._hyper_1_2_chunk | 
 _timescaledb_internal._hyper_1_3_chunk | 
 _timescaledb_internal._hyper_1_4_chunk | 

SELECT * FROM "two_Partitions";
     timeCustom      | device_id | series_0 | series_1 | series_2 | series_bool 
---------------------+-----------+----------+----------+----------+-------------
 1257894000000000000 | dev1      |      1.5 |        1 |        2 | t
 1257894000000000000 | dev1      |      1.5 |        2 |          | 
 1257894000000001000 | dev1      |      2.5 |        3 |          | 
 1257894001000000000 | dev1      |      3.5 |        4 |          | 
 1257894002000000000 | dev1      |      5.5 |        6 |          | t
 1257894002000000000 | dev1      |      5.5 |        7 |          | f
 1257894002000000000 | dev1      |      2.5 |        3 |          | 
 1257897600000000000 | dev1      |      4.5 |        5 |          | f
 1257987600000000000 | dev1      |      1.5 |        1 |          | 
 1257987600000000000 | dev1      |      1.5 |        2 |          | 
 1257894000000000000 | dev2      |      1.5 |        1 |          | 
 1257894000000000000 | dev2      |      1.5 |        2 |          | 

SET client_min_messages = WARNING;
TRUNCATE "two_Partitions";
SELECT * FROM _timescaledb_catalog.hypertable;
 id | schema_name |   table_name   | associated_schema_name | associated_table_prefix | num_dimensions | chunk_sizing_func_schema |  chunk_sizing_func_name  | chunk_target_size | compression_state | compressed_hypertable_id | status 
----+-------------+----------------+------------------------+-------------------------+----------------+--------------------------+--------------------------+-------------------+-------------------+--------------------------+--------
  1 | public      | two_Partitions | _timescaledb_internal  | _hyper_1                |              2 | _timescaledb_functions   | calculate_chunk_interval |                 0 |                 0 |                          |      0

SELECT id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk;
 id | hypertable_id | schema_name | table_name | compressed_chunk_id | dropped | status | osm_chunk 
----+---------------+-------------+------------+---------------------+---------+--------+-----------

-- should be empty
SELECT * FROM test.show_subtables('"two_Partitions"');
 Child | Tablespace 
-------+------------

SELECT * FROM "two_Partitions";
 timeCustom | device_id | series_0 | series_1 | series_2 | series_bool 
------------+-----------+----------+----------+----------+-------------

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 id, hypertable_id, schema_name, table_name, compressed_chunk_id, dropped, status, osm_chunk FROM _timescaledb_catalog.chunk;
 id | hypertable_id |      schema_name      |    table_name    | compressed_chunk_id | dropped | status | osm_chunk 
----+---------------+-----------------------+------------------+---------------------+---------+--------+-----------
  5 |             1 | _timescaledb_internal | _hyper_1_5_chunk |                     | f       |      0 | f
  6 |             1 | _timescaledb_internal | _hyper_1_6_chunk |                     | f       |      0 | f
  7 |             1 | _timescaledb_internal | _hyper_1_7_chunk |                     | f       |      0 | f

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";
WARNING:  FIRING trigger when: BEFORE level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_before
WARNING:  FIRING trigger when: AFTER level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_after
ERROR:  cannot drop table _timescaledb_internal._hyper_1_5_chunk because other objects depend on it
-- cannot TRUNCATE ONLY a hypertable
TRUNCATE ONLY "two_Partitions" CASCADE;
ERROR:  cannot truncate only a hypertable
\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;
 color 
-------
     1

-- fix for bug #3580
\set ON_ERROR_STOP 0
TRUNCATE nonexistentrelation;
ERROR:  relation "nonexistentrelation" does not exist
\set ON_ERROR_STOP 1
CREATE TABLE truncate_nested (color int);
INSERT INTO truncate_nested VALUES (2);
SELECT * FROM truncate_normal, truncate_nested;
 color | color 
-------+-------
     1 |     2

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;
 color | color 
-------+-------

INSERT INTO truncate_normal VALUES (3);
INSERT INTO truncate_nested VALUES (4);
SELECT * FROM truncate_normal, truncate_nested;
 color | color 
-------+-------
     3 |     4

TRUNCATE truncate_normal;
SELECT * FROM truncate_normal, truncate_nested;
 color | color 
-------+-------

INSERT INTO truncate_normal VALUES (5);
INSERT INTO truncate_nested VALUES (6);
SELECT * FROM truncate_normal, truncate_nested;
 color | color 
-------+-------
     5 |     6

SELECT * FROM test.show_subtables('"two_Partitions"');
                 Child                  | Tablespace 
----------------------------------------+------------
 _timescaledb_internal._hyper_1_5_chunk | 
 _timescaledb_internal._hyper_1_6_chunk | 
 _timescaledb_internal._hyper_1_7_chunk | 

TRUNCATE "two_Partitions", truncate_normal CASCADE;
WARNING:  FIRING trigger when: BEFORE level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_before
WARNING:  FIRING trigger when: AFTER level: STATEMENT op: TRUNCATE cnt: <NULL> trigger_name _test_truncate_after
-- should be empty
SELECT * FROM test.show_subtables('"two_Partitions"');
 Child | Tablespace 
-------+------------

SELECT * FROM "two_Partitions";
 timeCustom | device_id | series_0 | series_1 | series_2 | series_bool 
------------+-----------+----------+----------+----------+-------------

SELECT * FROM truncate_normal, truncate_nested;
 color | color 
-------+-------

-- test TRUNCATE can be performed by a user
-- with TRUNCATE privilege who is not table owner
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE ROLE owner WITH LOGIN;
CREATE ROLE truncator WITH LOGIN;
CREATE DATABASE test_trunc_ht OWNER owner;
\c test_trunc_ht :ROLE_SUPERUSER
SET client_min_messages = ERROR;
CREATE EXTENSION timescaledb;
RESET client_min_messages;
\c test_trunc_ht owner
CREATE TABLE test_hypertable (time TIMESTAMP WITHOUT TIME ZONE NOT NULL, value DOUBLE PRECISION);
SELECT create_hypertable('test_hypertable', 'time');
WARNING:  column type "timestamp without time zone" used for "time" does not follow best practices
      create_hypertable       
------------------------------
 (1,public,test_hypertable,t)

-- fail since we don't have TRUNCATE privileges yet
\set ON_ERROR_STOP 0
\c test_trunc_ht truncator
TRUNCATE TABLE test_hypertable;
ERROR:  permission denied for table test_hypertable
\set ON_ERROR_STOP 1
\c test_trunc_ht owner
GRANT TRUNCATE ON test_hypertable TO truncator;
-- now succeed after privilege was granted
\c test_trunc_ht truncator;
TRUNCATE TABLE test_hypertable;
\c :TEST_DBNAME :ROLE_SUPERUSER
-- set client_min_messages to ERROR to suppress warnings about orphaned files
SET client_min_messages TO ERROR;
DROP DATABASE test_trunc_ht WITH (FORCE);
DROP ROLE owner;
DROP ROLE truncator;
