Skip to content

Commit

Permalink
Fix delete on tables involving hypertables with compression
Browse files Browse the repository at this point in the history
The DML blocker to block INSERTs and UPDATEs on compressed hypertables
would trigger if the UPDATE or DELETE referenced any hypertable with
compressed chunks. This patch changes the logic to only block if the
target of the UPDATE or DELETE is a compressed hypertable.
  • Loading branch information
svenklemm committed Jul 16, 2020
1 parent 8801781 commit f93f87c
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 3 deletions.
14 changes: 13 additions & 1 deletion src/planner.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,18 @@ valid_hook_call(void)
return ts_extension_is_loaded() && planner_hcache_exists();
}

static bool
dml_involves_hypertable(PlannerInfo *root, Hypertable *ht, Index rti)
{
Index result_rti = root->parse->resultRelation;
RangeTblEntry *result_rte = root->simple_rte_array[result_rti];

if (result_rti == rti || ht->main_table_relid == result_rte->relid)
return true;

return false;
}

static void
timescaledb_set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte)
{
Expand Down Expand Up @@ -763,7 +775,7 @@ timescaledb_set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, Rang
case TS_REL_CHUNK:
case TS_REL_CHUNK_CHILD:
/* Check for UPDATE/DELETE (DLM) on compressed chunks */
if (IS_UPDL_CMD(root->parse))
if (IS_UPDL_CMD(root->parse) && dml_involves_hypertable(root, ht, rti))
{
if (ts_cm_functions->set_rel_pathlist_dml != NULL)
ts_cm_functions->set_rel_pathlist_dml(root, rel, rti, rte, ht);
Expand Down
6 changes: 4 additions & 2 deletions tsl/src/nodes/decompress_chunk/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,10 @@ constify_tableoid_walker(Node *node, ConstifyTableOidContext *ctx)
* we doublecheck system columns here because projection will
* segfault if any system columns get through
*/
if (var->varattno < 0)
elog(ERROR, "transparent decompression only supports tableoid system column");
if (var->varattno < SelfItemPointerAttributeNumber)
elog(ERROR,
"transparent decompression only supports tableoid system column %d",
var->varattno);

return node;
}
Expand Down
55 changes: 55 additions & 0 deletions tsl/test/expected/compression.out
Original file line number Diff line number Diff line change
Expand Up @@ -1124,3 +1124,58 @@ ERROR: constraint "fk_table1" requires column "col2" to be a timescaledb.compre
ALTER TABLE table1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'col1,col2');
NOTICE: adding index _compressed_hypertable_23_col1__ts_meta_sequence_num_idx ON _timescaledb_internal._compressed_hypertable_23 USING BTREE(col1, _ts_meta_sequence_num)
NOTICE: adding index _compressed_hypertable_23_col2__ts_meta_sequence_num_idx ON _timescaledb_internal._compressed_hypertable_23 USING BTREE(col2, _ts_meta_sequence_num)
-- test delete non-compressed tables involving hypertables with compression
CREATE TABLE delete_ht1 (
time timestamptz NOT NULL,
value double precision,
series_id integer
);
SELECT table_name FROM create_hypertable ('delete_ht1', 'time');
table_name
------------
delete_ht1
(1 row)

INSERT INTO delete_ht1
VALUES ('2020-04-20 01:01', 100, 1), ('2020-05-20 01:01', 100, 1), ('2020-04-20 01:01', 200, 2);
CREATE TABLE delete_ht2 (
time timestamptz NOT NULL,
value double precision,
series_id integer
);
SELECT table_name FROM create_hypertable ('delete_ht2', 'time');
table_name
------------
delete_ht2
(1 row)

ALTER TABLE delete_ht2 SET (timescaledb.compress);
INSERT INTO delete_ht2
VALUES ('2020-04-20 01:01', 100, 1), ('2020-05-20 01:01', 100, 1);
SELECT
compress_chunk (ch1.schema_name || '.' || ch1.table_name)
FROM
_timescaledb_catalog.chunk ch1,
_timescaledb_catalog.hypertable ht
WHERE
ch1.hypertable_id = ht.id
AND ht.table_name LIKE 'delete_ht2'
ORDER BY
ch1.id;
compress_chunk
------------------------------------------
_timescaledb_internal._hyper_25_51_chunk
_timescaledb_internal._hyper_25_52_chunk
(2 rows)

WITH confirmed_drop_series AS (
SELECT
series_id
FROM
delete_ht2 data_exists
WHERE
time >= '2020-04-17 17:14:24.161989+00'
)
DELETE FROM delete_ht1
WHERE
series_id IN (SELECT series_id FROM confirmed_drop_series);
48 changes: 48 additions & 0 deletions tsl/test/sql/compression.sql
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,51 @@ ALTER TABLE table1 SET (timescaledb.compress, timescaledb.compress_segmentby = '
-- Listing all fields of the compound key should succeed:
ALTER TABLE table1 SET (timescaledb.compress, timescaledb.compress_segmentby = 'col1,col2');

-- test delete non-compressed tables involving hypertables with compression
CREATE TABLE delete_ht1 (
time timestamptz NOT NULL,
value double precision,
series_id integer
);

SELECT table_name FROM create_hypertable ('delete_ht1', 'time');

INSERT INTO delete_ht1
VALUES ('2020-04-20 01:01', 100, 1), ('2020-05-20 01:01', 100, 1), ('2020-04-20 01:01', 200, 2);

CREATE TABLE delete_ht2 (
time timestamptz NOT NULL,
value double precision,
series_id integer
);

SELECT table_name FROM create_hypertable ('delete_ht2', 'time');

ALTER TABLE delete_ht2 SET (timescaledb.compress);

INSERT INTO delete_ht2
VALUES ('2020-04-20 01:01', 100, 1), ('2020-05-20 01:01', 100, 1);

SELECT
compress_chunk (ch1.schema_name || '.' || ch1.table_name)
FROM
_timescaledb_catalog.chunk ch1,
_timescaledb_catalog.hypertable ht
WHERE
ch1.hypertable_id = ht.id
AND ht.table_name LIKE 'delete_ht2'
ORDER BY
ch1.id;

WITH confirmed_drop_series AS (
SELECT
series_id
FROM
delete_ht2 data_exists
WHERE
time >= '2020-04-17 17:14:24.161989+00'
)
DELETE FROM delete_ht1
WHERE
series_id IN (SELECT series_id FROM confirmed_drop_series);

0 comments on commit f93f87c

Please sign in to comment.