Skip to content

Commit 2525b81

Browse files
svenklemmtimescale-automation
authored andcommitted
Fix segfault in UNION queries with top-level ordering
We can't just filter the equivalence member based on em_is_child as our hypertable might not be top-level equivalence member. (cherry picked from commit 180c7be)
1 parent 9bddf22 commit 2525b81

7 files changed

+120
-12
lines changed

.unreleased/pr_6957

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes: #6957 Fix segfault in UNION queries with ordering on compressed chunks

tsl/src/nodes/decompress_chunk/decompress_chunk.c

+8-12
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ build_compressed_scan_pathkeys(SortInfo *sort_info, PlannerInfo *root, List *chu
195195
* already refers a compressed column, it is a bug. See
196196
* build_sortinfo().
197197
*/
198-
Assert(compressed_em != NULL);
198+
Ensure(compressed_em, "corresponding equivalence member not found");
199199

200200
required_compressed_pathkeys = lappend(required_compressed_pathkeys, pk);
201201

@@ -1488,17 +1488,6 @@ add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec,
14881488
Var *var;
14891489
Assert(!bms_overlap(cur_em->em_relids, info->compressed_rel->relids));
14901490

1491-
/*
1492-
* We want to base our equivalence member on the hypertable equivalence
1493-
* member, not on the uncompressed chunk one, because the latter is
1494-
* marked as child itself. This is mostly relevant for PG16 where we
1495-
* have to specify a parent for the newly created equivalence member.
1496-
*/
1497-
if (cur_em->em_is_child)
1498-
{
1499-
continue;
1500-
}
1501-
15021491
/* only consider EquivalenceMembers that are Vars, possibly with RelabelType, of the
15031492
* uncompressed chunk */
15041493
var = (Var *) cur_em->em_expr;
@@ -1507,6 +1496,13 @@ add_segmentby_to_equivalence_class(PlannerInfo *root, EquivalenceClass *cur_ec,
15071496
if (!(var && IsA(var, Var)))
15081497
continue;
15091498

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

tsl/test/shared/expected/transparent_decompress_chunk-13.out

+24
Original file line numberDiff line numberDiff line change
@@ -1040,3 +1040,27 @@ EXECUTE param_prep (1);
10401040

10411041
DEALLOCATE param_prep;
10421042
RESET plan_cache_mode;
1043+
-- test hypertable being non-toplevel equivalence member #6925
1044+
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
1045+
CREATE TABLE i6925_t2(LIKE i6925_t1);
1046+
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
1047+
table_name
1048+
i6925_t1
1049+
(1 row)
1050+
1051+
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
1052+
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
1053+
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
1054+
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
1055+
count
1056+
1
1057+
(1 row)
1058+
1059+
SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
1060+
queryid | lag
1061+
---------+-----
1062+
1 |
1063+
(1 row)
1064+
1065+
DROP TABLE i6925_t1;
1066+
DROP TABLE i6925_t2;

tsl/test/shared/expected/transparent_decompress_chunk-14.out

+24
Original file line numberDiff line numberDiff line change
@@ -1040,3 +1040,27 @@ EXECUTE param_prep (1);
10401040

10411041
DEALLOCATE param_prep;
10421042
RESET plan_cache_mode;
1043+
-- test hypertable being non-toplevel equivalence member #6925
1044+
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
1045+
CREATE TABLE i6925_t2(LIKE i6925_t1);
1046+
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
1047+
table_name
1048+
i6925_t1
1049+
(1 row)
1050+
1051+
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
1052+
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
1053+
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
1054+
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
1055+
count
1056+
1
1057+
(1 row)
1058+
1059+
SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
1060+
queryid | lag
1061+
---------+-----
1062+
1 |
1063+
(1 row)
1064+
1065+
DROP TABLE i6925_t1;
1066+
DROP TABLE i6925_t2;

tsl/test/shared/expected/transparent_decompress_chunk-15.out

+24
Original file line numberDiff line numberDiff line change
@@ -1042,3 +1042,27 @@ EXECUTE param_prep (1);
10421042

10431043
DEALLOCATE param_prep;
10441044
RESET plan_cache_mode;
1045+
-- test hypertable being non-toplevel equivalence member #6925
1046+
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
1047+
CREATE TABLE i6925_t2(LIKE i6925_t1);
1048+
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
1049+
table_name
1050+
i6925_t1
1051+
(1 row)
1052+
1053+
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
1054+
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
1055+
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
1056+
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
1057+
count
1058+
1
1059+
(1 row)
1060+
1061+
SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
1062+
queryid | lag
1063+
---------+-----
1064+
1 |
1065+
(1 row)
1066+
1067+
DROP TABLE i6925_t1;
1068+
DROP TABLE i6925_t2;

tsl/test/shared/expected/transparent_decompress_chunk-16.out

+24
Original file line numberDiff line numberDiff line change
@@ -1042,3 +1042,27 @@ EXECUTE param_prep (1);
10421042

10431043
DEALLOCATE param_prep;
10441044
RESET plan_cache_mode;
1045+
-- test hypertable being non-toplevel equivalence member #6925
1046+
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
1047+
CREATE TABLE i6925_t2(LIKE i6925_t1);
1048+
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
1049+
table_name
1050+
i6925_t1
1051+
(1 row)
1052+
1053+
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
1054+
NOTICE: default order by for hypertable "i6925_t1" is set to "observed DESC"
1055+
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
1056+
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
1057+
count
1058+
1
1059+
(1 row)
1060+
1061+
SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
1062+
queryid | lag
1063+
---------+-----
1064+
1 |
1065+
(1 row)
1066+
1067+
DROP TABLE i6925_t1;
1068+
DROP TABLE i6925_t2;

tsl/test/shared/sql/transparent_decompress_chunk.sql.in

+15
Original file line numberDiff line numberDiff line change
@@ -331,3 +331,18 @@ EXECUTE param_prep (2);
331331
EXECUTE param_prep (1);
332332
DEALLOCATE param_prep;
333333
RESET plan_cache_mode;
334+
335+
-- test hypertable being non-toplevel equivalence member #6925
336+
CREATE TABLE i6925_t1(observed timestamptz not null, queryid int8, total_exec_time int8);
337+
CREATE TABLE i6925_t2(LIKE i6925_t1);
338+
339+
SELECT table_name FROM create_hypertable('i6925_t1', 'observed');
340+
ALTER TABLE i6925_t1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'queryid');
341+
INSERT INTO i6925_t1 SELECT '2020-01-01', 1, 1;
342+
SELECT count(compress_chunk(chunk_name)) FROM show_chunks('i6925_t1') chunk_name;
343+
344+
SELECT queryid, lag(total_exec_time) OVER (PARTITION BY queryid) FROM (SELECT * FROM i6925_t1 UNION ALL SELECT * FROM i6925_t2) q;
345+
346+
DROP TABLE i6925_t1;
347+
DROP TABLE i6925_t2;
348+

0 commit comments

Comments
 (0)