timescaledb/tsl/test/expected/compression_errors.out
Konstantina Skovola f28131cff5 Don't ask for orderby column if default already set
When enabling compression on a hypertable, the orderby option can be
omitted, which will set the default value of "time DESC".
However previously, when executing the same command twice not setting
orderby, the second time we would get an error that orderby was
previously set and must be specified.
For example when executing
`alter table set (timescaledb.compress, timescaledb.segmentby = '..')`

The reason for that error was that it's unclear if no orderby means
leave as is, or if it means set the default value.
But in the case where orderby is already set to the default value,
there is no ambiguity and both cases are equivalent, so the default
value can be reset without giving an error.

Fixes #4331
2022-06-02 11:18:11 +03:00

548 lines
31 KiB
Plaintext

-- This file and its contents are licensed under the Timescale License.
-- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license.
\set ON_ERROR_STOP 0
\set VERBOSITY default
--table with special column names --
create table foo2 (a integer, "bacB toD" integer, c integer, d integer);
select table_name from create_hypertable('foo2', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
------------
foo2
(1 row)
create table foo3 (a integer, "bacB toD" integer, c integer, d integer);
select table_name from create_hypertable('foo3', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
------------
foo3
(1 row)
create table non_compressed (a integer, "bacB toD" integer, c integer, d integer);
select table_name from create_hypertable('non_compressed', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
----------------
non_compressed
(1 row)
insert into non_compressed values( 3 , 16 , 20, 4);
ALTER TABLE foo2 set (timescaledb.compress_segmentby = '"bacB toD",c' , timescaledb.compress_orderby = 'c');
ERROR: the option timescaledb.compress must be set to true to enable compression
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c' , timescaledb.compress_orderby = 'c');
ERROR: cannot use column "c" for both ordering and segmenting
HINT: Use separate columns for the timescaledb.compress_orderby and timescaledb.compress_segmentby options.
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c' , timescaledb.compress_orderby = 'd DESC');
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c' , timescaledb.compress_orderby = 'd');
-- this is acceptable: having previously set the default value for orderby
-- and skipping orderby on a subsequent alter command
create table default_skipped (a integer not null, b integer, c integer, d integer);
select create_hypertable('default_skipped', 'a', chunk_time_interval=> 10);
create_hypertable
------------------------------
(6,public,default_skipped,t)
(1 row)
alter table default_skipped set (timescaledb.compress, timescaledb.compress_segmentby = 'c');
alter table default_skipped set (timescaledb.compress, timescaledb.compress_segmentby = 'c');
create table with_rls (a integer, b integer);
ALTER TABLE with_rls ENABLE ROW LEVEL SECURITY;
select table_name from create_hypertable('with_rls', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
------------
with_rls
(1 row)
ALTER TABLE with_rls set (timescaledb.compress, timescaledb.compress_orderby='a');
ERROR: compression cannot be used on table with row security
--note that the time column "a" should be added to the end of the orderby list
select * from _timescaledb_catalog.hypertable_compression order by attname;
hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst
---------------+----------+--------------------------+------------------------+----------------------+-------------+--------------------
1 | a | 4 | | 2 | f | t
6 | a | 4 | | 1 | f | t
6 | b | 4 | | | |
1 | bacB toD | 0 | 1 | | |
1 | c | 0 | 2 | | |
6 | c | 0 | 1 | | |
1 | d | 4 | | 1 | t | f
6 | d | 4 | | | |
(8 rows)
ALTER TABLE foo3 set (timescaledb.compress, timescaledb.compress_orderby='d DeSc NullS lAsT');
--shold allow alter since segment by was empty
ALTER TABLE foo3 set (timescaledb.compress, timescaledb.compress_orderby='d Asc NullS lAsT');
--this is ok too
ALTER TABLE foo3 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c', timescaledb.compress_orderby = 'd DeSc NullS lAsT');
-- Negative test cases ---
ALTER TABLE foo2 set (timescaledb.compress, timescaledb.compress_segmentby = '"bacB toD",c');
ERROR: must specify a column to order by
DETAIL: The timescaledb.compress_orderby option was previously set and must also be specified in the updated configuration.
alter table default_skipped set (timescaledb.compress, timescaledb.compress_orderby = 'a asc', timescaledb.compress_segmentby = 'c');
alter table default_skipped set (timescaledb.compress, timescaledb.compress_segmentby = 'c');
ERROR: must specify a column to order by
DETAIL: The timescaledb.compress_orderby option was previously set and must also be specified in the updated configuration.
create table reserved_column_prefix (a integer, _ts_meta_foo integer, "bacB toD" integer, c integer, d integer);
select table_name from create_hypertable('reserved_column_prefix', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
------------------------
reserved_column_prefix
(1 row)
ALTER TABLE reserved_column_prefix set (timescaledb.compress);
ERROR: cannot compress tables with reserved column prefix '_ts_meta_'
--basic test with count
create table foo (a integer, b integer, c integer, t text, p point);
ALTER TABLE foo ADD CONSTRAINT chk_existing CHECK(b > 0);
select table_name from create_hypertable('foo', 'a', chunk_time_interval=> 10);
NOTICE: adding not-null constraint to column "a"
DETAIL: Time dimensions cannot have NULL values.
table_name
------------
foo
(1 row)
insert into foo values( 3 , 16 , 20);
insert into foo values( 10 , 10 , 20);
insert into foo values( 20 , 11 , 20);
insert into foo values( 30 , 12 , 20);
-- should error out --
ALTER TABLE foo ALTER b SET NOT NULL, set (timescaledb.compress);
ERROR: ALTER TABLE <hypertable> SET does not support multiple clauses
ALTER TABLE foo ALTER b SET NOT NULL;
select attname, attnotnull from pg_attribute where attrelid = (select oid from pg_class where relname like 'foo') and attname like 'b';
attname | attnotnull
---------+------------
b | t
(1 row)
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'd');
ERROR: column "d" does not exist
HINT: The timescaledb.compress_segmentby option must reference a valid column.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'd');
ERROR: column "d" does not exist
HINT: The timescaledb.compress_orderby option must reference a valid column.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c desc nulls');
ERROR: unable to parse ordering option "c desc nulls"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c desc nulls thirsty');
ERROR: unable to parse ordering option "c desc nulls thirsty"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c climb nulls first');
ERROR: unable to parse ordering option "c climb nulls first"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c nulls first asC');
ERROR: unable to parse ordering option "c nulls first asC"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c desc nulls first asc');
ERROR: unable to parse ordering option "c desc nulls first asc"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c desc hurry');
ERROR: unable to parse ordering option "c desc hurry"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c descend');
ERROR: unable to parse ordering option "c descend"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c; SELECT 1');
ERROR: unable to parse ordering option "c; SELECT 1"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = '1,2');
ERROR: unable to parse ordering option "1,2"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c + 1');
ERROR: unable to parse ordering option "c + 1"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'random()');
ERROR: unable to parse ordering option "random()"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c LIMIT 1');
ERROR: unable to parse ordering option "c LIMIT 1"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'c USING <');
ERROR: unable to parse ordering option "c USING <"
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 't COLLATE "en_US"');
ERROR: unable to parse ordering option "t COLLATE "en_US""
HINT: The timescaledb.compress_orderby option must be a set of column names with sort options, separated by commas. It is the same format as an ORDER BY clause.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'c asc' , timescaledb.compress_orderby = 'c');
ERROR: unable to parse segmenting option "c asc"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'c nulls last');
ERROR: unable to parse segmenting option "c nulls last"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'c + 1');
ERROR: unable to parse segmenting option "c + 1"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'random()');
ERROR: unable to parse segmenting option "random()"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'c LIMIT 1');
ERROR: unable to parse segmenting option "c LIMIT 1"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_segmentby = 'c + b');
ERROR: unable to parse segmenting option "c + b"
HINT: The option timescaledb.compress_segmentby must be a set of columns separated by commas.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, p');
ERROR: invalid ordering column type point
DETAIL: Could not identify a less-than operator for the type.
--should succeed
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a, b');
--ddl on ht with compression
ALTER TABLE foo DROP COLUMN a;
ERROR: cannot drop column named in partition key
DETAIL: Cannot drop column that is a hypertable partitioning (space or time) dimension.
ALTER TABLE foo DROP COLUMN b;
ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled
ALTER TABLE foo ALTER COLUMN t SET NOT NULL;
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo RESET (timescaledb.compress);
ERROR: compression options cannot be reset
ALTER TABLE foo ADD CONSTRAINT chk CHECK(b > 0);
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo ADD CONSTRAINT chk UNIQUE(b);
ERROR: operation not supported on hypertables that have compression enabled
ALTER TABLE foo DROP CONSTRAINT chk_existing;
ERROR: operation not supported on hypertables that have compression enabled
--can add index , but not unique index
CREATE UNIQUE INDEX foo_idx ON foo ( a, c );
ERROR: operation not supported on hypertables that have compression enabled
CREATE INDEX foo_idx ON foo ( a, c );
--note that the time column "a" should not be added to the end of the order by list again (should appear first)
select hc.* from _timescaledb_catalog.hypertable_compression hc inner join _timescaledb_catalog.hypertable h on (h.id = hc.hypertable_id) where h.table_name = 'foo' order by attname;
hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst
---------------+---------+--------------------------+------------------------+----------------------+-------------+--------------------
15 | a | 4 | | 1 | t | f
15 | b | 4 | | 2 | t | f
15 | c | 4 | | | |
15 | p | 1 | | | |
15 | t | 2 | | | |
(5 rows)
select decompress_chunk(ch1.schema_name|| '.' || ch1.table_name)
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'foo' ORDER BY ch1.id limit 1;
ERROR: chunk "_hyper_15_2_chunk" is not compressed
--test changing the segment by columns
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a', timescaledb.compress_segmentby = 'b');
select ch1.schema_name|| '.' || ch1.table_name AS "CHUNK_NAME"
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'foo' ORDER BY ch1.id limit 1 \gset
select decompress_chunk(:'CHUNK_NAME');
ERROR: chunk "_hyper_15_2_chunk" is not compressed
select decompress_chunk(:'CHUNK_NAME', if_compressed=>true);
NOTICE: chunk "_hyper_15_2_chunk" is not compressed
decompress_chunk
------------------
(1 row)
--should succeed
select compress_chunk(:'CHUNK_NAME');
compress_chunk
-----------------------------------------
_timescaledb_internal._hyper_15_2_chunk
(1 row)
select compress_chunk(:'CHUNK_NAME');
ERROR: chunk "_hyper_15_2_chunk" is already compressed
select compress_chunk(:'CHUNK_NAME', if_not_compressed=>true);
NOTICE: chunk "_hyper_15_2_chunk" is already compressed
compress_chunk
-----------------------------------------
_timescaledb_internal._hyper_15_2_chunk
(1 row)
select compress_chunk(ch1.schema_name|| '.' || ch1.table_name)
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'non_compressed' ORDER BY ch1.id limit 1;
ERROR: compression not enabled on "non_compressed"
DETAIL: It is not possible to compress chunks on a hypertable or continuous aggregate that does not have compression enabled.
HINT: Enable compression using ALTER TABLE/MATERIALIZED VIEW with the timescaledb.compress option.
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a', timescaledb.compress_segmentby = 'c');
ERROR: cannot change configuration on already compressed chunks
DETAIL: There are compressed chunks that prevent changing the existing compression configuration.
ALTER TABLE foo set (timescaledb.compress='f');
ERROR: cannot change configuration on already compressed chunks
DETAIL: There are compressed chunks that prevent changing the existing compression configuration.
ALTER TABLE foo reset (timescaledb.compress);
ERROR: compression options cannot be reset
select decompress_chunk(ch1.schema_name|| '.' || ch1.table_name)
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'non_compressed' ORDER BY ch1.id limit 1;
ERROR: missing compressed hypertable
--should succeed
select decompress_chunk(ch1.schema_name|| '.' || ch1.table_name)
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht where ch1.hypertable_id = ht.id and ht.table_name like 'foo' and ch1.compressed_chunk_id IS NOT NULL;
decompress_chunk
-----------------------------------------
_timescaledb_internal._hyper_15_2_chunk
(1 row)
--should succeed
ALTER TABLE foo set (timescaledb.compress, timescaledb.compress_orderby = 'a', timescaledb.compress_segmentby = 'b');
select hc.* from _timescaledb_catalog.hypertable_compression hc inner join _timescaledb_catalog.hypertable h on (h.id = hc.hypertable_id) where h.table_name = 'foo' order by attname;
hypertable_id | attname | compression_algorithm_id | segmentby_column_index | orderby_column_index | orderby_asc | orderby_nullsfirst
---------------+---------+--------------------------+------------------------+----------------------+-------------+--------------------
15 | a | 4 | | 1 | t | f
15 | b | 0 | 1 | | |
15 | c | 4 | | | |
15 | p | 1 | | | |
15 | t | 2 | | | |
(5 rows)
SELECT comp_hyper.schema_name|| '.' || comp_hyper.table_name as "COMPRESSED_HYPER_NAME"
FROM _timescaledb_catalog.hypertable comp_hyper
INNER JOIN _timescaledb_catalog.hypertable uncomp_hyper ON (comp_hyper.id = uncomp_hyper.compressed_hypertable_id)
WHERE uncomp_hyper.table_name like 'foo' ORDER BY comp_hyper.id LIMIT 1 \gset
select add_retention_policy(:'COMPRESSED_HYPER_NAME', INTERVAL '4 months', true);
ERROR: cannot add retention policy to compressed hypertable "_compressed_hypertable_18"
HINT: Please add the policy to the corresponding uncompressed hypertable instead.
--Constraint checking for compression
create table fortable(col integer primary key);
create table table_constr( device_id integer,
timec integer ,
location integer ,
c integer constraint valid_cval check (c > 20) ,
d integer,
primary key ( device_id, timec)
);
select table_name from create_hypertable('table_constr', 'timec', chunk_time_interval=> 10);
table_name
--------------
table_constr
(1 row)
ALTER TABLE table_constr set (timescaledb.compress, timescaledb.compress_segmentby = 'd');
ERROR: column "device_id" must be used for segmenting or ordering
DETAIL: The constraint "table_constr_pkey" cannot be enforced with the given compression configuration.
alter table table_constr add constraint table_constr_uk unique (location, timec, device_id);
ALTER TABLE table_constr set (timescaledb.compress, timescaledb.compress_orderby = 'timec', timescaledb.compress_segmentby = 'device_id');
ERROR: column "location" must be used for segmenting or ordering
DETAIL: The constraint "table_constr_uk" cannot be enforced with the given compression configuration.
alter table table_constr add constraint table_constr_fk FOREIGN KEY(d) REFERENCES fortable(col) on delete cascade;
ALTER TABLE table_constr set (timescaledb.compress, timescaledb.compress_orderby = 'timec', timescaledb.compress_segmentby = 'device_id, location');
ERROR: column "d" must be used for segmenting
DETAIL: The foreign key constraint "table_constr_fk" cannot be enforced with the given compression configuration.
--exclusion constraints not allowed
alter table table_constr add constraint table_constr_exclu exclude using btree (timec with = );
ALTER TABLE table_constr set (timescaledb.compress, timescaledb.compress_orderby = 'timec', timescaledb.compress_segmentby = 'device_id, location, d');
ERROR: constraint table_constr_exclu is not supported for compression
HINT: Exclusion constraints are not supported on hypertables that are compressed.
alter table table_constr drop constraint table_constr_exclu ;
--now it works
ALTER TABLE table_constr set (timescaledb.compress, timescaledb.compress_orderby = 'timec', timescaledb.compress_segmentby = 'device_id, location, d');
--can't add fks after compression enabled
alter table table_constr add constraint table_constr_fk_add_after FOREIGN KEY(d) REFERENCES fortable(col) on delete cascade;
ERROR: operation not supported on hypertables that have compression enabled
-- ddl ADD column variants that are not supported
ALTER TABLE table_constr ADD COLUMN newcol integer CHECK ( newcol < 10 );
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN newcol integer UNIQUE;
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN newcol integer PRIMARY KEY;
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN newcol integer NOT NULL;
ERROR: cannot add column with NOT NULL constraint without default to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN newcol integer DEFAULT random() + random();
ERROR: cannot add column with non-constant default expression to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN IF NOT EXISTS newcol integer REFERENCES fortable(col);
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN IF NOT EXISTS newcol integer GENERATED ALWAYS AS IDENTITY;
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN IF NOT EXISTS newcol integer GENERATED BY DEFAULT AS IDENTITY;
ERROR: cannot add column with constraints to a hypertable that has compression enabled
ALTER TABLE table_constr ADD COLUMN newcol nonexistent_type;
ERROR: type "nonexistent_type" does not exist
LINE 1: ALTER TABLE table_constr ADD COLUMN newcol nonexistent_type;
^
--FK check should not error even with dropped columns (previously had a bug related to this)
CREATE TABLE table_fk (
time timestamptz NOT NULL,
id1 int8 NOT NULL,
id2 int8 NOT NULL,
value float8 NULL,
CONSTRAINT fk1 FOREIGN KEY (id1) REFERENCES fortable(col),
CONSTRAINT fk2 FOREIGN KEY (id2) REFERENCES fortable(col)
);
SELECT create_hypertable('table_fk', 'time');
create_hypertable
------------------------
(21,public,table_fk,t)
(1 row)
ALTER TABLE table_fk DROP COLUMN id1;
ALTER TABLE table_fk SET (timescaledb.compress,timescaledb.compress_segmentby = 'id2');
-- TEST fk cascade delete behavior on compressed chunk --
insert into fortable values(1);
insert into fortable values(10);
--we want 2 chunks here --
insert into table_constr values(1000, 1, 44, 44, 1);
insert into table_constr values(1000, 10, 44, 44, 10);
select ch1.schema_name|| '.' || ch1.table_name AS "CHUNK_NAME"
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht
where ch1.hypertable_id = ht.id and ht.table_name like 'table_constr'
ORDER BY ch1.id limit 1 \gset
-- we have 1 compressed and 1 uncompressed chunk after this.
select compress_chunk(:'CHUNK_NAME');
compress_chunk
-----------------------------------------
_timescaledb_internal._hyper_19_7_chunk
(1 row)
SELECT total_chunks , number_compressed_chunks
FROM hypertable_compression_stats('table_constr');
total_chunks | number_compressed_chunks
--------------+--------------------------
2 | 1
(1 row)
--github issue 1661
--disable compression after enabling it on a table that has fk constraints
CREATE TABLE table_constr2( device_id integer,
timec integer ,
location integer ,
d integer references fortable(col),
primary key ( device_id, timec)
);
SELECT table_name from create_hypertable('table_constr2', 'timec', chunk_time_interval=> 10);
table_name
---------------
table_constr2
(1 row)
INSERT INTO fortable VALUES( 99 );
INSERT INTO table_constr2 VALUES( 1000, 10, 5, 99);
ALTER TABLE table_constr2 SET (timescaledb.compress, timescaledb.compress_segmentby = 'device_id');
ERROR: column "d" must be used for segmenting
DETAIL: The foreign key constraint "table_constr2_d_fkey" cannot be enforced with the given compression configuration.
ALTER TABLE table_constr2 SET (timescaledb.compress, timescaledb.compress_segmentby = 'device_id, d');
--compress a chunk and try to disable compression, it should fail --
SELECT ch1.schema_name|| '.' || ch1.table_name AS "CHUNK_NAME"
FROM _timescaledb_catalog.chunk ch1, _timescaledb_catalog.hypertable ht
WHERE ch1.hypertable_id = ht.id and ht.table_name like 'table_constr2' \gset
SELECT compress_chunk(:'CHUNK_NAME');
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_23_10_chunk
(1 row)
ALTER TABLE table_constr2 set (timescaledb.compress=false);
ERROR: cannot change configuration on already compressed chunks
DETAIL: There are compressed chunks that prevent changing the existing compression configuration.
--decompress all chunks and disable compression.
SELECT decompress_chunk(:'CHUNK_NAME');
decompress_chunk
------------------------------------------
_timescaledb_internal._hyper_23_10_chunk
(1 row)
ALTER TABLE table_constr2 SET (timescaledb.compress=false);
-- TEST compression policy
-- modify the config to trigger errors at runtime
CREATE TABLE test_table_int(time bigint, val int);
SELECT create_hypertable('test_table_int', 'time', chunk_time_interval => 1);
NOTICE: adding not-null constraint to column "time"
DETAIL: Time dimensions cannot have NULL values.
create_hypertable
------------------------------
(25,public,test_table_int,t)
(1 row)
CREATE OR REPLACE function dummy_now() returns BIGINT LANGUAGE SQL IMMUTABLE as 'SELECT 5::BIGINT';
SELECT set_integer_now_func('test_table_int', 'dummy_now');
set_integer_now_func
----------------------
(1 row)
INSERT INTO test_table_int SELECT generate_series(1,5), 10;
ALTER TABLE test_table_int set (timescaledb.compress);
SELECT add_compression_policy('test_table_int', 2::int) AS compressjob_id
\gset
\c :TEST_DBNAME :ROLE_SUPERUSER
UPDATE _timescaledb_config.bgw_job
SET config = config - 'compress_after'
WHERE id = :compressjob_id;
SELECT config FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id;
config
-----------------------
{"hypertable_id": 25}
(1 row)
--should fail
CALL run_job(:compressjob_id);
ERROR: job 1000 config must have compress_after
CONTEXT: PL/pgSQL function _timescaledb_internal.policy_compression(integer,jsonb) line 35 at RAISE
SELECT remove_compression_policy('test_table_int');
remove_compression_policy
---------------------------
t
(1 row)
--again add a new policy that we'll tamper with
SELECT add_compression_policy('test_table_int', 2::int) AS compressjob_id
\gset
UPDATE _timescaledb_config.bgw_job
SET config = config - 'hypertable_id'
WHERE id = :compressjob_id;
SELECT config FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id;
config
-----------------------
{"compress_after": 2}
(1 row)
--should fail
CALL run_job(:compressjob_id);
ERROR: job 1001 config must have hypertable_id
CONTEXT: PL/pgSQL function _timescaledb_internal.policy_compression(integer,jsonb) line 26 at RAISE
UPDATE _timescaledb_config.bgw_job
SET config = NULL
WHERE id = :compressjob_id;
SELECT config FROM _timescaledb_config.bgw_job WHERE id = :compressjob_id;
config
--------
(1 row)
--should fail
CALL run_job(:compressjob_id);
ERROR: job 1001 has null config
CONTEXT: PL/pgSQL function _timescaledb_internal.policy_compression(integer,jsonb) line 21 at RAISE
-- test ADD COLUMN IF NOT EXISTS
CREATE TABLE metric (time TIMESTAMPTZ NOT NULL, val FLOAT8 NOT NULL, dev_id INT4 NOT NULL);
SELECT create_hypertable('metric', 'time', 'dev_id', 10);
create_hypertable
----------------------
(27,public,metric,t)
(1 row)
ALTER TABLE metric SET (
timescaledb.compress,
timescaledb.compress_segmentby = 'dev_id',
timescaledb.compress_orderby = 'time DESC'
);
INSERT INTO metric(time, val, dev_id)
SELECT s.*, 3.14+1, 1
FROM generate_series('2021-08-17 00:00:00'::timestamp,
'2021-08-17 00:02:00'::timestamp, '1 s'::interval) s;
SELECT compress_chunk(show_chunks('metric'));
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_27_17_chunk
(1 row)
-- column does not exist the first time
ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" VARCHAR ;
-- column already exists the second time
ALTER TABLE metric ADD COLUMN IF NOT EXISTS "medium" VARCHAR ;
NOTICE: column "medium" of relation "metric" already exists, skipping
-- also add one without IF NOT EXISTS
ALTER TABLE metric ADD COLUMN "medium_1" VARCHAR ;
ALTER TABLE metric ADD COLUMN "medium_1" VARCHAR ;
ERROR: column "medium_1" of relation "metric" already exists