Skip to content

Commit

Permalink
Fix segfault in UNION queries with top-level ordering
Browse files Browse the repository at this point in the history
We can't just filter the equivalence member based on em_is_child as our
hypertable might not be top-level equivalence member.
  • Loading branch information
svenklemm committed May 26, 2024
1 parent f5d466c commit 6f5a68b
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 12 deletions.
20 changes: 8 additions & 12 deletions tsl/src/nodes/decompress_chunk/decompress_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ build_compressed_scan_pathkeys(SortInfo *sort_info, PlannerInfo *root, List *chu
* already refers a compressed column, it is a bug. See
* build_sortinfo().
*/
Assert(compressed_em != NULL);
Ensure(compressed_em, "corresponding equivalence member not found");

required_compressed_pathkeys = lappend(required_compressed_pathkeys, pk);

Expand Down Expand Up @@ -1482,17 +1482,6 @@ add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec,
Var *var;
Assert(!bms_overlap(cur_em->em_relids, info->compressed_rel->relids));

/*
* We want to base our equivalence member on the hypertable equivalence
* member, not on the uncompressed chunk one, because the latter is
* marked as child itself. This is mostly relevant for PG16 where we
* have to specify a parent for the newly created equivalence member.
*/
if (cur_em->em_is_child)
{
continue;
}

/* only consider EquivalenceMembers that are Vars, possibly with RelabelType, of the
* uncompressed chunk */
var = (Var *) cur_em->em_expr;
Expand All @@ -1501,6 +1490,13 @@ add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec,
if (!(var && IsA(var, Var)))
continue;

/*
* We want to base our equivalence member on the hypertable equivalence
* member, not on the uncompressed chunk one. We can't just check for
* em_is_child though because the hypertable might be a child itself and not
* a top-level EquivalenceMember. This is mostly relevant for PG16+ where
* we have to specify a parent for the newly created equivalence member.
*/
if ((Index) var->varno != info->ht_rel->relid)
continue;

Expand Down
22 changes: 22 additions & 0 deletions tsl/test/shared/expected/transparent_decompress_chunk-14.out
Original file line number Diff line number Diff line change
Expand Up @@ -1039,3 +1039,25 @@ EXECUTE param_prep (1);

DEALLOCATE param_prep;
RESET plan_cache_mode;
-- test hypertable being non-toplevel equivalence member #6925
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
CREATE TABLE i6925_t2(LIKE i6925_t1);
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
table_name
i6925_t1
(1 row)

ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
count
1
(1 row)

SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
queryid | lag
---------+-----
1 |
(1 row)

22 changes: 22 additions & 0 deletions tsl/test/shared/expected/transparent_decompress_chunk-15.out
Original file line number Diff line number Diff line change
Expand Up @@ -1041,3 +1041,25 @@ EXECUTE param_prep (1);

DEALLOCATE param_prep;
RESET plan_cache_mode;
-- test hypertable being non-toplevel equivalence member #6925
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
CREATE TABLE i6925_t2(LIKE i6925_t1);
SELECT create_hypertable('i6925_t1', 'observed');
create_hypertable
(8,public,i6925_t1,t)
(1 row)

ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
count
1
(1 row)

SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
queryid | lag
---------+-----
1 |
(1 row)

22 changes: 22 additions & 0 deletions tsl/test/shared/expected/transparent_decompress_chunk-16.out
Original file line number Diff line number Diff line change
Expand Up @@ -1041,3 +1041,25 @@ EXECUTE param_prep (1);

DEALLOCATE param_prep;
RESET plan_cache_mode;
-- test hypertable being non-toplevel equivalence member #6925
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
CREATE TABLE i6925_t2(LIKE i6925_t1);
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
table_name
i6925_t1
(1 row)

ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
count
1
(1 row)

SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
queryid | lag
---------+-----
1 |
(1 row)

12 changes: 12 additions & 0 deletions tsl/test/shared/sql/transparent_decompress_chunk.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -331,3 +331,15 @@ EXECUTE param_prep (2);
EXECUTE param_prep (1);
DEALLOCATE param_prep;
RESET plan_cache_mode;

-- test hypertable being non-toplevel equivalence member #6925
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
CREATE TABLE i6925_t2(LIKE i6925_t1);

SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;

SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;

0 comments on commit 6f5a68b

Please sign in to comment.