Fix EXPLAIN for compressed DML

EXPLAIN ANALYZE for compressed DML would error out with `bogus varno`
error because we would modify the original expressions of the plan
that were still referenced in nodes instead of adjusting copies and
using those copies in our internal scans.
This commit is contained in:
Sven Klemm 2023-10-18 11:17:22 +02:00 committed by Sven Klemm
parent 5f5f519030
commit 8f3bb0ba70
4 changed files with 70 additions and 4 deletions

1
.unreleased/pr_6210 Normal file
View File

@ -0,0 +1 @@
Fixes: #6210 Fix EXPLAIN ANALYZE for compressed DML

View File

@ -2756,9 +2756,7 @@ fill_predicate_context(Chunk *ch, List *predicates, List **filters, List **index
ListCell *lc;
foreach (lc, predicates)
{
Node *node = lfirst(lc);
if (node == NULL)
continue;
Node *node = copyObject(lfirst(lc));
Var *var;
char *column_name;
@ -3367,7 +3365,6 @@ decompress_chunk_walker(PlanState *ps, struct decompress_chunk_context *ctx)
case T_TidScanState:
case T_TidRangeScanState:
{
/* We copy so we can always just free the predicates */
predicates = list_copy(ps->plan->qual);
needs_decompression = true;
break;

View File

@ -45,6 +45,22 @@ QUERY PLAN
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (actual rows=20 loops=1)
(10 rows)
BEGIN; :EXPLAIN_ANALYZE UPDATE decompress_tracking SET value = value + 3 WHERE device = 'd2'; ROLLBACK;
QUERY PLAN
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 2
Tuples decompressed: 20
-> Update on decompress_tracking (actual rows=0 loops=1)
Update on _hyper_X_X_chunk decompress_tracking_1
Update on _hyper_X_X_chunk decompress_tracking_2
-> Result (actual rows=20 loops=1)
-> Append (actual rows=20 loops=1)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_1 (actual rows=15 loops=1)
Filter: (device = 'd2'::text)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (actual rows=5 loops=1)
Filter: (device = 'd2'::text)
(12 rows)
BEGIN; :EXPLAIN_ANALYZE DELETE FROM decompress_tracking; ROLLBACK;
QUERY PLAN
Custom Scan (HypertableModify) (actual rows=0 loops=1)
@ -58,6 +74,21 @@ QUERY PLAN
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (actual rows=20 loops=1)
(9 rows)
BEGIN; :EXPLAIN_ANALYZE DELETE FROM decompress_tracking WHERE device = 'd3'; ROLLBACK;
QUERY PLAN
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 2
Tuples decompressed: 30
-> Delete on decompress_tracking (actual rows=0 loops=1)
Delete on _hyper_X_X_chunk decompress_tracking_1
Delete on _hyper_X_X_chunk decompress_tracking_2
-> Append (actual rows=30 loops=1)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_1 (actual rows=15 loops=1)
Filter: (device = 'd3'::text)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (actual rows=15 loops=1)
Filter: (device = 'd3'::text)
(11 rows)
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01 1:30','d1',random(); ROLLBACK;
QUERY PLAN
Custom Scan (HypertableModify) (actual rows=0 loops=1)
@ -97,4 +128,34 @@ QUERY PLAN
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
(6 rows)
-- test prepared statements EXPLAIN still works after execution
SET plan_cache_mode TO force_generic_plan;
PREPARE p1 AS UPDATE decompress_tracking SET value = value + 3 WHERE device = 'd1';
BEGIN; EXPLAIN EXECUTE p1; EXECUTE p1; EXPLAIN EXECUTE p1; ROLLBACK;
QUERY PLAN
Custom Scan (HypertableModify) (cost=0.00..70.83 rows=433 width=18)
-> Update on decompress_tracking (cost=0.00..70.83 rows=433 width=18)
Update on _hyper_X_X_chunk decompress_tracking_1
Update on _hyper_X_X_chunk decompress_tracking_2
-> Result (cost=0.00..70.83 rows=433 width=18)
-> Append (cost=0.00..65.42 rows=433 width=18)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_1 (cost=0.00..31.62 rows=432 width=18)
Filter: (device = 'd1'::text)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (cost=0.00..31.62 rows=1 width=18)
Filter: (device = 'd1'::text)
(10 rows)
QUERY PLAN
Custom Scan (HypertableModify) (cost=0.00..70.83 rows=433 width=18)
-> Update on decompress_tracking (cost=0.00..70.83 rows=433 width=18)
Update on _hyper_X_X_chunk decompress_tracking_1
Update on _hyper_X_X_chunk decompress_tracking_2
-> Result (cost=0.00..70.83 rows=433 width=18)
-> Append (cost=0.00..65.42 rows=433 width=18)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_1 (cost=0.00..31.62 rows=432 width=18)
Filter: (device = 'd1'::text)
-> Seq Scan on _hyper_X_X_chunk decompress_tracking_2 (cost=0.00..31.62 rows=1 width=18)
Filter: (device = 'd1'::text)
(10 rows)
DROP TABLE decompress_tracking;

View File

@ -19,10 +19,17 @@ SELECT count(compress_chunk(ch)) FROM show_chunks('decompress_tracking') ch;
:EXPLAIN UPDATE decompress_tracking SET value = value + 3;
BEGIN; :EXPLAIN_ANALYZE UPDATE decompress_tracking SET value = value + 3; ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE UPDATE decompress_tracking SET value = value + 3 WHERE device = 'd2'; ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE DELETE FROM decompress_tracking; ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE DELETE FROM decompress_tracking WHERE device = 'd3'; ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01 1:30','d1',random(); ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01','d2',random(); ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking SELECT '2020-01-01','d4',random(); ROLLBACK;
BEGIN; :EXPLAIN_ANALYZE INSERT INTO decompress_tracking (VALUES ('2020-01-01 1:30','d1',random()),('2020-01-01 1:30','d2',random())); ROLLBACK;
-- test prepared statements EXPLAIN still works after execution
SET plan_cache_mode TO force_generic_plan;
PREPARE p1 AS UPDATE decompress_tracking SET value = value + 3 WHERE device = 'd1';
BEGIN; EXPLAIN EXECUTE p1; EXECUTE p1; EXPLAIN EXECUTE p1; ROLLBACK;
DROP TABLE decompress_tracking;