mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-16 18:43:18 +08:00
Fix issue when copying into arrow slot
If you set the table access method for a hypertable all new chunks will use `ArrowTupleTableSlot` but the copy code assumes that the parent table has a virtual tuple table slot. This causes a crash when copying a heap tuple since the values are stored in the "main" slot and not in either of the child tuple table slots. Fix this issue by storing the values in the uncompressed slot when it is empty.
This commit is contained in:
parent
d28a9fc892
commit
1a9d319d4b
@ -732,6 +732,20 @@ tts_arrow_copy_heap_tuple(TupleTableSlot *slot)
|
||||
copy_slot_values(slot, aslot->noncompressed_slot, slot->tts_tupleDescriptor->natts);
|
||||
}
|
||||
|
||||
/* If the non-compressed slot is empty, we are being called as if we are a
|
||||
* virtual TTS (from function `copyfrom` in src/copy.c), so in this case
|
||||
* we should copy the heap tuple from the "root" slot, which is
|
||||
* virtual.
|
||||
*
|
||||
* We already know that the "root" slot is not empty when this function is
|
||||
* being called.
|
||||
*
|
||||
* This does an extra memcpy() of the tts_values and tts_isnull, so might
|
||||
* be possible to optimize away.
|
||||
*/
|
||||
if (TTS_EMPTY(aslot->noncompressed_slot))
|
||||
copy_slot_values(slot, aslot->noncompressed_slot, slot->tts_tupleDescriptor->natts);
|
||||
|
||||
/* Since this tuple is generated from a baserel, there are cases when PG
|
||||
* code expects the TID (t_self) to be set (e.g., during ANALYZE). But
|
||||
* this doesn't happen if the tuple is formed from values similar to a
|
||||
|
@ -105,6 +105,11 @@ select format('%I.%I', chunk_schema, chunk_name)::regclass as chunk2
|
||||
where format('%I.%I', hypertable_schema, hypertable_name)::regclass = :'hypertable'::regclass
|
||||
order by chunk2 asc
|
||||
limit 1 offset 1 \gset
|
||||
create view amrels as
|
||||
select cl.oid::regclass as rel, am.amname, inh.inhparent::regclass as relparent
|
||||
from pg_class cl
|
||||
inner join pg_am am on (cl.relam = am.oid)
|
||||
left join pg_inherits inh on (inh.inhrelid = cl.oid);
|
||||
-- Compress the chunks and check that the counts are the same
|
||||
select location_id, count(*) into orig from :hypertable GROUP BY location_id;
|
||||
select compress_chunk(show_chunks(:'hypertable'), compress_using => 'hyperstore');
|
||||
@ -209,3 +214,42 @@ select * from copy_test1 order by metric_id;
|
||||
-- load it again, but this statement fails.
|
||||
--
|
||||
-- select * into subset from :hypertable where device_id between 0 and 10;
|
||||
-- Testing copy into a table that has the access method set but has
|
||||
-- already existing (compressed) heap-chunks in the table.
|
||||
CREATE TABLE test1 (timec timestamptz , i integer, b bigint, t text);
|
||||
SELECT table_name from create_hypertable('test1', 'timec');
|
||||
NOTICE: adding not-null constraint to column "timec"
|
||||
table_name
|
||||
------------
|
||||
test1
|
||||
(1 row)
|
||||
|
||||
INSERT INTO test1 SELECT q, 10, 11, 'hello'
|
||||
FROM generate_series( '2020-01-03 10:00:00-05', '2020-01-03 12:00:00-05' , '5 min'::interval) q;
|
||||
alter table test1 set (timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = 'timec DESC');
|
||||
SELECT compress_chunk(show_chunks('test1'));
|
||||
compress_chunk
|
||||
-----------------------------------------
|
||||
_timescaledb_internal._hyper_5_15_chunk
|
||||
(1 row)
|
||||
|
||||
select count(*) from test1;
|
||||
count
|
||||
-------
|
||||
25
|
||||
(1 row)
|
||||
|
||||
select * from amrels where relparent = 'test1'::regclass;
|
||||
rel | amname | relparent
|
||||
-----------------------------------------+--------+-----------
|
||||
_timescaledb_internal._hyper_5_15_chunk | heap | test1
|
||||
(1 row)
|
||||
|
||||
alter table test1 set access method hyperstore;
|
||||
copy test1 from stdin delimiter ',';
|
||||
select count(*) from test1;
|
||||
count
|
||||
-------
|
||||
26
|
||||
(1 row)
|
||||
|
||||
|
@ -4,6 +4,12 @@
|
||||
|
||||
\ir include/setup_hyperstore.sql
|
||||
|
||||
create view amrels as
|
||||
select cl.oid::regclass as rel, am.amname, inh.inhparent::regclass as relparent
|
||||
from pg_class cl
|
||||
inner join pg_am am on (cl.relam = am.oid)
|
||||
left join pg_inherits inh on (inh.inhrelid = cl.oid);
|
||||
|
||||
-- Compress the chunks and check that the counts are the same
|
||||
select location_id, count(*) into orig from :hypertable GROUP BY location_id;
|
||||
select compress_chunk(show_chunks(:'hypertable'), compress_using => 'hyperstore');
|
||||
@ -69,3 +75,23 @@ select * from copy_test1 order by metric_id;
|
||||
--
|
||||
-- select * into subset from :hypertable where device_id between 0 and 10;
|
||||
|
||||
-- Testing copy into a table that has the access method set but has
|
||||
-- already existing (compressed) heap-chunks in the table.
|
||||
CREATE TABLE test1 (timec timestamptz , i integer, b bigint, t text);
|
||||
SELECT table_name from create_hypertable('test1', 'timec');
|
||||
INSERT INTO test1 SELECT q, 10, 11, 'hello'
|
||||
FROM generate_series( '2020-01-03 10:00:00-05', '2020-01-03 12:00:00-05' , '5 min'::interval) q;
|
||||
alter table test1 set (timescaledb.compress_segmentby = 'b', timescaledb.compress_orderby = 'timec DESC');
|
||||
SELECT compress_chunk(show_chunks('test1'));
|
||||
|
||||
select count(*) from test1;
|
||||
|
||||
select * from amrels where relparent = 'test1'::regclass;
|
||||
|
||||
alter table test1 set access method hyperstore;
|
||||
|
||||
copy test1 from stdin delimiter ',';
|
||||
2020-01-02 11:16:00-05,11,16,copy
|
||||
\.
|
||||
|
||||
select count(*) from test1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user