Skip to content

Commit

Permalink
Fix compressed DML with constraints of form value OP column
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
svenklemm committed Apr 28, 2024
1 parent a7890e6 commit b7d5a46
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
9 changes: 8 additions & 1 deletion tsl/src/compression/compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Check warning on line 2581 in tsl/src/compression/compression.c

View check run for this annotation

Codecov / codecov/patch

tsl/src/compression/compression.c#L2581

Added line #L2581 was not covered by tests
opcode = get_opcode(opno);
if (!OidIsValid(opcode))
continue;

Check warning on line 2584 in tsl/src/compression/compression.c

View check run for this annotation

Codecov / codecov/patch

tsl/src/compression/compression.c#L2584

Added line #L2584 was not covered by tests
}
else
continue;
Expand All @@ -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)
Expand Down
55 changes: 55 additions & 0 deletions tsl/test/expected/compression_update_delete.out
Original file line number Diff line number Diff line change
Expand Up @@ -2944,3 +2944,58 @@ 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 '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 '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)

14 changes: 14 additions & 0 deletions tsl/test/sql/compression_update_delete.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1493,3 +1493,17 @@ 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 'c' > device; ROLLBACK;
BEGIN; EXPLAIN (costs off, timing off, summary off, analyze) DELETE FROM test_commutator WHERE 'b' < device; ROLLBACK;

0 comments on commit b7d5a46

Please sign in to comment.