@@ -2851,13 +2851,12 @@ BEGIN; :EXPLAIN DELETE FROM test_pushdown WHERE device = substring(CURRENT_USER,
28512851--- QUERY PLAN ---
28522852 Custom Scan (ModifyHypertable) (actual rows=0.00 loops=1)
28532853 Batches scanned: 1
2854- Batches decompressed: 1
2855- Tuples decompressed: 1
2854+ Batches deleted: 1
28562855 -> Delete on test_pushdown (actual rows=0.00 loops=1)
28572856 Delete on _hyper_39_76_chunk test_pushdown_1
2858- -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=1 .00 loops=1)
2857+ -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=0 .00 loops=1)
28592858 Chunks excluded during startup: 0
2860- -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=1 .00 loops=1)
2859+ -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=0 .00 loops=1)
28612860 Filter: (device = ("substring"((CURRENT_USER)::text, (length((CURRENT_USER)::text) + 1)) || 'c'::text))
28622861
28632862-- JOIN tests
@@ -2990,6 +2989,77 @@ BEGIN; :EXPLAIN EXECUTE q1('not here'); ROLLBACK;
29902989 -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=0.00 loops=1)
29912990 Filter: (device = 'not here'::text)
29922991
2992+ -- prepared statement with generic plan (param should be constified)
2993+ SET plan_cache_mode = force_generic_plan;
2994+ BEGIN; :EXPLAIN EXECUTE q1('a'); ROLLBACK;
2995+ --- QUERY PLAN ---
2996+ Custom Scan (ModifyHypertable) (actual rows=0.00 loops=1)
2997+ Batches scanned: 1
2998+ Batches deleted: 1
2999+ -> Delete on test_pushdown (actual rows=0.00 loops=1)
3000+ Delete on _hyper_39_76_chunk test_pushdown_1
3001+ -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=0.00 loops=1)
3002+ Chunks excluded during startup: 0
3003+ -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=0.00 loops=1)
3004+ Filter: (device = $1)
3005+
3006+ BEGIN; :EXPLAIN EXECUTE q1('not here'); ROLLBACK;
3007+ --- QUERY PLAN ---
3008+ Custom Scan (ModifyHypertable) (actual rows=0.00 loops=1)
3009+ -> Delete on test_pushdown (actual rows=0.00 loops=1)
3010+ Delete on _hyper_39_76_chunk test_pushdown_1
3011+ -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=0.00 loops=1)
3012+ Chunks excluded during startup: 0
3013+ -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=0.00 loops=1)
3014+ Filter: (device = $1)
3015+
3016+ RESET plan_cache_mode;
3017+ -- ensure that we're not incorrectly constifying the nestloop join params
3018+ CREATE TABLE nl_param(time timestamptz NOT NULL, device int, PRIMARY KEY(device, time));
3019+ SELECT table_name FROM create_hypertable('nl_param', 'time', chunk_time_interval => INTERVAL '10 years');
3020+ table_name
3021+ ------------
3022+ nl_param
3023+
3024+ INSERT INTO nl_param
3025+ SELECT '2020-01-01'::timestamptz + (i || ' seconds')::interval, (i % 100) + 1
3026+ FROM generate_series(1, 50000) i;
3027+ ALTER TABLE nl_param SET (timescaledb.compress, timescaledb.compress_segmentby='device');
3028+ SELECT compress_chunk(show_chunks('nl_param'));
3029+ compress_chunk
3030+ ------------------------------------------
3031+ _timescaledb_internal._hyper_41_78_chunk
3032+
3033+ -- Uncompressed rows so PG sees a non-empty heap and considers indexed paths
3034+ INSERT INTO nl_param
3035+ SELECT '2025-01-01'::timestamptz + (i || ' seconds')::interval, (i % 100) + 1
3036+ FROM generate_series(1, 50000) i;
3037+ CREATE TABLE nl_devices(device int);
3038+ INSERT INTO nl_devices VALUES (1);
3039+ ANALYZE nl_param, nl_devices;
3040+ SET enable_hashjoin = off;
3041+ SET enable_mergejoin = off;
3042+ SET enable_seqscan = off;
3043+ BEGIN; :EXPLAIN DELETE FROM nl_param p USING nl_devices d WHERE p.device=d.device; SELECT count(*) FROM nl_param; ROLLBACK;
3044+ --- QUERY PLAN ---
3045+ Custom Scan (ModifyHypertable) (actual rows=0.00 loops=1)
3046+ Batches scanned: 100
3047+ Batches decompressed: 100
3048+ Tuples decompressed: 50000
3049+ -> Delete on nl_param p (actual rows=0.00 loops=1)
3050+ Delete on _hyper_41_78_chunk p_1
3051+ -> Nested Loop (actual rows=1000.00 loops=1)
3052+ -> Seq Scan on nl_devices d (actual rows=1.00 loops=1)
3053+ -> Index Scan using "78_nl_param_pkey" on _hyper_41_78_chunk p_1 (actual rows=1000.00 loops=1)
3054+ Index Cond: (device = d.device)
3055+
3056+ count
3057+ -------
3058+ 99000
3059+
3060+ RESET enable_hashjoin;
3061+ RESET enable_mergejoin;
3062+ RESET enable_seqscan;
29933063-- test arrayop pushdown less than 3 decompressions are expected for successful pushdown
29943064BEGIN; :EXPLAIN DELETE FROM test_pushdown WHERE device IN ('a','d'); ROLLBACK;
29953065--- QUERY PLAN ---
@@ -3015,13 +3085,12 @@ BEGIN; :EXPLAIN DELETE FROM test_pushdown WHERE device IN ('a',CURRENT_USER); RO
30153085--- QUERY PLAN ---
30163086 Custom Scan (ModifyHypertable) (actual rows=0.00 loops=1)
30173087 Batches scanned: 1
3018- Batches decompressed: 1
3019- Tuples decompressed: 1
3088+ Batches deleted: 1
30203089 -> Delete on test_pushdown (actual rows=0.00 loops=1)
30213090 Delete on _hyper_39_76_chunk test_pushdown_1
3022- -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=1 .00 loops=1)
3091+ -> Custom Scan (ChunkAppend) on test_pushdown (actual rows=0 .00 loops=1)
30233092 Chunks excluded during startup: 0
3024- -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=1 .00 loops=1)
3093+ -> Seq Scan on _hyper_39_76_chunk test_pushdown_1 (actual rows=0 .00 loops=1)
30253094 Filter: (device = ANY (ARRAY['a'::text, (CURRENT_USER)::text]))
30263095
30273096-- arroyop pushdown only works for segmentby columns atm so 3 decompressions are expected for now
@@ -3129,7 +3198,7 @@ CREATE TABLE update_trigger_test (
31293198SELECT create_hypertable('update_trigger_test', 'effective_date_time');
31303199 create_hypertable
31313200-----------------------------------
3132- (41 ,public,update_trigger_test,t)
3201+ (43 ,public,update_trigger_test,t)
31333202
31343203CREATE OR REPLACE FUNCTION update_modified_at_test()
31353204RETURNS TRIGGER
@@ -3155,7 +3224,7 @@ ALTER TABLE update_trigger_test SET (timescaledb.compress);
31553224SELECT compress_chunk(show_chunks('update_trigger_test'));
31563225 compress_chunk
31573226------------------------------------------
3158- _timescaledb_internal._hyper_41_78_chunk
3227+ _timescaledb_internal._hyper_43_80_chunk
31593228
31603229BEGIN;
31613230UPDATE update_trigger_test SET measurement = measurement + 2
@@ -3165,7 +3234,7 @@ ROLLBACK;
31653234SELECT decompress_chunk(show_chunks('update_trigger_test'));
31663235 decompress_chunk
31673236------------------------------------------
3168- _timescaledb_internal._hyper_41_78_chunk
3237+ _timescaledb_internal._hyper_43_80_chunk
31693238
31703239ALTER TABLE update_trigger_test SET (timescaledb.compress, timescaledb.compress_segmentby='entity_id');
31713240NOTICE: updated compression settings will only apply to future compressions
@@ -3174,7 +3243,7 @@ HINT: Use compress_chunk(chunk, recompress => true) to recompress.
31743243SELECT compress_chunk(show_chunks('update_trigger_test'));
31753244 compress_chunk
31763245------------------------------------------
3177- _timescaledb_internal._hyper_41_78_chunk
3246+ _timescaledb_internal._hyper_43_80_chunk
31783247
31793248BEGIN;
31803249UPDATE update_trigger_test SET measurement = measurement + 2
@@ -3204,13 +3273,13 @@ BEGIN
32043273 Batches scanned: 3
32053274 Batches deleted: 3
32063275 -> Delete on delete_counter (actual rows=0.00 loops=1)
3207- Delete on _hyper_43_81_chunk delete_counter_1
3208- Delete on _hyper_43_82_chunk delete_counter_2
3209- Delete on _hyper_43_85_chunk delete_counter_3
3276+ Delete on _hyper_45_83_chunk delete_counter_1
3277+ Delete on _hyper_45_84_chunk delete_counter_2
3278+ Delete on _hyper_45_87_chunk delete_counter_3
32103279 -> Append (actual rows=246.00 loops=1)
3211- -> Seq Scan on _hyper_43_81_chunk delete_counter_1 (actual rows=0.00 loops=1)
3212- -> Seq Scan on _hyper_43_82_chunk delete_counter_2 (actual rows=123.00 loops=1)
3213- -> Seq Scan on _hyper_43_85_chunk delete_counter_3 (actual rows=123.00 loops=1)
3280+ -> Seq Scan on _hyper_45_83_chunk delete_counter_1 (actual rows=0.00 loops=1)
3281+ -> Seq Scan on _hyper_45_84_chunk delete_counter_2 (actual rows=123.00 loops=1)
3282+ -> Seq Scan on _hyper_45_87_chunk delete_counter_3 (actual rows=123.00 loops=1)
32143283
32153284ROLLBACK
32163285BEGIN; DELETE FROM delete_counter; ROLLBACK;
@@ -3225,16 +3294,16 @@ BEGIN
32253294 Batches decompressed: 3
32263295 Tuples decompressed: 369
32273296 -> Delete on delete_counter (actual rows=0.00 loops=1)
3228- Delete on _hyper_43_81_chunk delete_counter_1
3229- Delete on _hyper_43_82_chunk delete_counter_2
3230- Delete on _hyper_43_85_chunk delete_counter_3
3297+ Delete on _hyper_45_83_chunk delete_counter_1
3298+ Delete on _hyper_45_84_chunk delete_counter_2
3299+ Delete on _hyper_45_87_chunk delete_counter_3
32313300 -> Custom Scan (ChunkAppend) on delete_counter (actual rows=615.00 loops=1)
32323301 Chunks excluded during startup: 0
3233- -> Seq Scan on _hyper_43_81_chunk delete_counter_1 (actual rows=246.00 loops=1)
3302+ -> Seq Scan on _hyper_45_83_chunk delete_counter_1 (actual rows=246.00 loops=1)
32343303 Filter: (random() < '1'::double precision)
3235- -> Seq Scan on _hyper_43_82_chunk delete_counter_2 (actual rows=246.00 loops=1)
3304+ -> Seq Scan on _hyper_45_84_chunk delete_counter_2 (actual rows=246.00 loops=1)
32363305 Filter: (random() < '1'::double precision)
3237- -> Seq Scan on _hyper_43_85_chunk delete_counter_3 (actual rows=123.00 loops=1)
3306+ -> Seq Scan on _hyper_45_87_chunk delete_counter_3 (actual rows=123.00 loops=1)
32383307 Filter: (random() < '1'::double precision)
32393308
32403309ROLLBACK
@@ -3265,11 +3334,11 @@ EXPLAIN (analyze,costs off, timing off,summary off, buffers off) DELETE FROM cag
32653334 Batches scanned: 2
32663335 Batches deleted: 2
32673336 -> Delete on cagg_inval (actual rows=0.00 loops=1)
3268- Delete on _hyper_45_86_chunk cagg_inval_1
3269- Delete on _hyper_45_87_chunk cagg_inval_2
3337+ Delete on _hyper_47_88_chunk cagg_inval_1
3338+ Delete on _hyper_47_89_chunk cagg_inval_2
32703339 -> Append (actual rows=0.00 loops=1)
3271- -> Seq Scan on _hyper_45_86_chunk cagg_inval_1 (actual rows=0.00 loops=1)
3272- -> Seq Scan on _hyper_45_87_chunk cagg_inval_2 (actual rows=0.00 loops=1)
3340+ -> Seq Scan on _hyper_47_88_chunk cagg_inval_1 (actual rows=0.00 loops=1)
3341+ -> Seq Scan on _hyper_47_89_chunk cagg_inval_2 (actual rows=0.00 loops=1)
32733342
32743343ROLLBACK;
32753344ROLLBACK
@@ -3284,18 +3353,18 @@ EXPLAIN (analyze,costs off, timing off,summary off, buffers off) DELETE FROM cag
32843353 Batches scanned: 2
32853354 Batches deleted: 2
32863355 -> Delete on cagg_inval (actual rows=0.00 loops=1)
3287- Delete on _hyper_45_86_chunk cagg_inval_1
3288- Delete on _hyper_45_87_chunk cagg_inval_2
3356+ Delete on _hyper_47_88_chunk cagg_inval_1
3357+ Delete on _hyper_47_89_chunk cagg_inval_2
32893358 -> Append (actual rows=0.00 loops=1)
3290- -> Seq Scan on _hyper_45_86_chunk cagg_inval_1 (actual rows=0.00 loops=1)
3291- -> Seq Scan on _hyper_45_87_chunk cagg_inval_2 (actual rows=0.00 loops=1)
3359+ -> Seq Scan on _hyper_47_88_chunk cagg_inval_1 (actual rows=0.00 loops=1)
3360+ -> Seq Scan on _hyper_47_89_chunk cagg_inval_2 (actual rows=0.00 loops=1)
32923361
32933362-- should have invalidation entry from the direct batch delete
32943363SELECT * FROM _timescaledb_catalog.continuous_aggs_hypertable_invalidation_log ORDER BY 1,2;
32953364 hypertable_id | lowest_modified_value | greatest_modified_value
32963365---------------+-----------------------+-------------------------
3297- 45 | 1577865600000000 | 1577865600000000
3298- 45 | 1609488000000000 | 1609488000000000
3366+ 47 | 1577865600000000 | 1577865600000000
3367+ 47 | 1609488000000000 | 1609488000000000
32993368
33003369-- direct batch delete with time column as segmentby. Segmentby columns don't
33013370-- have _ts_meta_min/max, so the invalidation context must read the segmentby
0 commit comments