Skip to content

Commit

Permalink
Fix assert in dimension slice lookup
Browse files Browse the repository at this point in the history
Calling ts_scan_iterator_next will advance internal scanner data
structures. It is therefore not safe to use the iterator after
ts_scan_iterator_next returned NULL and expect to be able to access
the previous tuple. Under certain circumstances this may point the
iterator to tuples not normally visible.
  • Loading branch information
svenklemm committed Sep 25, 2023
1 parent 887f538 commit bdcca06
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/dimension_slice.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,13 +811,20 @@ ts_dimension_slice_scan_iterator_get_by_id(ScanIterator *it, int32 slice_id,
const ScanTupLock *tuplock)
{
TupleInfo *ti;
DimensionSlice *slice = NULL;

ts_dimension_slice_scan_iterator_set_slice_id(it, slice_id, tuplock);
ts_scan_iterator_start_or_restart_scan(it);
ti = ts_scan_iterator_next(it);
Assert(ti);
Assert(ts_scan_iterator_next(it) == NULL); /* This is a heavy call, consider removing it */
return ti ? ts_dimension_slice_from_tuple(ti) : NULL;

if (ti)
{
slice = ts_dimension_slice_from_tuple(ti);
Assert(ts_scan_iterator_next(it) == NULL);
}

return slice;
}

DimensionSlice *
Expand Down
25 changes: 25 additions & 0 deletions tsl/test/expected/chunk_utils_internal.out
Original file line number Diff line number Diff line change
Expand Up @@ -1391,6 +1391,31 @@ SELECT _timescaledb_functions.hypertable_osm_range_update('osm_tstz', '2020-01-0
SELECT _timescaledb_functions.hypertable_osm_range_update('osm_tstz', 9223372036854771806, 9223372036854775406);
ERROR: invalid time argument type "bigint"
\set ON_ERROR_STOP 1
-- test dimension slice tuple visibility
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE TABLE osm_slice_update(time int not null);
SELECT hypertable_id AS ht_id FROM create_hypertable('osm_slice_update', 'time', chunk_time_interval => 10) \gset
INSERT INTO osm_slice_update VALUES (1);
UPDATE _timescaledb_catalog.hypertable SET status = 3 WHERE id = :ht_id;
UPDATE _timescaledb_catalog.chunk SET osm_chunk = true WHERE hypertable_id = :ht_id;
\c
BEGIN;
SELECT _timescaledb_functions.hypertable_osm_range_update('osm_slice_update',40,50);
hypertable_osm_range_update
-----------------------------
f
(1 row)

ROLLBACK;
\c
-- new session should not be affected by previous rolled back transaction
-- should show 0 10 as range
\set ON_ERROR_STOP 0
INSERT INTO osm_slice_update VALUES (1);
ERROR: Cannot insert into tiered chunk range of public.osm_slice_update - attempt to create new chunk with range [0 10] failed
INSERT INTO osm_slice_update VALUES (1);
ERROR: Cannot insert into tiered chunk range of public.osm_slice_update - attempt to create new chunk with range [0 10] failed
\set ON_ERROR_STOP 1
-- clean up databases created
\c :TEST_DBNAME :ROLE_SUPERUSER
DROP DATABASE postgres_fdw_db;
Expand Down
24 changes: 24 additions & 0 deletions tsl/test/sql/chunk_utils_internal.sql
Original file line number Diff line number Diff line change
Expand Up @@ -738,8 +738,32 @@ SELECT _timescaledb_functions.hypertable_osm_range_update('osm_tstz', '2020-01-0
-- udpate range of timestamp with bigint
SELECT _timescaledb_functions.hypertable_osm_range_update('osm_tstz', 9223372036854771806, 9223372036854775406);
\set ON_ERROR_STOP 1

-- test dimension slice tuple visibility
\c :TEST_DBNAME :ROLE_SUPERUSER
CREATE TABLE osm_slice_update(time int not null);
SELECT hypertable_id AS ht_id FROM create_hypertable('osm_slice_update', 'time', chunk_time_interval => 10) \gset

INSERT INTO osm_slice_update VALUES (1);
UPDATE _timescaledb_catalog.hypertable SET status = 3 WHERE id = :ht_id;
UPDATE _timescaledb_catalog.chunk SET osm_chunk = true WHERE hypertable_id = :ht_id;

\c
BEGIN;
SELECT _timescaledb_functions.hypertable_osm_range_update('osm_slice_update',40,50);
ROLLBACK;

\c
-- new session should not be affected by previous rolled back transaction
-- should show 0 10 as range
\set ON_ERROR_STOP 0
INSERT INTO osm_slice_update VALUES (1);
INSERT INTO osm_slice_update VALUES (1);
\set ON_ERROR_STOP 1

-- clean up databases created
\c :TEST_DBNAME :ROLE_SUPERUSER
DROP DATABASE postgres_fdw_db;
DROP DATABASE :DATA_NODE_1;
DROP DATABASE :DATA_NODE_2;

0 comments on commit bdcca06

Please sign in to comment.