-- 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_single.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."one_Partition" (
  "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."one_Partition" (device_id, "timeCustom" DESC NULLS LAST) WHERE device_id IS NOT NULL;
CREATE INDEX ON PUBLIC."one_Partition" ("timeCustom" DESC NULLS LAST, series_0) WHERE series_0 IS NOT NULL;
CREATE INDEX ON PUBLIC."one_Partition" ("timeCustom" DESC NULLS LAST, series_1)  WHERE series_1 IS NOT NULL;
CREATE INDEX ON PUBLIC."one_Partition" ("timeCustom" DESC NULLS LAST, series_2) WHERE series_2 IS NOT NULL;
CREATE INDEX ON PUBLIC."one_Partition" ("timeCustom" DESC NULLS LAST, series_bool) WHERE series_bool IS NOT NULL;
\c :DBNAME :ROLE_SUPERUSER
CREATE SCHEMA "one_Partition" AUTHORIZATION :ROLE_DEFAULT_PERM_USER;
\c :DBNAME :ROLE_DEFAULT_PERM_USER;
SELECT * FROM create_hypertable('"public"."one_Partition"', 'timeCustom', associated_schema_name=>'one_Partition', chunk_time_interval=>_timescaledb_functions.interval_to_usec('1 month'));
--output command tags
\set QUIET off
BEGIN;
\COPY "one_Partition" FROM 'data/ds1_dev1_1.tsv' NULL AS '';
COMMIT;
INSERT INTO "one_Partition"("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 "one_Partition"("timeCustom", device_id, series_0, series_1) VALUES
(1257894000000000000, 'dev2', 1.5, 2);
\set QUIET on
\o
-- Make sure UPDATE isn't optimized if it includes Append plans
-- Need to turn of nestloop to make append appear the same on PG96 and PG10
set enable_nestloop = 'off';
CREATE OR REPLACE FUNCTION series_val()
RETURNS integer LANGUAGE PLPGSQL STABLE AS
$BODY$
BEGIN
    RETURN 5;
END;
$BODY$;
-- ConstraintAwareAppend applied for SELECT
EXPLAIN (buffers off, costs off)
SELECT FROM "one_Partition"
WHERE series_1 IN (SELECT series_1 FROM "one_Partition" WHERE series_1 > series_val());
--- QUERY PLAN ---
 Hash Join
   Hash Cond: ("one_Partition".series_1 = "one_Partition_1".series_1)
   ->  Custom Scan (ChunkAppend) on "one_Partition"
         Chunks excluded during startup: 0
         ->  Index Only Scan using "_hyper_1_1_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_1_chunk
               Index Cond: (series_1 > (series_val())::double precision)
         ->  Index Only Scan using "_hyper_1_2_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_2_chunk
               Index Cond: (series_1 > (series_val())::double precision)
         ->  Index Only Scan using "_hyper_1_3_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_3_chunk
               Index Cond: (series_1 > (series_val())::double precision)
   ->  Hash
         ->  HashAggregate
               Group Key: "one_Partition_1".series_1
               ->  Custom Scan (ChunkAppend) on "one_Partition" "one_Partition_1"
                     Chunks excluded during startup: 0
                     ->  Index Only Scan using "_hyper_1_1_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_1_chunk _hyper_1_1_chunk_1
                           Index Cond: (series_1 > (series_val())::double precision)
                     ->  Index Only Scan using "_hyper_1_2_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_2_chunk _hyper_1_2_chunk_1
                           Index Cond: (series_1 > (series_val())::double precision)
                     ->  Index Only Scan using "_hyper_1_3_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_3_chunk _hyper_1_3_chunk_1
                           Index Cond: (series_1 > (series_val())::double precision)

-- ConstraintAwareAppend NOT applied for UPDATE
EXPLAIN (buffers off, costs off)
UPDATE "one_Partition"
SET series_1 = 8
WHERE series_1 IN (SELECT series_1 FROM "one_Partition" WHERE series_1 > series_val());
--- QUERY PLAN ---
 Custom Scan (ModifyHypertable)
   ->  Update on "one_Partition"
         Update on _hyper_1_1_chunk "one_Partition_2"
         Update on _hyper_1_2_chunk "one_Partition_3"
         Update on _hyper_1_3_chunk "one_Partition_4"
         ->  Hash Join
               Hash Cond: ("one_Partition".series_1 = "one_Partition_1".series_1)
               ->  Append
                     ->  Seq Scan on _hyper_1_1_chunk "one_Partition_2"
                     ->  Seq Scan on _hyper_1_2_chunk "one_Partition_3"
                     ->  Seq Scan on _hyper_1_3_chunk "one_Partition_4"
               ->  Hash
                     ->  HashAggregate
                           Group Key: "one_Partition_1".series_1
                           ->  Append
                                 ->  Index Scan using "_hyper_1_1_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_1_chunk "one_Partition_5"
                                       Index Cond: (series_1 > (series_val())::double precision)
                                 ->  Index Scan using "_hyper_1_2_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_2_chunk "one_Partition_6"
                                       Index Cond: (series_1 > (series_val())::double precision)
                                 ->  Index Scan using "_hyper_1_3_chunk_one_Partition_timeCustom_series_1_idx" on _hyper_1_3_chunk "one_Partition_7"
                                       Index Cond: (series_1 > (series_val())::double precision)

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

UPDATE "one_Partition"
SET series_1 = 8
WHERE series_1 IN (SELECT series_1 FROM "one_Partition" WHERE series_1 > series_val());
SELECT * FROM "one_Partition" ORDER BY "timeCustom", device_id, series_0, series_1, series_2;
     timeCustom      | device_id | series_0 | series_1 | series_2 | series_bool 
---------------------+-----------+----------+----------+----------+-------------
 1257894000000000000 | dev1      |      1.5 |        1 |        2 | t
 1257894000000000000 | dev1      |      1.5 |        2 |          | 
 1257894000000000000 | dev2      |      1.5 |        1 |          | 
 1257894000000000000 | dev2      |      1.5 |        2 |          | 
 1257894000000001000 | dev1      |      2.5 |        3 |          | 
 1257894001000000000 | dev1      |      3.5 |        4 |          | 
 1257894002000000000 | dev1      |      2.5 |        3 |          | 
 1257894002000000000 | dev1      |      5.5 |        8 |          | f
 1257894002000000000 | dev1      |      5.5 |        8 |          | t
 1257897600000000000 | dev1      |      4.5 |        5 |          | f
 1257987600000000000 | dev1      |      1.5 |        1 |          | 
 1257987600000000000 | dev1      |      1.5 |        2 |          | 

UPDATE "one_Partition" SET series_1 = 47;
UPDATE "one_Partition" SET series_bool = true;
SELECT * FROM "one_Partition" ORDER BY "timeCustom", device_id, series_0, series_1, series_2;
     timeCustom      | device_id | series_0 | series_1 | series_2 | series_bool 
---------------------+-----------+----------+----------+----------+-------------
 1257894000000000000 | dev1      |      1.5 |       47 |        2 | t
 1257894000000000000 | dev1      |      1.5 |       47 |          | t
 1257894000000000000 | dev2      |      1.5 |       47 |          | t
 1257894000000000000 | dev2      |      1.5 |       47 |          | t
 1257894000000001000 | dev1      |      2.5 |       47 |          | t
 1257894001000000000 | dev1      |      3.5 |       47 |          | t
 1257894002000000000 | dev1      |      2.5 |       47 |          | t
 1257894002000000000 | dev1      |      5.5 |       47 |          | t
 1257894002000000000 | dev1      |      5.5 |       47 |          | t
 1257897600000000000 | dev1      |      4.5 |       47 |          | t
 1257987600000000000 | dev1      |      1.5 |       47 |          | t
 1257987600000000000 | dev1      |      1.5 |       47 |          | t

-- test update on chunks directly
CREATE TABLE direct_update(time timestamptz) WITH (tsdb.hypertable);
NOTICE:  using column "time" as partitioning column
INSERT INTO direct_update VALUES ('2020-01-01');
SELECT show_chunks('direct_update') AS "CHUNK" \gset
--should have ModifyHyperable node
EXPLAIN (costs off, timing off, summary off) UPDATE :CHUNK SET time = time + INTERVAL '1 minute';
--- QUERY PLAN ---
 Custom Scan (ModifyHypertable)
   ->  Update on _hyper_2_4_chunk
         ->  Seq Scan on _hyper_2_4_chunk

EXPLAIN (costs off, timing off, summary off) UPDATE ONLY :CHUNK SET time = time + INTERVAL '1 minute';
--- QUERY PLAN ---
 Custom Scan (ModifyHypertable)
   ->  Update on _hyper_2_4_chunk
         ->  Seq Scan on _hyper_2_4_chunk

-- correct time range should succeed
UPDATE :CHUNK SET time = time + INTERVAL '1 minute' RETURNING *;
             time             
------------------------------
 Wed Jan 01 00:01:00 2020 PST

UPDATE ONLY :CHUNK SET time = time + INTERVAL '1 minute' RETURNING *;
             time             
------------------------------
 Wed Jan 01 00:02:00 2020 PST

-- crossing chunk boundary should fail
\set ON_ERROR_STOP 0
UPDATE :CHUNK SET time = time + INTERVAL '1 month' RETURNING *;
ERROR:  new row for relation "_hyper_2_4_chunk" violates check constraint "constraint_4"
UPDATE ONLY :CHUNK SET time = time + INTERVAL '1 month' RETURNING *;
ERROR:  new row for relation "_hyper_2_4_chunk" violates check constraint "constraint_4"
\set ON_ERROR_STOP 1
