diff --git a/CHANGELOG.md b/CHANGELOG.md index b4f27230a..e80e6bd9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,9 @@ accidentally triggering the load of a previous DB version.** * #3769 Allow ALTER TABLE DROP COLUMN on compressed hypertable **Bugfixes** -* #3766 Fix segfault in ts_hist_sfunc * #3739 Fix compression policy on tables using INTEGER +* #3766 Fix segfault in ts_hist_sfunc +* #3789 Fix time_bucket comparison transformation **Thanks** * @cbisnett for reporting and fixing a typo in an error message diff --git a/src/plan_expand_hypertable.c b/src/plan_expand_hypertable.c index 89ca3db64..2237d9364 100644 --- a/src/plan_expand_hypertable.c +++ b/src/plan_expand_hypertable.c @@ -318,8 +318,8 @@ transform_time_bucket_comparison(PlannerInfo *root, OpExpr *op) TypeCacheEntry *tce; int strategy; - /* caller must ensure time_bucket only has 2 arguments */ - Assert(list_length(time_bucket->args) == 2); + if (list_length(time_bucket->args) != 2 || !IsA(value, Const) || !IsA(width, Const)) + return op; /* * if time_bucket call is on wrong side we switch operator @@ -359,11 +359,6 @@ transform_time_bucket_comparison(PlannerInfo *root, OpExpr *op) Datum datum; int64 integralValue, integralWidth; - /* - * caller should make sure value and width are Const - */ - Assert(IsA(value, Const) && IsA(width, Const)); - if (castNode(Const, value)->constisnull || width->constisnull) return op; diff --git a/test/expected/plan_expand_hypertable-12.out b/test/expected/plan_expand_hypertable-12.out index de609936f..2c972674c 100644 --- a/test/expected/plan_expand_hypertable-12.out +++ b/test/expected/plan_expand_hypertable-12.out @@ -1391,6 +1391,47 @@ time_bucket exclusion with timestamptz and day interval Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) (11 rows) +\qecho no transformation +no transformation +:PREFIX SELECT * FROM hyper WHERE time_bucket(10 + floor(random())::int, time) > 10 AND time_bucket(10 + floor(random())::int, time) < 100 AND time < 150 ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: hyper."time" + -> Custom Scan (ChunkAppend) on hyper + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_4_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_5_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_6_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_7_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_8_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_9_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_10_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_11_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_12_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_13_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_14_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_15_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) +(34 rows) + \qecho exclude chunks based on time column with partitioning function. This exclude chunks based on time column with partitioning function. This \qecho transparently applies the time partitioning function on the time diff --git a/test/expected/plan_expand_hypertable-13.out b/test/expected/plan_expand_hypertable-13.out index 2c62ceb41..16e46a768 100644 --- a/test/expected/plan_expand_hypertable-13.out +++ b/test/expected/plan_expand_hypertable-13.out @@ -1391,6 +1391,47 @@ time_bucket exclusion with timestamptz and day interval Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) (11 rows) +\qecho no transformation +no transformation +:PREFIX SELECT * FROM hyper WHERE time_bucket(10 + floor(random())::int, time) > 10 AND time_bucket(10 + floor(random())::int, time) < 100 AND time < 150 ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: hyper."time" + -> Custom Scan (ChunkAppend) on hyper + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_4_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_5_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_6_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_7_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_8_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_9_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_10_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_11_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_12_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_13_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_14_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_15_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) +(34 rows) + \qecho exclude chunks based on time column with partitioning function. This exclude chunks based on time column with partitioning function. This \qecho transparently applies the time partitioning function on the time diff --git a/test/expected/plan_expand_hypertable-14.out b/test/expected/plan_expand_hypertable-14.out index 2c62ceb41..16e46a768 100644 --- a/test/expected/plan_expand_hypertable-14.out +++ b/test/expected/plan_expand_hypertable-14.out @@ -1391,6 +1391,47 @@ time_bucket exclusion with timestamptz and day interval Filter: ((time_bucket('@ 1 day'::interval, "time") >= 'Mon Jan 03 00:00:00 2000 PST'::timestamp with time zone) AND (time_bucket('@ 7 days'::interval, "time") <= 'Mon Jan 10 00:00:00 2000 PST'::timestamp with time zone)) (11 rows) +\qecho no transformation +no transformation +:PREFIX SELECT * FROM hyper WHERE time_bucket(10 + floor(random())::int, time) > 10 AND time_bucket(10 + floor(random())::int, time) < 100 AND time < 150 ORDER BY time; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: hyper."time" + -> Custom Scan (ChunkAppend) on hyper + Chunks excluded during startup: 0 + -> Seq Scan on _hyper_1_1_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_2_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_3_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_4_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_5_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_6_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_7_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_8_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_9_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_10_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_11_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_12_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_13_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_14_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) + -> Seq Scan on _hyper_1_15_chunk + Filter: (("time" < 150) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") > 10) AND (time_bucket(((10 + (floor(random()))::integer))::bigint, "time") < 100)) +(34 rows) + \qecho exclude chunks based on time column with partitioning function. This exclude chunks based on time column with partitioning function. This \qecho transparently applies the time partitioning function on the time diff --git a/test/sql/include/plan_expand_hypertable_query.sql b/test/sql/include/plan_expand_hypertable_query.sql index b004d5748..e5cd954f3 100644 --- a/test/sql/include/plan_expand_hypertable_query.sql +++ b/test/sql/include/plan_expand_hypertable_query.sql @@ -202,6 +202,9 @@ SELECT * FROM cte ORDER BY value; :PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('1d',time) <= '2000-01-10' ORDER BY time; :PREFIX SELECT time FROM metrics_timestamptz WHERE time_bucket('1d',time) >= '2000-01-03' AND time_bucket('7d',time) <= '2000-01-10' ORDER BY time; +\qecho no transformation +:PREFIX SELECT * FROM hyper WHERE time_bucket(10 + floor(random())::int, time) > 10 AND time_bucket(10 + floor(random())::int, time) < 100 AND time < 150 ORDER BY time; + \qecho exclude chunks based on time column with partitioning function. This \qecho transparently applies the time partitioning function on the time \qecho value to be able to exclude chunks (similar to a closed dimension).