From 0ff29aa61671ece2ba16caade51d418ec3cc6c29 Mon Sep 17 00:00:00 2001 From: Nikhil Sontakke Date: Tue, 2 Apr 2024 12:42:32 +0530 Subject: [PATCH] Fix a crash involving a view on a hypertable The logic in chunk append path creation when a space dimension was involved was crashing while checking for matches in the flattened out children chunk lists. This has been fixed now. --- .unreleased/bugfix_6796 | 1 + src/nodes/chunk_append/chunk_append.c | 7 +++-- test/expected/chunk_utils.out | 45 +++++++++++++++++++++++++++ test/sql/chunk_utils.sql | 17 ++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 .unreleased/bugfix_6796 diff --git a/.unreleased/bugfix_6796 b/.unreleased/bugfix_6796 new file mode 100644 index 00000000000..d9e4b2b7831 --- /dev/null +++ b/.unreleased/bugfix_6796 @@ -0,0 +1 @@ +Fixes: #6796 Fix a crash involving a view on a hypertable diff --git a/src/nodes/chunk_append/chunk_append.c b/src/nodes/chunk_append/chunk_append.c index 8804ca05fef..e940d7ddb21 100644 --- a/src/nodes/chunk_append/chunk_append.c +++ b/src/nodes/chunk_append/chunk_append.c @@ -348,9 +348,6 @@ ts_chunk_append_path_create(PlannerInfo *root, RelOptInfo *rel, Hypertable *ht, List *merge_childs = NIL; MergeAppendPath *append; - if (flat == NULL) - break; - /* * For each lc_oid, there will be 0, 1, or 2 matches in flat_list: 0 matches * if child was pruned, 1 match if the chunk is uncompressed or fully compressed, @@ -363,6 +360,10 @@ ts_chunk_append_path_create(PlannerInfo *root, RelOptInfo *rel, Hypertable *ht, #ifdef USE_ASSERT_CHECKING int nmatches = 0; #endif + /* Before entering the "DO" loop, check for a valid path entry */ + if (flat == NULL) + break; + do { Path *child = (Path *) lfirst(flat); diff --git a/test/expected/chunk_utils.out b/test/expected/chunk_utils.out index acaff39e22c..8cf240bb6c5 100644 --- a/test/expected/chunk_utils.out +++ b/test/expected/chunk_utils.out @@ -1556,3 +1556,48 @@ SELECT drop_chunks('drop_chunk_test_ts', created_after => INTERVAL '1 hour', cre _timescaledb_internal._hyper_4_20_chunk (2 rows) +-- Test views on top of hypertables +CREATE TABLE view_test (project_id INT, ts TIMESTAMPTZ NOT NULL); +SELECT create_hypertable('view_test', by_range('ts', INTERVAL '1 day')); + create_hypertable +------------------- + (17,t) +(1 row) + +-- exactly one partition per project_id +SELECT * FROM add_dimension('view_test', 'project_id', chunk_time_interval => 1); -- exactly one partition per project; works for *integer* types +NOTICE: adding not-null constraint to column "project_id" + dimension_id | schema_name | table_name | column_name | created +--------------+-------------+------------+-------------+--------- + 22 | try_schema | view_test | project_id | t +(1 row) + +INSERT INTO view_test (project_id, ts) +SELECT g % 25 + 1 AS project_id, i.ts + (g * interval '1 week') / i.total AS ts +FROM (SELECT timestamptz '2024-01-01 00:00:00+0', 600) i(ts, total), +generate_series(1, i.total) g; +-- Create a view on top of this hypertable +CREATE VIEW test_view_part_few AS SELECT project_id, + ts + FROM view_test + WHERE project_id = ANY (ARRAY[5, 10, 15]); +-- Complicated query on a view involving a range check and a sort +SELECT * FROM test_view_part_few WHERE ts BETWEEN '2024-01-04 00:00:00+00'AND '2024-01-05 00:00:00' ORDER BY ts LIMIT 1000; + project_id | ts +------------+------------------------------ + 10 | Wed Jan 03 16:31:12 2024 PST + 15 | Wed Jan 03 17:55:12 2024 PST + 5 | Wed Jan 03 22:07:12 2024 PST + 10 | Wed Jan 03 23:31:12 2024 PST + 15 | Thu Jan 04 00:55:12 2024 PST + 5 | Thu Jan 04 05:07:12 2024 PST + 10 | Thu Jan 04 06:31:12 2024 PST + 15 | Thu Jan 04 07:55:12 2024 PST + 5 | Thu Jan 04 12:07:12 2024 PST + 10 | Thu Jan 04 13:31:12 2024 PST + 15 | Thu Jan 04 14:55:12 2024 PST + 5 | Thu Jan 04 19:07:12 2024 PST + 10 | Thu Jan 04 20:31:12 2024 PST + 15 | Thu Jan 04 21:55:12 2024 PST +(14 rows) + diff --git a/test/sql/chunk_utils.sql b/test/sql/chunk_utils.sql index 8086d67e061..cc52782051c 100644 --- a/test/sql/chunk_utils.sql +++ b/test/sql/chunk_utils.sql @@ -655,3 +655,20 @@ SELECT show_chunks('drop_chunk_test_ts'); -- timestamp SELECT show_chunks('drop_chunk_test_ts', created_after => now() - INTERVAL '1 hour', created_before => now()); SELECT drop_chunks('drop_chunk_test_ts', created_after => INTERVAL '1 hour', created_before => now()); + +-- Test views on top of hypertables +CREATE TABLE view_test (project_id INT, ts TIMESTAMPTZ NOT NULL); +SELECT create_hypertable('view_test', by_range('ts', INTERVAL '1 day')); +-- exactly one partition per project_id +SELECT * FROM add_dimension('view_test', 'project_id', chunk_time_interval => 1); -- exactly one partition per project; works for *integer* types +INSERT INTO view_test (project_id, ts) +SELECT g % 25 + 1 AS project_id, i.ts + (g * interval '1 week') / i.total AS ts +FROM (SELECT timestamptz '2024-01-01 00:00:00+0', 600) i(ts, total), +generate_series(1, i.total) g; +-- Create a view on top of this hypertable +CREATE VIEW test_view_part_few AS SELECT project_id, + ts + FROM view_test + WHERE project_id = ANY (ARRAY[5, 10, 15]); +-- Complicated query on a view involving a range check and a sort +SELECT * FROM test_view_part_few WHERE ts BETWEEN '2024-01-04 00:00:00+00'AND '2024-01-05 00:00:00' ORDER BY ts LIMIT 1000;