Fix compressed DML with constraints of form value OP column

UPDATE/DELETE operations with constraints where the column is on the
right side of the expression and the value on the left side e.g.
'a' > column were not handled correctly when operating on compressed chunks.
This commit is contained in:
Sven Klemm 2024-04-28 18:56:02 +02:00 committed by Sven Klemm
parent a7890e6411
commit 396dd0cb11
4 changed files with 130 additions and 1 deletions

1
.unreleased/pr_6869 Normal file
View File

@ -0,0 +1 @@
Fixes: #6869 Fix compressed DML with constraints of form value OP column

View File

@ -2553,6 +2553,7 @@ fill_predicate_context(Chunk *ch, CompressionSettings *settings, List *predicate
case T_OpExpr:
{
OpExpr *opexpr = (OpExpr *) node;
Oid opno = opexpr->opno;
RegProcedure opcode = opexpr->opfuncid;
Oid collation = opexpr->inputcollid;
Expr *leftop, *rightop;
@ -2575,6 +2576,12 @@ fill_predicate_context(Chunk *ch, CompressionSettings *settings, List *predicate
{
var = (Var *) rightop;
arg_value = (Const *) leftop;
opno = get_commutator(opno);
if (!OidIsValid(opno))
continue;
opcode = get_opcode(opno);
if (!OidIsValid(opcode))
continue;
}
else
continue;
@ -2584,7 +2591,7 @@ fill_predicate_context(Chunk *ch, CompressionSettings *settings, List *predicate
continue;
column_name = get_attname(ch->table_id, var->varattno, false);
TypeCacheEntry *tce = lookup_type_cache(var->vartype, TYPECACHE_BTREE_OPFAMILY);
int op_strategy = get_op_opfamily_strategy(opexpr->opno, tce->btree_opf);
int op_strategy = get_op_opfamily_strategy(opno, tce->btree_opf);
if (ts_array_is_member(settings->fd.segmentby, column_name))
{
switch (op_strategy)

View File

@ -2944,3 +2944,106 @@ EXPLAIN (analyze, timing off, costs off, summary off) DELETE FROM test_meta_filt
Rows Removed by Filter: 10
(8 rows)
-- test commutator handling in compressed dml constraints
CREATE TABLE test_commutator(time timestamptz NOT NULL, device text);
SELECT table_name FROM create_hypertable('test_commutator', 'time');
table_name
-----------------
test_commutator
(1 row)
INSERT INTO test_commutator SELECT '2020-01-01', 'a';
INSERT INTO test_commutator SELECT '2020-01-01', 'b';
INSERT INTO test_commutator SELECT '2020-01-01', 'c';
ALTER TABLE test_commutator SET (timescaledb.compress, timescaledb.compress_segmentby='device');
NOTICE: default order by for hypertable "test_commutator" is set to ""time" DESC"
SELECT compress_chunk(show_chunks('test_commutator'));
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_39_79_chunk
(1 row)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'a' = device; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 1
Tuples decompressed: 1
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=1 loops=1)
Filter: ('a'::text = device)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE device < 'c' ; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 2
Tuples decompressed: 2
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=2 loops=1)
Filter: (device < 'c'::text)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'c' > device; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 2
Tuples decompressed: 2
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=2 loops=1)
Filter: ('c'::text > device)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'c' >= device; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 3
Tuples decompressed: 3
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=3 loops=1)
Filter: ('c'::text >= device)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE device > 'b'; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 1
Tuples decompressed: 1
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=1 loops=1)
Filter: (device > 'b'::text)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'b' < device; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 1
Tuples decompressed: 1
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=1 loops=1)
Filter: ('b'::text < device)
(7 rows)
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'b' <= device; ROLLBACK;
QUERY PLAN
--------------------------------------------------------------------------------------
Custom Scan (HypertableModify) (actual rows=0 loops=1)
Batches decompressed: 2
Tuples decompressed: 2
-> Delete on test_commutator (actual rows=0 loops=1)
Delete on _hyper_39_79_chunk test_commutator_1
-> Seq Scan on _hyper_39_79_chunk test_commutator_1 (actual rows=2 loops=1)
Filter: ('b'::text <= device)
(7 rows)

View File

@ -1493,3 +1493,21 @@ SELECT compress_chunk(show_chunks('test_meta_filters'));
EXPLAIN (analyze, timing off, costs off, summary off) DELETE FROM test_meta_filters WHERE device = 'd1' AND metric = 'm1' AND v1 < 100;
-- test commutator handling in compressed dml constraints
CREATE TABLE test_commutator(time timestamptz NOT NULL, device text);
SELECT table_name FROM create_hypertable('test_commutator', 'time');
INSERT INTO test_commutator SELECT '2020-01-01', 'a';
INSERT INTO test_commutator SELECT '2020-01-01', 'b';
INSERT INTO test_commutator SELECT '2020-01-01', 'c';
ALTER TABLE test_commutator SET (timescaledb.compress, timescaledb.compress_segmentby='device');
SELECT compress_chunk(show_chunks('test_commutator'));
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'a' = device; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE device < 'c' ; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'c' > device; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'c' >= device; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE device > 'b'; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'b' < device; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'b' <= device; ROLLBACK;