mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
Fix time_bucket comparison transformation
The time_bucket comparison transformation code assumed the value and the width of the time_bucket comparison expression were both Const. But this was not validated only asserted. This can lead to wrong query results. Found by sqlsmith.
This commit is contained in:
parent
0f5268ad49
commit
7591f7f1f3
@ -11,8 +11,9 @@ accidentally triggering the load of a previous DB version.**
|
|||||||
* #3769 Allow ALTER TABLE DROP COLUMN on compressed hypertable
|
* #3769 Allow ALTER TABLE DROP COLUMN on compressed hypertable
|
||||||
|
|
||||||
**Bugfixes**
|
**Bugfixes**
|
||||||
* #3766 Fix segfault in ts_hist_sfunc
|
|
||||||
* #3739 Fix compression policy on tables using INTEGER
|
* #3739 Fix compression policy on tables using INTEGER
|
||||||
|
* #3766 Fix segfault in ts_hist_sfunc
|
||||||
|
* #3789 Fix time_bucket comparison transformation
|
||||||
|
|
||||||
**Thanks**
|
**Thanks**
|
||||||
* @cbisnett for reporting and fixing a typo in an error message
|
* @cbisnett for reporting and fixing a typo in an error message
|
||||||
|
@ -318,8 +318,8 @@ transform_time_bucket_comparison(PlannerInfo *root, OpExpr *op)
|
|||||||
TypeCacheEntry *tce;
|
TypeCacheEntry *tce;
|
||||||
int strategy;
|
int strategy;
|
||||||
|
|
||||||
/* caller must ensure time_bucket only has 2 arguments */
|
if (list_length(time_bucket->args) != 2 || !IsA(value, Const) || !IsA(width, Const))
|
||||||
Assert(list_length(time_bucket->args) == 2);
|
return op;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if time_bucket call is on wrong side we switch operator
|
* 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;
|
Datum datum;
|
||||||
int64 integralValue, integralWidth;
|
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)
|
if (castNode(Const, value)->constisnull || width->constisnull)
|
||||||
return op;
|
return op;
|
||||||
|
|
||||||
|
@ -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))
|
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)
|
(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
|
\qecho exclude chunks based on time column with partitioning function. This
|
||||||
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
|
\qecho transparently applies the time partitioning function on the time
|
||||||
|
@ -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))
|
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)
|
(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
|
\qecho exclude chunks based on time column with partitioning function. This
|
||||||
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
|
\qecho transparently applies the time partitioning function on the time
|
||||||
|
@ -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))
|
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)
|
(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
|
\qecho exclude chunks based on time column with partitioning function. This
|
||||||
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
|
\qecho transparently applies the time partitioning function on the time
|
||||||
|
@ -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('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;
|
: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 exclude chunks based on time column with partitioning function. This
|
||||||
\qecho transparently applies the time partitioning function on the time
|
\qecho transparently applies the time partitioning function on the time
|
||||||
\qecho value to be able to exclude chunks (similar to a closed dimension).
|
\qecho value to be able to exclude chunks (similar to a closed dimension).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user