Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .unreleased/pr_8153
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixes: #8153 Restoring a database having NULL compressed data
15 changes: 15 additions & 0 deletions test/sql/utils/pg_dump_aux_plain_dump.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
DUMPFILE=${DUMPFILE:-$1}
EXTRA_PGOPTIONS=${EXTRA_PGOPTIONS:-$2}
DUMP_OPTIONS=${DUMP_OPTIONS:-$3}
# Override PGOPTIONS to remove verbose output
PGOPTIONS="--client-min-messages=warning $EXTRA_PGOPTIONS"

export PGOPTIONS
echo ${DUMP_OPTIONS}
echo $DUMP_OPTIONS
echo $(echo $DUMP_OPTIONS)

${PG_BINDIR}/pg_dump -h ${PGHOST} -U ${TEST_ROLE_SUPERUSER} ${DUMP_OPTIONS} -Fp ${TEST_DBNAME} -f ${DUMPFILE}
# ${PG_BINDIR}/pg_dump -h ${PGHOST} -U ${TEST_ROLE_SUPERUSER} ${DUMP_OPTIONS} -Fp ${TEST_DBNAME} > /dev/null 2>&1 -f ${DUMPFILE}
${PG_BINDIR}/dropdb -h ${PGHOST} -U ${TEST_ROLE_SUPERUSER} ${TEST_DBNAME}
${PG_BINDIR}/createdb -h ${PGHOST} -U ${TEST_ROLE_SUPERUSER} ${TEST_DBNAME}
11 changes: 9 additions & 2 deletions tsl/src/compression/algorithms/null.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ null_compressed_send(CompressedDataHeader *header, StringInfo buffer)
extern Datum
null_compressed_recv(StringInfo buffer)
{
elog(ERROR, "null compression doesn't implement recv");
PG_RETURN_VOID();
/* Sanity checks for invalid buffer */
if (buffer->len == 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("compressed data is invalid to be a null compressed block")));
if (buffer->data == NULL)
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("compressed data is NULL")));
PG_RETURN_POINTER(null_compressor_get_dummy_block());
}

extern Compressor *
Expand Down
9 changes: 1 addition & 8 deletions tsl/src/compression/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -2015,14 +2015,7 @@ tsl_compressed_data_recv(PG_FUNCTION_ARGS)
if (header.compression_algorithm >= _END_COMPRESSION_ALGORITHMS)
elog(ERROR, "invalid compression algorithm %d", header.compression_algorithm);

if (header.compression_algorithm == COMPRESSION_ALGORITHM_NULL)
{
PG_RETURN_NULL();
}
else
{
return definitions[header.compression_algorithm].compressed_data_recv(buf);
}
return definitions[header.compression_algorithm].compressed_data_recv(buf);
}

extern Datum
Expand Down
80 changes: 80 additions & 0 deletions tsl/test/expected/compression_null_dump_restore.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
-- 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.
-- This test is to verify fixing the behaviour reported in: SDC #2912
-- Create destination database
\set TEST_DBNAME_3 :TEST_DBNAME _3
\c postgres :ROLE_SUPERUSER
CREATE DATABASE :TEST_DBNAME_3;
\c :TEST_DBNAME_3 :ROLE_SUPERUSER
create extension timescaledb CASCADE;
-- Create source database
\set TEST_DBNAME_2 :TEST_DBNAME _2
\c postgres :ROLE_SUPERUSER
CREATE DATABASE :TEST_DBNAME_2;
\c :TEST_DBNAME_2 :ROLE_SUPERUSER
create extension timescaledb CASCADE;
-- Create compressed table with one column having all NULL
-- values, so it will be compressed with the NULL algorithm
--
create table null_dump (ts int primary key, n int);
select create_hypertable('null_dump', 'ts');
create_hypertable
------------------------
(1,public,null_dump,t)
(1 row)

insert into null_dump values (1), (2), (3), (4);
alter table null_dump set (timescaledb.compress, timescaledb.compress_orderby = 'ts');
select compress_chunk(show_chunks('null_dump'));
compress_chunk
----------------------------------------
_timescaledb_internal._hyper_1_1_chunk
(1 row)

