diff --git a/CHANGELOG.md b/CHANGELOG.md index 36cf8fc22..af75afc76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ accidentally triggering the load of a previous DB version.** * #5218 Add role-level security to job error log * #5214 Fix use of prepared statement in async module * #5290 Compression can't be enabled on continuous aggregates when segmentby/orderby columns need quotation +* #5239 Fix next_start calculation for fixed schedules ## 2.9.3 (2023-02-03) @@ -35,6 +36,7 @@ upgrade as soon as possible. * @ssmoss for reporting issues on continuous aggregates * @jaskij for reporting the compliation issue that occurred with clang + ## 2.9.2 (2023-01-26) This release contains bug fixes since the 2.9.1 release. diff --git a/src/bgw/job_stat.c b/src/bgw/job_stat.c index 246575def..6bb2b16c2 100644 --- a/src/bgw/job_stat.c +++ b/src/bgw/job_stat.c @@ -170,61 +170,105 @@ typedef struct } JobResultCtx; /* - * time_bucket(schedule_interval, finish_time, origin => initial_start) + * logic is the following + * Ideally we would return + * time_bucket(schedule_interval, finish_time, origin => initial_start, timezone). + * That is what we return when the schedule interval does not have month components. + * However, when there is a month component in the schedule interval, + * then supplying the origin in time_bucket + * does not work and the returned bucket is aligned on the start of the month. + * In those cases, we only have month components. So we compute the difference in + * months between the initial_start's timebucket and the finish time's bucket. */ static TimestampTz get_next_scheduled_execution_slot(BgwJob *job, TimestampTz finish_time) { Assert(job->fd.fixed_schedule == true); - Datum timebucket_fini, result, offset; Datum schedint_datum = IntervalPGetDatum(&job->fd.schedule_interval); + Datum timebucket_fini, timebucket_init, result; - if (job->fd.timezone == NULL) + Interval one_month = { + .day = 0, + .time = 0, + .month = 1, + }; + + if (job->fd.schedule_interval.month > 0) { - offset = DirectFunctionCall2(ts_timestamptz_bucket, - schedint_datum, - TimestampTzGetDatum(job->fd.initial_start)); + if (job->fd.timezone == NULL) + { + timebucket_init = DirectFunctionCall2(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(job->fd.initial_start)); + timebucket_fini = DirectFunctionCall2(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time)); + } + else + { + char *tz = text_to_cstring(job->fd.timezone); + timebucket_fini = DirectFunctionCall3(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + CStringGetTextDatum(tz)); - timebucket_fini = DirectFunctionCall3(ts_timestamptz_bucket, - schedint_datum, - TimestampTzGetDatum(finish_time), - TimestampTzGetDatum(job->fd.initial_start)); - /* always the next time_bucket */ - result = DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); + timebucket_init = DirectFunctionCall3(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(job->fd.initial_start), + CStringGetTextDatum(tz)); + } + /* always the next bucket */ + timebucket_fini = + DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); + /* get the number of months between them */ + Datum year_init = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("year"), timebucket_init); + Datum year_fini = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("year"), timebucket_fini); + + Datum month_init = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("month"), timebucket_init); + Datum month_fini = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("month"), timebucket_fini); + + /* convert everything to months */ + float8 month_diff = DatumGetFloat8(year_fini) * 12 + DatumGetFloat8(month_fini) - + (DatumGetFloat8(year_init) * 12 + DatumGetFloat8(month_init)); + + Datum months_to_add = DirectFunctionCall2(interval_mul, + IntervalPGetDatum(&one_month), + Float8GetDatum(month_diff)); + + result = DirectFunctionCall2(timestamptz_pl_interval, + TimestampTzGetDatum(job->fd.initial_start), + months_to_add); } else { - char *tz = text_to_cstring(job->fd.timezone); - timebucket_fini = DirectFunctionCall4(ts_timestamptz_timezone_bucket, - schedint_datum, - TimestampTzGetDatum(finish_time), - CStringGetTextDatum(tz), - TimestampTzGetDatum(job->fd.initial_start)); - /* always the next time_bucket */ - result = DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); - - offset = DirectFunctionCall3(ts_timestamptz_timezone_bucket, - schedint_datum, - TimestampTzGetDatum(job->fd.initial_start), - CStringGetTextDatum(tz)); + if (job->fd.timezone == NULL) + { + /* it is safe to use the origin in time_bucket calculation */ + timebucket_fini = DirectFunctionCall3(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + TimestampTzGetDatum(job->fd.initial_start)); + result = timebucket_fini; + } + else + { + char *tz = text_to_cstring(job->fd.timezone); + timebucket_fini = DirectFunctionCall4(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + CStringGetTextDatum(tz), + TimestampTzGetDatum(job->fd.initial_start)); + result = timebucket_fini; + } } - - offset = DirectFunctionCall2(timestamp_mi, TimestampTzGetDatum(job->fd.initial_start), offset); - /* if we have a month component, the origin doesn't work so we must manually - include the offset */ - if (job->fd.schedule_interval.month) - { - result = DirectFunctionCall2(timestamptz_pl_interval, result, offset); - } - /* - * adding the schedule interval above to get the next bucket might still not hit - * the next bucket if we are crossing DST. So we can end up with a next_start value - * that is actually less than the finish time of the job. Hence, we have to make sure - * the next scheduled slot we compute is in the future and not in the past - */ while (DatumGetTimestampTz(result) <= finish_time) + { result = DirectFunctionCall2(timestamptz_pl_interval, result, schedint_datum); - + } return DatumGetTimestampTz(result); } diff --git a/test/src/bgw/scheduler_mock.c b/test/src/bgw/scheduler_mock.c index cbccfc2ed..620f6fe5e 100644 --- a/test/src/bgw/scheduler_mock.c +++ b/test/src/bgw/scheduler_mock.c @@ -67,55 +67,89 @@ ts_test_next_scheduled_execution_slot(PG_FUNCTION_ARGS) TimestampTz initial_start = PG_GETARG_TIMESTAMPTZ(2); text *timezone = PG_ARGISNULL(3) ? NULL : PG_GETARG_TEXT_PP(3); - Datum timebucket_fini, result, offset; + Datum timebucket_fini, timebucket_init, result; Datum schedint_datum = IntervalPGetDatum(schedule_interval); + Interval one_month = { + .day = 0, + .time = 0, + .month = 1, + }; - if (timezone == NULL) + if (schedule_interval->month > 0) { - offset = DirectFunctionCall2(ts_timestamptz_bucket, - schedint_datum, - TimestampTzGetDatum(initial_start)); + if (timezone == NULL) + { + timebucket_init = DirectFunctionCall2(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(initial_start)); + timebucket_fini = DirectFunctionCall2(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time)); + } + else + { + char *tz = text_to_cstring(timezone); + timebucket_fini = DirectFunctionCall3(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + CStringGetTextDatum(tz)); - timebucket_fini = DirectFunctionCall3(ts_timestamptz_bucket, - schedint_datum, - TimestampTzGetDatum(finish_time), - TimestampTzGetDatum(initial_start)); - /* always the next time_bucket */ - result = DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); + timebucket_init = DirectFunctionCall3(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(initial_start), + CStringGetTextDatum(tz)); + } + /* always the next bucket */ + timebucket_fini = + DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); + /* get the number of months between them */ + Datum year_init = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("year"), timebucket_init); + Datum year_fini = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("year"), timebucket_fini); + + Datum month_init = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("month"), timebucket_init); + Datum month_fini = + DirectFunctionCall2(timestamptz_part, CStringGetTextDatum("month"), timebucket_fini); + + /* convert everything to months */ + float8 month_diff = DatumGetFloat8(year_fini) * 12 + DatumGetFloat8(month_fini) - + (DatumGetFloat8(year_init) * 12 + DatumGetFloat8(month_init)); + + Datum months_to_add = DirectFunctionCall2(interval_mul, + IntervalPGetDatum(&one_month), + Float8GetDatum(month_diff)); + result = DirectFunctionCall2(timestamptz_pl_interval, + TimestampTzGetDatum(initial_start), + months_to_add); } else { - char *tz = text_to_cstring(timezone); - timebucket_fini = DirectFunctionCall4(ts_timestamptz_timezone_bucket, - schedint_datum, - TimestampTzGetDatum(finish_time), - CStringGetTextDatum(tz), - TimestampTzGetDatum(initial_start)); - /* always the next time_bucket */ - result = DirectFunctionCall2(timestamptz_pl_interval, timebucket_fini, schedint_datum); - - offset = DirectFunctionCall3(ts_timestamptz_timezone_bucket, - schedint_datum, - TimestampTzGetDatum(initial_start), - CStringGetTextDatum(tz)); + if (timezone == NULL) + { + /* it is safe to use the origin in time_bucket calculation */ + timebucket_fini = DirectFunctionCall3(ts_timestamptz_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + TimestampTzGetDatum(initial_start)); + result = timebucket_fini; + } + else + { + char *tz = text_to_cstring(timezone); + timebucket_fini = DirectFunctionCall4(ts_timestamptz_timezone_bucket, + schedint_datum, + TimestampTzGetDatum(finish_time), + CStringGetTextDatum(tz), + TimestampTzGetDatum(initial_start)); + result = timebucket_fini; + } } - - offset = DirectFunctionCall2(timestamp_mi, TimestampTzGetDatum(initial_start), offset); - /* if we have a month component, the origin doesn't work so we must manually - include the offset */ - if (schedule_interval->month) - { - result = DirectFunctionCall2(timestamptz_pl_interval, result, offset); - } - /* - * adding the schedule interval above to get the next bucket might still not hit - * the next bucket if we are crossing DST. So we can end up with a next_start value - * that is actually less than the finish time of the job. Hence, we have to make sure - * the next scheduled slot we compute is in the future and not in the past - */ while (DatumGetTimestampTz(result) <= finish_time) + { result = DirectFunctionCall2(timestamptz_pl_interval, result, schedint_datum); - + } return result; } diff --git a/tsl/test/expected/fixed_schedules.out b/tsl/test/expected/fixed_schedules.out new file mode 100644 index 000000000..314cf4365 --- /dev/null +++ b/tsl/test/expected/fixed_schedules.out @@ -0,0 +1,807 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +select '2023-01-02 11:53:19.059771+02'::timestamptz as finish_time \gset +select :'finish_time'::timestamptz - interval '5 sec' as start_time \gset +-- years +select ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 yr", +ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 yr timezone", +ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "10 yr", +ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "10 yr timezone"; + 1 yr | 1 yr timezone | 10 yr | 10 yr timezone +-------------------------------------+-------------------------------------+-------------------------------------+------------------------------------- + Tue Jan 02 01:53:14.059771 2024 PST | Tue Jan 02 01:53:14.059771 2024 PST | Sun Jan 02 01:53:14.059771 2033 PST | Sun Jan 02 01:53:14.059771 2033 PST +(1 row) + +-- weeks +select ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 week", +ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 week timezone", +ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "2 week", +ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "2 week timezone"; + 1 week | 1 week timezone | 2 week | 2 week timezone +-------------------------------------+-------------------------------------+-------------------------------------+------------------------------------- + Mon Jan 09 01:53:14.059771 2023 PST | Mon Jan 09 01:53:14.059771 2023 PST | Mon Jan 16 01:53:14.059771 2023 PST | Mon Jan 16 01:53:14.059771 2023 PST +(1 row) + +-- months +select ts_test_next_scheduled_execution_slot('1 month', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 month", +ts_test_next_scheduled_execution_slot('1 month', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 month timezone", +ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "2 month", +ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "2 month timezone"; + 1 month | 1 month timezone | 2 month | 2 month timezone +-------------------------------------+-------------------------------------+-------------------------------------+------------------------------------- + Thu Feb 02 01:53:14.059771 2023 PST | Thu Feb 02 01:53:14.059771 2023 PST | Thu Mar 02 01:53:14.059771 2023 PST | Thu Mar 02 01:53:14.059771 2023 PST +(1 row) + +-- timezone in Berlin changes between 1 and 2 am +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 hour\'' +\set START_TIME_BEFORE_SUMMER_SWITCH 'TIMESTAMPTZ \'2022-03-27 01:00:00\'' +\set FINISH_TIME_AFTER_SUMMER_SWITCH 'TIMESTAMPTZ \'2022-03-27 01:19:20\'' +\set START_TIME_BEFORE_WINTER_SWITCH 'TIMESTAMPTZ \'2022-10-30 01:01:00\'' +\set FINISH_TIME_AFTER_WINTER_SWITCH 'TIMESTAMPTZ \'2022-10-30 01:10:19\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Mar 27 03:00:00 2022 CEST | Sun Mar 27 03:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Mar 27 04:00:00 2022 CEST | Sun Mar 27 04:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Mar 27 05:00:00 2022 CEST | Sun Mar 27 05:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Mar 27 06:00:00 2022 CEST | Sun Mar 27 06:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Mar 27 07:00:00 2022 CEST | Sun Mar 27 07:00:00 2022 CEST +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Oct 30 02:01:00 2022 CEST | Sun Oct 30 02:01:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Oct 30 02:01:00 2022 CET | Sun Oct 30 02:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Oct 30 03:01:00 2022 CET | Sun Oct 30 03:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Oct 30 04:01:00 2022 CET | Sun Oct 30 04:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Oct 30 05:00:00 2022 CET | Sun Oct 30 05:00:00 2022 CET +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 day\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Mon Mar 28 01:00:00 2022 CEST | Mon Mar 28 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Tue Mar 29 01:00:00 2022 CEST | Tue Mar 29 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Tue Mar 29 02:00:00 2022 CEST | Wed Mar 30 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Wed Mar 30 02:00:00 2022 CEST | Thu Mar 31 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Thu Mar 31 02:00:00 2022 CEST | Fri Apr 01 01:00:00 2022 CEST +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Mon Oct 31 01:01:00 2022 CET | Mon Oct 31 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Tue Nov 01 00:01:00 2022 CET | Tue Nov 01 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Nov 02 00:01:00 2022 CET | Wed Nov 02 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Thu Nov 03 00:01:00 2022 CET | Thu Nov 03 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Thu Nov 03 01:00:00 2022 CET | Fri Nov 04 01:00:00 2022 CET +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 week\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 03 01:00:00 2022 CEST | Sun Apr 03 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 10 01:00:00 2022 CEST | Sun Apr 10 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 10 02:00:00 2022 CEST | Sun Apr 17 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 17 02:00:00 2022 CEST | Sun Apr 24 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 24 02:00:00 2022 CEST | Sun May 01 01:00:00 2022 CEST +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 06 01:01:00 2022 CET | Sun Nov 06 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 13 00:01:00 2022 CET | Sun Nov 13 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 20 00:01:00 2022 CET | Sun Nov 20 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 27 00:01:00 2022 CET | Sun Nov 27 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 27 01:00:00 2022 CET | Sun Dec 04 01:00:00 2022 CET +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 month\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Wed Apr 27 01:00:00 2022 CEST | Wed Apr 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Fri May 27 01:00:00 2022 CEST | Fri May 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Mon Jun 27 01:00:00 2022 CEST | Mon Jun 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Wed Jul 27 01:00:00 2022 CEST | Wed Jul 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sat Aug 27 01:00:00 2022 CEST | Sat Aug 27 01:00:00 2022 CEST +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Nov 30 01:01:00 2022 CET | Wed Nov 30 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Dec 30 01:01:00 2022 CET | Fri Dec 30 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Mon Jan 30 01:01:00 2023 CET | Mon Jan 30 01:01:00 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Tue Feb 28 01:01:00 2023 CET | Tue Feb 28 01:01:00 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Mon Mar 27 01:00:00 2023 CEST | Mon Mar 27 01:00:00 2023 CEST +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 year\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 year\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Mon Mar 27 01:00:00 2023 CEST | Mon Mar 27 01:00:00 2023 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Mar 27 01:00:00 2024 CET | Wed Mar 27 01:00:00 2024 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Thu Mar 27 01:00:00 2025 CET | Thu Mar 27 01:00:00 2025 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Mar 27 01:00:00 2026 CET | Fri Mar 27 01:00:00 2026 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sat Mar 27 01:00:00 2027 CET | Sat Mar 27 01:00:00 2027 CET +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Mon Oct 30 01:01:00 2023 CET | Mon Oct 30 01:01:00 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Oct 30 01:01:00 2024 CET | Wed Oct 30 01:01:00 2024 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Thu Oct 30 01:01:00 2025 CET | Thu Oct 30 01:01:00 2025 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Oct 30 01:01:00 2026 CET | Fri Oct 30 01:01:00 2026 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sat Mar 27 01:00:00 2027 CET | Sat Mar 27 01:00:00 2027 CET +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'2 month\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'2 month\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Fri May 27 01:00:00 2022 CEST | Fri May 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Wed Jul 27 01:00:00 2022 CEST | Wed Jul 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Tue Sep 27 01:00:00 2022 CEST | Tue Sep 27 01:00:00 2022 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sun Nov 27 01:00:00 2022 CET | Sun Nov 27 01:00:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Jan 27 01:00:00 2023 CET | Fri Jan 27 01:00:00 2023 CET +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Dec 30 01:01:00 2022 CET | Fri Dec 30 01:01:00 2022 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Tue Feb 28 01:01:00 2023 CET | Tue Feb 28 01:01:00 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Sun Apr 30 01:01:00 2023 CEST | Sun Apr 30 01:01:00 2023 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Fri Jun 30 01:01:00 2023 CEST | Fri Jun 30 01:01:00 2023 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Thu Jul 27 01:00:00 2023 CEST | Thu Jul 27 01:00:00 2023 CEST +(1 row) + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'2 year\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'2 year\'' +\ir include/scheduler_fixed_common.sql +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. +\c :TEST_DBNAME :ROLE_SUPERUSER +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; +\set client_min_messages = DEBUG; +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; + initial_start_summer_switch | first_finish_time_summer_switch +------------------------------+--------------------------------- + Sun Mar 27 01:00:00 2022 CET | Sun Mar 27 01:19:20 2022 CET +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Mar 27 01:00:00 2024 CET | Wed Mar 27 01:00:00 2024 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Mar 27 01:00:00 2026 CET | Fri Mar 27 01:00:00 2026 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +-------------------------------+------------------------------- + Mon Mar 27 01:00:00 2028 CEST | Mon Mar 27 01:00:00 2028 CEST +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Mar 27 01:00:00 2030 CET | Wed Mar 27 01:00:00 2030 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sat Mar 27 01:00:00 2032 CET | Sat Mar 27 01:00:00 2032 CET +(1 row) + +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; + initial_start_winter_switch | first_finish_time_winter_switch +-------------------------------+--------------------------------- + Sun Oct 30 01:01:00 2022 CEST | Sun Oct 30 01:10:19 2022 CEST +(1 row) + +select :'t1' as without_timezone, :'t1_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Oct 30 01:01:00 2024 CET | Wed Oct 30 01:01:00 2024 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Fri Oct 30 01:01:00 2026 CET | Fri Oct 30 01:01:00 2026 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Mon Oct 30 01:01:00 2028 CET | Mon Oct 30 01:01:00 2028 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Wed Oct 30 01:01:00 2030 CET | Wed Oct 30 01:01:00 2030 CET +(1 row) + +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + without_timezone | with_timezone +------------------------------+------------------------------ + Sat Mar 27 01:00:00 2032 CET | Sat Mar 27 01:00:00 2032 CET +(1 row) + diff --git a/tsl/test/expected/scheduler_fixed.out b/tsl/test/expected/scheduler_fixed.out index e2e5883c7..e3068ffdd 100644 --- a/tsl/test/expected/scheduler_fixed.out +++ b/tsl/test/expected/scheduler_fixed.out @@ -194,3 +194,68 @@ select :'t3' as without_timezone, :'t3_tz' as with_timezone; -- test some unacceptable values for schedule interval select add_job('job_5', schedule_interval => interval '1 month 1week', initial_start => :'initial_start'::timestamptz); ERROR: month intervals cannot have day or time component +\set client_min_messages = DEBUG; +select '2023-01-02 11:53:19.059771+02'::timestamptz as finish_time \gset +-- years +select ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Tue Jan 02 10:53:16.059771 2024 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('2 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Thu Jan 02 10:53:16.059771 2025 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Sun Jan 02 10:53:16.059771 2033 CET +(1 row) + +-- weeks +select ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Mon Jan 09 10:53:16.059771 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Mon Jan 16 10:53:16.059771 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Mon Jan 16 10:53:16.059771 2023 CET +(1 row) + +-- months +select ts_test_next_scheduled_execution_slot('10 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Thu Nov 02 10:53:16.059771 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('10 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec', 'Europe/Athens'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Thu Nov 02 10:53:16.059771 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Thu Mar 02 10:53:16.059771 2023 CET +(1 row) + +select ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec', 'Europe/Athens'); + ts_test_next_scheduled_execution_slot +--------------------------------------- + Thu Mar 02 10:53:16.059771 2023 CET +(1 row) + diff --git a/tsl/test/sql/CMakeLists.txt b/tsl/test/sql/CMakeLists.txt index 06b4afd33..63ac4970b 100644 --- a/tsl/test/sql/CMakeLists.txt +++ b/tsl/test/sql/CMakeLists.txt @@ -95,7 +95,8 @@ if(CMAKE_BUILD_TYPE MATCHES Debug) remote_txn.sql transparent_decompression_queries.sql tsl_tables.sql - license_tsl.sql) + license_tsl.sql + fixed_schedules.sql) endif(CMAKE_BUILD_TYPE MATCHES Debug) if((${PG_VERSION_MAJOR} GREATER_EQUAL "14")) diff --git a/tsl/test/sql/fixed_schedules.sql b/tsl/test/sql/fixed_schedules.sql new file mode 100644 index 000000000..b50691861 --- /dev/null +++ b/tsl/test/sql/fixed_schedules.sql @@ -0,0 +1,64 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER + +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; + +\set client_min_messages = DEBUG; + +select '2023-01-02 11:53:19.059771+02'::timestamptz as finish_time \gset +select :'finish_time'::timestamptz - interval '5 sec' as start_time \gset + +-- years +select ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 yr", +ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 yr timezone", +ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "10 yr", +ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "10 yr timezone"; + +-- weeks +select ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 week", +ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 week timezone", +ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "2 week", +ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "2 week timezone"; + +-- months +select ts_test_next_scheduled_execution_slot('1 month', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "1 month", +ts_test_next_scheduled_execution_slot('1 month', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "1 month timezone", +ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'start_time'::timestamptz) as "2 month", +ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'start_time'::timestamptz, 'Europe/Athens') as "2 month timezone"; + +-- timezone in Berlin changes between 1 and 2 am +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 hour\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 hour\'' +\set START_TIME_BEFORE_SUMMER_SWITCH 'TIMESTAMPTZ \'2022-03-27 01:00:00\'' +\set FINISH_TIME_AFTER_SUMMER_SWITCH 'TIMESTAMPTZ \'2022-03-27 01:19:20\'' +\set START_TIME_BEFORE_WINTER_SWITCH 'TIMESTAMPTZ \'2022-10-30 01:01:00\'' +\set FINISH_TIME_AFTER_WINTER_SWITCH 'TIMESTAMPTZ \'2022-10-30 01:10:19\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 day\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 day\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 week\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 week\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 month\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 month\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'1 year\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'1 year\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'2 month\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'2 month\'' +\ir include/scheduler_fixed_common.sql + +\set BUCKET_WIDTH_WINTER_SUMMER 'INTERVAL \'2 year\'' +\set BUCKET_WIDTH_SUMMER_WINTER 'INTERVAL \'2 year\'' +\ir include/scheduler_fixed_common.sql diff --git a/tsl/test/sql/include/scheduler_fixed_common.sql b/tsl/test/sql/include/scheduler_fixed_common.sql new file mode 100644 index 000000000..6998493c3 --- /dev/null +++ b/tsl/test/sql/include/scheduler_fixed_common.sql @@ -0,0 +1,51 @@ +-- This file and its contents are licensed under the Timescale License. +-- Please see the included NOTICE for copyright information and +-- LICENSE-TIMESCALE for a copy of the license. + +\c :TEST_DBNAME :ROLE_SUPERUSER + +CREATE OR REPLACE FUNCTION ts_test_next_scheduled_execution_slot(schedule_interval INTERVAL, finish_time TIMESTAMPTZ, initial_start TIMESTAMPTZ, timezone TEXT = NULL) +RETURNS TIMESTAMPTZ AS :MODULE_PATHNAME LANGUAGE C VOLATILE; + +\set client_min_messages = DEBUG; + +-- test what happens across DST +-- go from +1 to +2 +set timezone to 'Europe/Berlin'; +-- DST switch on March 27th 2022, in particular, between 1am and 2 am (old time) +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :FINISH_TIME_AFTER_SUMMER_SWITCH, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_SUMMER_SWITCH as initial_start_summer_switch, :FINISH_TIME_AFTER_SUMMER_SWITCH as first_finish_time_summer_switch; +select :'t1' as without_timezone, :'t1_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; +--------- and then +2 to +1 +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH) as t1 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :FINISH_TIME_AFTER_WINTER_SWITCH, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') +as t1_tz \gset +select :START_TIME_BEFORE_WINTER_SWITCH as initial_start_winter_switch, :FINISH_TIME_AFTER_WINTER_SWITCH as first_finish_time_winter_switch; +select :'t1' as without_timezone, :'t1_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t2 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t1_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t2_tz \gset +select :'t2' as without_timezone, :'t2_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t3 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t2_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, timezone => 'Europe/Berlin') as t3_tz \gset +select :'t3' as without_timezone, :'t3_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH) as t4 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_SUMMER_WINTER, :'t3_tz'::timestamptz, :START_TIME_BEFORE_WINTER_SWITCH, 'Europe/Berlin') as t4_tz \gset +select :'t4' as without_timezone, :'t4_tz' as with_timezone; +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH) as t5 \gset +select ts_test_next_scheduled_execution_slot(:BUCKET_WIDTH_WINTER_SUMMER, :'t4_tz'::timestamptz, :START_TIME_BEFORE_SUMMER_SWITCH, 'Europe/Berlin') as t5_tz \gset +select :'t5' as without_timezone, :'t5_tz' as with_timezone; + diff --git a/tsl/test/sql/scheduler_fixed.sql b/tsl/test/sql/scheduler_fixed.sql index e5ed50f0b..f5874e509 100644 --- a/tsl/test/sql/scheduler_fixed.sql +++ b/tsl/test/sql/scheduler_fixed.sql @@ -122,3 +122,21 @@ select :'t3' as without_timezone, :'t3_tz' as with_timezone; \set ON_ERROR_STOP 0 -- test some unacceptable values for schedule interval select add_job('job_5', schedule_interval => interval '1 month 1week', initial_start => :'initial_start'::timestamptz); + +\set client_min_messages = DEBUG; + +select '2023-01-02 11:53:19.059771+02'::timestamptz as finish_time \gset + +-- years +select ts_test_next_scheduled_execution_slot('1 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('2 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('10 year', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +-- weeks +select ts_test_next_scheduled_execution_slot('1 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('2 week', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +-- months +select ts_test_next_scheduled_execution_slot('10 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('10 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec', 'Europe/Athens'); +select ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec'); +select ts_test_next_scheduled_execution_slot('2 month', :'finish_time'::timestamptz, :'finish_time'::timestamptz - interval '3 sec', 'Europe/Athens'); diff --git a/tsl/test/t/006_job_crash_log.pl b/tsl/test/t/006_job_crash_log.pl index e7f43623a..a9576026d 100644 --- a/tsl/test/t/006_job_crash_log.pl +++ b/tsl/test/t/006_job_crash_log.pl @@ -5,7 +5,7 @@ use strict; use warnings; use TimescaleNode; -use Test::More tests => 4; +use Test::More tests => 5; # This test checks that a job crash is reported in the job errors table # (that is, a record gets inserted into the table _timescaledb_internal.job_errors). @@ -40,14 +40,20 @@ my $query_add = my $jobid = $node->safe_psql('postgres', "$query_add"); is($jobid, '1000', 'job was added'); -# sleep 10 to make sure job has started running -$node->safe_psql('postgres', "select pg_sleep(10)"); +my $query_pid_exists = <<"END_OF_QUERY"; +select count(*) from pg_stat_activity +where application_name like 'User-Defined Action%' + and query like '%custom_proc_sleep60%' +END_OF_QUERY # select the pid of this job in order to kill it my $query_pid = <<"END_OF_QUERY"; select pid from pg_stat_activity where application_name like 'User-Defined Action%' and query like '%custom_proc_sleep60%' END_OF_QUERY + +ok($node->poll_query_until('postgres', "$query_pid_exists", '1')); + my $pid = $node->safe_psql('postgres', "$query_pid"); isnt($pid, "", "check the pid is not null"); # now kill the one backend