Skip to content

Commit

Permalink
Fix Datapart functions to be Timezone Invariant (babelfish-for-postgr…
Browse files Browse the repository at this point in the history
…esql#3226)

We were incorrectly passing timezone to timestamp2tm function which would cause the datepart functions to be timezone dependent , If we pass tzp by reference to timestamp2tm function, then internally localtime converts the given original timestamp value to date and time values adding timezone offset taking GMT as a reference timezone. However, if NULL is passed instead then we keep the original timestamp intact and that's what actually PG does.

Issues Resolved
BABEL-5453

Signed-off-by: Nirmit Shah [email protected]
  • Loading branch information
shah-nirmit authored Dec 13, 2024
1 parent 3c85d27 commit 5a092d3
Show file tree
Hide file tree
Showing 7 changed files with 2,141 additions and 2 deletions.
3 changes: 1 addition & 2 deletions contrib/babelfishpg_tsql/runtime/functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,6 @@ datepart_internal(char* field, Timestamp timestamp, float8 df_tz, bool general_i
Timestamp tsql_first_day, first_day;
struct pg_tm tt1, *tm = &tt1;
uint first_week_end, year, month, day, res = 0, day_of_year; /* for Zeller's Congruence */
int tz1;

/*
* This block is used when the second argument in datepart is not a
Expand All @@ -396,7 +395,7 @@ datepart_internal(char* field, Timestamp timestamp, float8 df_tz, bool general_i
}

/* Gets the date time related fields back from timestamp into struct tm pointer */
if (timestamp2tm(timestamp, &tz1, tm, &fsec1, NULL, NULL) != 0)
if (timestamp2tm(timestamp, NULL, tm, &fsec1, NULL, NULL) != 0)
{
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
Expand Down
3 changes: 3 additions & 0 deletions test/JDBC/expected/datepart-vu-cleanup.out
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ GO

DROP PROCEDURE date_part_vu_prepare_sys_day_proc
GO

DROP TABLE date_part_vu_prepare_TestDates, date_part_vu_prepare_TestTimezones, date_part_vu_prepare_TestResults, date_part_vu_prepare_DateParts;
GO
44 changes: 44 additions & 0 deletions test/JDBC/expected/datepart-vu-prepare.out
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,47 @@ CREATE PROCEDURE date_part_vu_prepare_sys_day_proc @a datetime
AS
SELECT DAY(@a)
GO

-- Test Case for Date Part Functions Timezone Invariance
CREATE TABLE date_part_vu_prepare_DateParts (DatePartName VARCHAR(20));
GO
CREATE TABLE date_part_vu_prepare_TestDates (
TestDateTime DATETIME,
TestDateTimeOffset DATETIMEOFFSET,
TestDateTime2 DATETIME2,
TestSmallDateTime SMALLDATETIME
);
GO
CREATE TABLE date_part_vu_prepare_TestTimezones (TimezoneName VARCHAR(50));
GO
CREATE TABLE date_part_vu_prepare_TestResults (
TestCase VARCHAR(100),
TimeZone VARCHAR(50),
DataType VARCHAR(20),
InputDate VARCHAR(50),
DatePart VARCHAR(20),
DatePartValue SQL_VARIANT,
DateName NVARCHAR(100)
);
GO

-- -- Populate tables
INSERT INTO date_part_vu_prepare_DateParts (DatePartName) VALUES
('year'), ('quarter'), ('month'), ('dayofyear'), ('day'),
('week'), ('weekday'), ('hour'), ('minute'), ('second'),
('millisecond'), ('microsecond'), ('nanosecond'),
('tzoffset'), ('iso_week');
GO
~~ROW COUNT: 15~~

INSERT INTO date_part_vu_prepare_TestDates VALUES
('2025-01-01 05:30:45', '2025-01-01 05:30:45 +00:00', '2025-01-01 05:30:45.1234567', '2025-01-01 05:31:00'),
('2025-06-15 23:59:59', '2025-06-15 23:59:59 +00:00', '2025-06-15 23:59:59.9876543', '2025-06-15 23:59:00');
GO
~~ROW COUNT: 2~~

INSERT INTO date_part_vu_prepare_TestTimezones (TimezoneName) VALUES
('UTC'),('America/New_York'), ('Europe/London'), ('Asia/Tokyo'), ('Africa/Nairobi');
GO
~~ROW COUNT: 5~~

Loading

0 comments on commit 5a092d3

Please sign in to comment.