-- Dump the content of the source database
\setenv TEST_DBNAME :TEST_DBNAME_2
\setenv DUMP_OPTIONS '--quote-all-identifiers --no-tablespaces --no-owner --no-privileges --exclude-schema=test'
\c postgres :ROLE_SUPERUSER
\! utils/pg_dump_aux_plain_dump.sh dump/null-compress-dump.sql
--quote-all-identifiers --no-tablespaces --no-owner --no-privileges --exclude-schema=test
--quote-all-identifiers --no-tablespaces --no-owner --no-privileges --exclude-schema=test
--quote-all-identifiers --no-tablespaces --no-owner --no-privileges --exclude-schema=test
pg_dump: warning: there are circular foreign-key constraints on this table:
pg_dump: detail: hypertable
pg_dump: hint: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.
pg_dump: hint: Consider using a full dump instead of a --data-only dump to avoid this problem.
pg_dump: warning: there are circular foreign-key constraints on this table:
pg_dump: detail: chunk
pg_dump: hint: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.
pg_dump: hint: Consider using a full dump instead of a --data-only dump to avoid this problem.
pg_dump: warning: there are circular foreign-key constraints on this table:
pg_dump: detail: continuous_agg
pg_dump: hint: You might not be able to restore the dump without using --disable-triggers or temporarily dropping the constraints.
pg_dump: hint: Consider using a full dump instead of a --data-only dump to avoid this problem.
-- Restore the data into the destination database
\c :TEST_DBNAME_3 :ROLE_SUPERUSER
select public.timescaledb_pre_restore();
timescaledb_pre_restore
-------------------------
t
(1 row)

\set ECHO none
select public.timescaledb_post_restore();
timescaledb_post_restore
--------------------------
t
(1 row)

select * from public.null_dump order by 1;
ts | n
----+---
1 |
2 |
3 |
4 |
(4 rows)

drop database db_compression_null_dump_restore_2;
drop database db_compression_null_dump_restore_3;
1 change: 1 addition & 0 deletions tsl/test/sql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(TEST_FILES
compression_fks.sql
compression_indexcreate.sql
compression_insert.sql
compression_null_dump_restore.sql
compression_nulls_and_defaults.sql
compression_policy.sql
compression_qualpushdown.sql
Expand Down
51 changes: 51 additions & 0 deletions tsl/test/sql/compression_null_dump_restore.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-- 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.

-- This test is to verify fixing the behaviour reported in: SDC #2912

-- Create destination database
\set TEST_DBNAME_3 :TEST_DBNAME _3
\c postgres :ROLE_SUPERUSER
CREATE DATABASE :TEST_DBNAME_3;
\c :TEST_DBNAME_3 :ROLE_SUPERUSER
create extension timescaledb CASCADE;

-- Create source database
\set TEST_DBNAME_2 :TEST_DBNAME _2
\c postgres :ROLE_SUPERUSER
CREATE DATABASE :TEST_DBNAME_2;
\c :TEST_DBNAME_2 :ROLE_SUPERUSER
create extension timescaledb CASCADE;

-- Create compressed table with one column having all NULL
-- values, so it will be compressed with the NULL algorithm
--
create table null_dump (ts int primary key, n int);
select create_hypertable('null_dump', 'ts');
insert into null_dump values (1), (2), (3), (4);
alter table null_dump set (timescaledb.compress, timescaledb.compress_orderby = 'ts');
select compress_chunk(show_chunks('null_dump'));

-- Dump the content of the source database
\setenv TEST_DBNAME :TEST_DBNAME_2
\setenv DUMP_OPTIONS '--quote-all-identifiers --no-tablespaces --no-owner --no-privileges --exclude-schema=test'
\c postgres :ROLE_SUPERUSER
\! utils/pg_dump_aux_plain_dump.sh dump/null-compress-dump.sql

-- Restore the data into the destination database
\c :TEST_DBNAME_3 :ROLE_SUPERUSER
select public.timescaledb_pre_restore();
\set ECHO none
\o /dev/null
SET client_min_messages = 'error';
\i dump/null-compress-dump.sql
\o
\set ECHO queries
select public.timescaledb_post_restore();

select * from public.null_dump order by 1;

\c postgres :ROLE_SUPERUSER
drop database :TEST_DBNAME_2;
drop database :TEST_DBNAME_3;
10 changes: 2 additions & 8 deletions tsl/test/src/compression_unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,14 +999,8 @@ test_null()
TestAssertTrue(transmission.len > 0);
TestAssertTrue(transmission.data != NULL);

LOCAL_FCINFO(local_fcinfo, 1);
local_fcinfo->args[0] =
(NullableDatum){ .value = PointerGetDatum(&transmission), .isnull = false };

// Call the function directly
tsl_compressed_data_recv(local_fcinfo);

TestAssertTrue(local_fcinfo->isnull);
Datum res = DirectFunctionCall1(tsl_compressed_data_recv, PointerGetDatum(&transmission));
TestAssertTrue(DatumGetPointer(res) != NULL);
}
{
void *compressed = null_compressor_get_dummy_block();
Expand Down
Loading