mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-15 18:13:18 +08:00
Set null vector for insert into compressed table
As part of inserting into a compressed table, the tuple is materialized, which computes the data size for the tuple using `heap_compute_data_size`. When computing the data size of the tuple, columns that are null are not considered and are just ignored. Columns that are dropped are, however, not explicitly checked and instead the `heap_compute_data_size` rely on these columns being set to null. When reading tuples from a compressed table for insert, the null vector is cleared, meaning that it by default is non-null. Since columns that are dropped are not explicitly processed, they are expected to have a defined value, which they do not have, causing a crash when an attempt to dereference them are made. This commit fixes this by setting the null vector to all null, and the code after will overwrite the columns with proper null bits, except the dropped columns that will be considered null. Fixes #4251
This commit is contained in:
parent
e3f0fbfeff
commit
aaffc1d5a6
@ -1594,16 +1594,25 @@ compress_singlerow(CompressSingleRowState *cr, TupleTableSlot *in_slot)
|
||||
|
||||
ExecClearTuple(out_slot);
|
||||
|
||||
/* ExecClearTuple above will leave dropped columns as non-null, which will
|
||||
* cause a segmentation fault in `heap_compute_data_size` since that
|
||||
* function expects dropped columns to have the null bit set. Since the
|
||||
* null bits are set below for all columns except */
|
||||
memset(out_slot->tts_isnull,
|
||||
true,
|
||||
sizeof(*out_slot->tts_isnull) * out_slot->tts_tupleDescriptor->natts);
|
||||
|
||||
invalues = in_slot->tts_values;
|
||||
out_values = out_slot->tts_values;
|
||||
out_isnull = out_slot->tts_isnull;
|
||||
|
||||
/* Possible optimization:
|
||||
* Can we do a pass through compression without a full copy?
|
||||
* full copy needed for multiple values. But we are dealing only with a single value,
|
||||
* so just need the result of transformation after passing it through the compressor function
|
||||
* This probably needs a bit of rewrte of the compression algorithm code
|
||||
/* Possible optimization: Can we do a pass through compression without a
|
||||
* full copy? full copy needed for multiple values. But we are dealing
|
||||
* only with a single value, so just need the result of transformation
|
||||
* after passing it through the compressor function This probably needs a
|
||||
* bit of rewrite of the compression algorithm code
|
||||
*/
|
||||
Assert(row_compressor->n_input_columns == in_slot->tts_tupleDescriptor->natts);
|
||||
for (int col = 0; col < row_compressor->n_input_columns; col++)
|
||||
{
|
||||
PerColumn *column = &row_compressor->per_column[col];
|
||||
|
@ -938,3 +938,38 @@ FROM
|
||||
INSERT INTO :TABLENAME SELECT;
|
||||
ERROR: direct insert into internal compressed hypertable is not supported
|
||||
\set ON_ERROR_STOP 1
|
||||
-- Test that inserting into a compressed table works even when the
|
||||
-- column has been dropped.
|
||||
CREATE TABLE test4 (
|
||||
timestamp timestamp without time zone not null,
|
||||
ident text not null,
|
||||
one double precision,
|
||||
two double precision
|
||||
);
|
||||
SELECT * FROM create_hypertable('test4', 'timestamp');
|
||||
hypertable_id | schema_name | table_name | created
|
||||
---------------+-------------+------------+---------
|
||||
20 | public | test4 | t
|
||||
(1 row)
|
||||
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-10-14 17:50:16.207', '2' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-11-14 17:50:16.207', '1' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-12-14 17:50:16.207', '3' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-01-14 17:50:16.207', '4' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-02-14 17:50:16.207', '5' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-03-14 17:50:16.207', '6' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-04-14 17:50:16.207', '7' );
|
||||
ALTER TABLE test4 SET (
|
||||
timescaledb.compress,
|
||||
timescaledb.compress_orderby = 'timestamp',
|
||||
timescaledb.compress_segmentby = 'ident'
|
||||
);
|
||||
select count(compress_chunk(ch)) FROM show_chunks('test4') ch;
|
||||
count
|
||||
-------
|
||||
7
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE test4 DROP COLUMN two;
|
||||
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
|
||||
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');
|
||||
|
@ -938,3 +938,38 @@ FROM
|
||||
INSERT INTO :TABLENAME SELECT;
|
||||
ERROR: direct insert into internal compressed hypertable is not supported
|
||||
\set ON_ERROR_STOP 1
|
||||
-- Test that inserting into a compressed table works even when the
|
||||
-- column has been dropped.
|
||||
CREATE TABLE test4 (
|
||||
timestamp timestamp without time zone not null,
|
||||
ident text not null,
|
||||
one double precision,
|
||||
two double precision
|
||||
);
|
||||
SELECT * FROM create_hypertable('test4', 'timestamp');
|
||||
hypertable_id | schema_name | table_name | created
|
||||
---------------+-------------+------------+---------
|
||||
20 | public | test4 | t
|
||||
(1 row)
|
||||
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-10-14 17:50:16.207', '2' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-11-14 17:50:16.207', '1' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-12-14 17:50:16.207', '3' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-01-14 17:50:16.207', '4' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-02-14 17:50:16.207', '5' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-03-14 17:50:16.207', '6' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-04-14 17:50:16.207', '7' );
|
||||
ALTER TABLE test4 SET (
|
||||
timescaledb.compress,
|
||||
timescaledb.compress_orderby = 'timestamp',
|
||||
timescaledb.compress_segmentby = 'ident'
|
||||
);
|
||||
select count(compress_chunk(ch)) FROM show_chunks('test4') ch;
|
||||
count
|
||||
-------
|
||||
7
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE test4 DROP COLUMN two;
|
||||
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
|
||||
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');
|
||||
|
@ -938,3 +938,38 @@ FROM
|
||||
INSERT INTO :TABLENAME SELECT;
|
||||
ERROR: direct insert into internal compressed hypertable is not supported
|
||||
\set ON_ERROR_STOP 1
|
||||
-- Test that inserting into a compressed table works even when the
|
||||
-- column has been dropped.
|
||||
CREATE TABLE test4 (
|
||||
timestamp timestamp without time zone not null,
|
||||
ident text not null,
|
||||
one double precision,
|
||||
two double precision
|
||||
);
|
||||
SELECT * FROM create_hypertable('test4', 'timestamp');
|
||||
hypertable_id | schema_name | table_name | created
|
||||
---------------+-------------+------------+---------
|
||||
20 | public | test4 | t
|
||||
(1 row)
|
||||
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-10-14 17:50:16.207', '2' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-11-14 17:50:16.207', '1' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-12-14 17:50:16.207', '3' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-01-14 17:50:16.207', '4' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-02-14 17:50:16.207', '5' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-03-14 17:50:16.207', '6' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-04-14 17:50:16.207', '7' );
|
||||
ALTER TABLE test4 SET (
|
||||
timescaledb.compress,
|
||||
timescaledb.compress_orderby = 'timestamp',
|
||||
timescaledb.compress_segmentby = 'ident'
|
||||
);
|
||||
select count(compress_chunk(ch)) FROM show_chunks('test4') ch;
|
||||
count
|
||||
-------
|
||||
7
|
||||
(1 row)
|
||||
|
||||
ALTER TABLE test4 DROP COLUMN two;
|
||||
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
|
||||
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');
|
||||
|
@ -612,3 +612,35 @@ FROM
|
||||
INSERT INTO :TABLENAME SELECT;
|
||||
\set ON_ERROR_STOP 1
|
||||
|
||||
-- Test that inserting into a compressed table works even when the
|
||||
-- column has been dropped.
|
||||
CREATE TABLE test4 (
|
||||
timestamp timestamp without time zone not null,
|
||||
ident text not null,
|
||||
one double precision,
|
||||
two double precision
|
||||
);
|
||||
|
||||
SELECT * FROM create_hypertable('test4', 'timestamp');
|
||||
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-10-14 17:50:16.207', '2' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-11-14 17:50:16.207', '1' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2021-12-14 17:50:16.207', '3' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-01-14 17:50:16.207', '4' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-02-14 17:50:16.207', '5' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-03-14 17:50:16.207', '6' );
|
||||
INSERT INTO test4 ( timestamp, ident ) VALUES ( '2022-04-14 17:50:16.207', '7' );
|
||||
|
||||
ALTER TABLE test4 SET (
|
||||
timescaledb.compress,
|
||||
timescaledb.compress_orderby = 'timestamp',
|
||||
timescaledb.compress_segmentby = 'ident'
|
||||
);
|
||||
|
||||
select count(compress_chunk(ch)) FROM show_chunks('test4') ch;
|
||||
|
||||
ALTER TABLE test4 DROP COLUMN two;
|
||||
|
||||
INSERT INTO test4 VALUES ('2021-10-14 17:50:16.207', '7', NULL);
|
||||
INSERT INTO test4 (timestamp, ident) VALUES ('2021-10-14 17:50:16.207', '7');
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user