Fix DEFAULT value handling in decompress_chunk

The sql function decompress_chunk did not filled in
default values during its operation.

Fixes #5412
This commit is contained in:
Zoltan Haindrich 2023-03-13 14:04:00 +00:00 committed by Zoltan Haindrich
parent 827684f3e2
commit 790b322b24
5 changed files with 102 additions and 18 deletions

View File

@ -18,6 +18,7 @@ accidentally triggering the load of a previous DB version.**
* #5410 Fix file trailer handling in the COPY fetcher * #5410 Fix file trailer handling in the COPY fetcher
* #5233 Out of on_proc_exit slots on guc license change * #5233 Out of on_proc_exit slots on guc license change
* #5427 Handle user-defined FDW options properly * #5427 Handle user-defined FDW options properly
* #5442 Decompression may have lost DEFAULT values
**Thanks** **Thanks**
* @nikolaps for reporting an issue with the COPY fetcher * @nikolaps for reporting an issue with the COPY fetcher

View File

@ -8,7 +8,7 @@ CREATE OR REPLACE FUNCTION assert_true(
RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$ $BODY$
BEGIN BEGIN
IF !val THEN IF val IS NOT TRUE THEN
RAISE 'Assert failed'; RAISE 'Assert failed';
END IF; END IF;
END END
@ -22,8 +22,8 @@ CREATE OR REPLACE FUNCTION assert_equal(
RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$ $BODY$
BEGIN BEGIN
IF val1 != val2 THEN IF (val1 = val2) IS NOT TRUE THEN
RAISE 'Assert failed'; RAISE 'Assert failed: % = %',val1,val2;
END IF; END IF;
END END
$BODY$; $BODY$;

View File

@ -1530,7 +1530,8 @@ static void populate_per_compressed_columns_from_data(PerCompressedColumn *per_c
bool *compressed_is_nulls); bool *compressed_is_nulls);
static void row_decompressor_decompress_row(RowDecompressor *row_decompressor); static void row_decompressor_decompress_row(RowDecompressor *row_decompressor);
static bool per_compressed_col_get_data(PerCompressedColumn *per_compressed_col, static bool per_compressed_col_get_data(PerCompressedColumn *per_compressed_col,
Datum *decompressed_datums, bool *decompressed_is_nulls); Datum *decompressed_datums, bool *decompressed_is_nulls,
TupleDesc out_desc);
static RowDecompressor static RowDecompressor
build_decompressor(Relation in_rel, Relation out_rel) build_decompressor(Relation in_rel, Relation out_rel)
@ -1740,7 +1741,8 @@ row_decompressor_decompress_row(RowDecompressor *decompressor)
{ {
bool col_is_done = per_compressed_col_get_data(&decompressor->per_compressed_cols[col], bool col_is_done = per_compressed_col_get_data(&decompressor->per_compressed_cols[col],
decompressor->decompressed_datums, decompressor->decompressed_datums,
decompressor->decompressed_is_nulls); decompressor->decompressed_is_nulls,
decompressor->out_desc);
is_done &= col_is_done; is_done &= col_is_done;
} }
@ -1752,6 +1754,7 @@ row_decompressor_decompress_row(RowDecompressor *decompressor)
HeapTuple decompressed_tuple = heap_form_tuple(decompressor->out_desc, HeapTuple decompressed_tuple = heap_form_tuple(decompressor->out_desc,
decompressor->decompressed_datums, decompressor->decompressed_datums,
decompressor->decompressed_is_nulls); decompressor->decompressed_is_nulls);
heap_insert(decompressor->out_rel, heap_insert(decompressor->out_rel,
decompressed_tuple, decompressed_tuple,
decompressor->mycid, decompressor->mycid,
@ -1774,7 +1777,7 @@ row_decompressor_decompress_row(RowDecompressor *decompressor)
*/ */
bool bool
per_compressed_col_get_data(PerCompressedColumn *per_compressed_col, Datum *decompressed_datums, per_compressed_col_get_data(PerCompressedColumn *per_compressed_col, Datum *decompressed_datums,
bool *decompressed_is_nulls) bool *decompressed_is_nulls, TupleDesc out_desc)
{ {
DecompressResult decompressed; DecompressResult decompressed;
int16 decompressed_column_offset = per_compressed_col->decompressed_column_offset; int16 decompressed_column_offset = per_compressed_col->decompressed_column_offset;
@ -1794,7 +1797,11 @@ per_compressed_col_get_data(PerCompressedColumn *per_compressed_col, Datum *deco
/* compressed NULL */ /* compressed NULL */
if (per_compressed_col->is_null) if (per_compressed_col->is_null)
{ {
decompressed_is_nulls[decompressed_column_offset] = true; decompressed_datums[decompressed_column_offset] =
getmissingattr(out_desc,
decompressed_column_offset + 1,
&decompressed_is_nulls[decompressed_column_offset]);
return true; return true;
} }

View File

@ -744,6 +744,33 @@ ALTER TABLE i2844 SET (timescaledb.compress = FALSE);
-- Please see the included NOTICE for copyright information and -- Please see the included NOTICE for copyright information and
-- LICENSE-TIMESCALE for a copy of the license. -- LICENSE-TIMESCALE for a copy of the license.
\set ECHO errors \set ECHO errors
\ir ../../../../test/sql/include/test_utils.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 OR REPLACE FUNCTION assert_true(
val boolean
)
RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
IF val IS NOT TRUE THEN
RAISE 'Assert failed';
END IF;
END
$BODY$;
CREATE OR REPLACE FUNCTION assert_equal(
val1 anyelement,
val2 anyelement
)
RETURNS VOID LANGUAGE PLPGSQL IMMUTABLE AS
$BODY$
BEGIN
IF (val1 = val2) IS NOT TRUE THEN
RAISE 'Assert failed: % = %',val1,val2;
END IF;
END
$BODY$;
CREATE TABLE test1 ("Time" timestamptz, intcol integer, bntcol bigint, txtcol text); CREATE TABLE test1 ("Time" timestamptz, intcol integer, bntcol bigint, txtcol text);
SELECT table_name from create_hypertable('test1', 'Time', chunk_time_interval=> INTERVAL '1 day'); SELECT table_name from create_hypertable('test1', 'Time', chunk_time_interval=> INTERVAL '1 day');
psql:include/compression_alter.sql:8: NOTICE: adding not-null constraint to column "Time" psql:include/compression_alter.sql:8: NOTICE: adding not-null constraint to column "Time"
@ -1053,10 +1080,51 @@ SELECT * FROM test_defaults ORDER BY 1,2;
Mon Jan 01 00:00:00 2001 PST | 1 | | 42 Mon Jan 01 00:00:00 2001 PST | 1 | | 42
(3 rows) (3 rows)
-- timescale/timescaledb#5412
ALTER TABLE test_defaults ADD COLUMN c3 int NOT NULL DEFAULT 43;
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
time | device_id | c1 | c2 | c3 | assert_equal
------------------------------+-----------+----+----+----+--------------
Sat Jan 01 00:00:00 2000 PST | 1 | | 42 | 43 |
Sat Jan 01 00:00:00 2000 PST | 2 | | 42 | 43 |
Mon Jan 01 00:00:00 2001 PST | 1 | | 42 | 43 |
(3 rows)
select decompress_chunk(show_chunks('test_defaults'),true);
psql:include/compression_alter.sql:179: NOTICE: chunk "_hyper_14_90_chunk" is not compressed
decompress_chunk
------------------------------------------
_timescaledb_internal._hyper_14_89_chunk
(2 rows)
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
time | device_id | c1 | c2 | c3 | assert_equal
------------------------------+-----------+----+----+----+--------------
Sat Jan 01 00:00:00 2000 PST | 1 | | 42 | 43 |
Sat Jan 01 00:00:00 2000 PST | 2 | | 42 | 43 |
Mon Jan 01 00:00:00 2001 PST | 1 | | 42 | 43 |
(3 rows)
select compress_chunk(show_chunks('test_defaults'));
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_14_89_chunk
_timescaledb_internal._hyper_14_90_chunk
(2 rows)
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
time | device_id | c1 | c2 | c3 | assert_equal
------------------------------+-----------+----+----+----+--------------
Sat Jan 01 00:00:00 2000 PST | 1 | | 42 | 43 |
Sat Jan 01 00:00:00 2000 PST | 2 | | 42 | 43 |
Mon Jan 01 00:00:00 2001 PST | 1 | | 42 | 43 |
(3 rows)
-- test dropping columns from compressed -- test dropping columns from compressed
CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text);
SELECT create_hypertable('test_drop','time'); SELECT create_hypertable('test_drop','time');
psql:include/compression_alter.sql:178: NOTICE: adding not-null constraint to column "time" psql:include/compression_alter.sql:186: NOTICE: adding not-null constraint to column "time"
create_hypertable create_hypertable
------------------------- -------------------------
(16,public,test_drop,t) (16,public,test_drop,t)
@ -1066,13 +1134,13 @@ ALTER TABLE test_drop SET (timescaledb.compress,timescaledb.compress_segmentby='
-- dropping segmentby or orderby columns will fail -- dropping segmentby or orderby columns will fail
\set ON_ERROR_STOP 0 \set ON_ERROR_STOP 0
ALTER TABLE test_drop DROP COLUMN time; ALTER TABLE test_drop DROP COLUMN time;
psql:include/compression_alter.sql:183: ERROR: cannot drop column named in partition key psql:include/compression_alter.sql:191: ERROR: cannot drop column named in partition key
ALTER TABLE test_drop DROP COLUMN o1; ALTER TABLE test_drop DROP COLUMN o1;
psql:include/compression_alter.sql:184: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled psql:include/compression_alter.sql:192: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled
ALTER TABLE test_drop DROP COLUMN o2; ALTER TABLE test_drop DROP COLUMN o2;
psql:include/compression_alter.sql:185: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled psql:include/compression_alter.sql:193: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled
ALTER TABLE test_drop DROP COLUMN device; ALTER TABLE test_drop DROP COLUMN device;
psql:include/compression_alter.sql:186: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled psql:include/compression_alter.sql:194: ERROR: cannot drop orderby or segmentby column from a hypertable with compression enabled
\set ON_ERROR_STOP 1 \set ON_ERROR_STOP 1
-- switch to WARNING only to suppress compress_chunk NOTICEs -- switch to WARNING only to suppress compress_chunk NOTICEs
SET client_min_messages TO WARNING; SET client_min_messages TO WARNING;
@ -1089,7 +1157,7 @@ ALTER TABLE test_drop DROP COLUMN f2;
-- test non-existant column -- test non-existant column
\set ON_ERROR_STOP 0 \set ON_ERROR_STOP 0
ALTER TABLE test_drop DROP COLUMN f10; ALTER TABLE test_drop DROP COLUMN f10;
psql:include/compression_alter.sql:200: ERROR: column "f10" of relation "test_drop" does not exist psql:include/compression_alter.sql:208: ERROR: column "f10" of relation "test_drop" does not exist
\set ON_ERROR_STOP 1 \set ON_ERROR_STOP 1
ALTER TABLE test_drop DROP COLUMN IF EXISTS f10; ALTER TABLE test_drop DROP COLUMN IF EXISTS f10;
INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2'; INSERT INTO test_drop SELECT NULL,'2001-01-01',2,'o1','o2';
@ -1171,8 +1239,8 @@ WHERE reltablespace in
( SELECT oid from pg_tablespace WHERE spcname = 'tablespace2') ORDER BY 1; ( SELECT oid from pg_tablespace WHERE spcname = 'tablespace2') ORDER BY 1;
relname relname
------------------------------------- -------------------------------------
_hyper_18_103_chunk _hyper_18_105_chunk
_hyper_18_103_chunk_test2_timec_idx _hyper_18_105_chunk_test2_timec_idx
test2 test2
(3 rows) (3 rows)
@ -1183,7 +1251,7 @@ SELECT decompress_chunk(ch) INTO decompressed_chunks FROM show_chunks('test2') c
SELECT compress_chunk(ch) FROM show_chunks('test2') ch; SELECT compress_chunk(ch) FROM show_chunks('test2') ch;
compress_chunk compress_chunk
------------------------------------------- -------------------------------------------
_timescaledb_internal._hyper_18_103_chunk _timescaledb_internal._hyper_18_105_chunk
(1 row) (1 row)
-- the chunk, compressed chunk + index + toast tables are in tablespace2 now . -- the chunk, compressed chunk + index + toast tables are in tablespace2 now .
@ -1199,7 +1267,7 @@ WHERE reltablespace in
(1 row) (1 row)
DROP TABLE test2 CASCADE; DROP TABLE test2 CASCADE;
NOTICE: drop cascades to table _timescaledb_internal.compress_hyper_19_105_chunk NOTICE: drop cascades to table _timescaledb_internal.compress_hyper_19_107_chunk
DROP TABLESPACE tablespace2; DROP TABLESPACE tablespace2;
-- Create a table with a compressed table and then delete the -- Create a table with a compressed table and then delete the
-- compressed table and see that the drop of the hypertable does not -- compressed table and see that the drop of the hypertable does not

View File

@ -3,7 +3,7 @@
-- LICENSE-TIMESCALE for a copy of the license. -- LICENSE-TIMESCALE for a copy of the license.
\ir compression_utils.sql \ir compression_utils.sql
\ir ../../../../test/sql/include/test_utils.sql
CREATE TABLE test1 ("Time" timestamptz, intcol integer, bntcol bigint, txtcol text); CREATE TABLE test1 ("Time" timestamptz, intcol integer, bntcol bigint, txtcol text);
SELECT table_name from create_hypertable('test1', 'Time', chunk_time_interval=> INTERVAL '1 day'); SELECT table_name from create_hypertable('test1', 'Time', chunk_time_interval=> INTERVAL '1 day');
@ -173,6 +173,14 @@ SELECT * FROM test_defaults ORDER BY 1,2;
CALL recompress_all_chunks('test_defaults', 1, false); CALL recompress_all_chunks('test_defaults', 1, false);
SELECT * FROM test_defaults ORDER BY 1,2; SELECT * FROM test_defaults ORDER BY 1,2;
-- timescale/timescaledb#5412
ALTER TABLE test_defaults ADD COLUMN c3 int NOT NULL DEFAULT 43;
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
select decompress_chunk(show_chunks('test_defaults'),true);
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
select compress_chunk(show_chunks('test_defaults'));
SELECT *,assert_equal(c3,43) FROM test_defaults ORDER BY 1,2;
-- test dropping columns from compressed -- test dropping columns from compressed
CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text); CREATE TABLE test_drop(f1 text, f2 text, f3 text, time timestamptz, device int, o1 text, o2 text);
SELECT create_hypertable('test_drop','time'); SELECT create_hypertable('test_drop','time');