Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion contrib/babelfishpg_common/src/datetime2.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "postgres.h"

#include "fmgr.h"
#include "common/int.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
Expand Down Expand Up @@ -491,7 +492,22 @@ date_datetime2(PG_FUNCTION_ARGS)
else if (DATE_IS_NOEND(dateVal))
TIMESTAMP_NOEND(result);
else
result = dateVal * USECS_PER_DAY;
{
/*
* Use overflow-safe multiplication to prevent int64 overflow.
* dateVal * USECS_PER_DAY can overflow for dates outside the
* valid datetime2 range (0001-01-01 to 9999-12-31).
*/
int64 product;

if (pg_mul_s64_overflow((int64) dateVal, USECS_PER_DAY, &product) ||
!IS_VALID_DATETIME2(product))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("data out of range for datetime2")));

result = (Timestamp) product;
}

PG_RETURN_TIMESTAMP(result);
}
Expand Down
49 changes: 49 additions & 0 deletions test/JDBC/expected/cast_date_to_datetime2.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@

-- Test DATE to DATETIME2 cast with out-of-range dates (BABEL-4527)
-- Out-of-range: year 999999 (exceeds datetime2 max of 9999-12-31)
SELECT CAST(CAST('999999-12-31' AS DATE) AS datetime2);
GO
~~START~~
datetime2
~~ERROR (Code: 33557097)~~

~~ERROR (Message: data out of range for datetime2)~~


-- Out-of-range: year 10000 (just past valid range)
SELECT CAST(CAST('10000-01-01' AS DATE) AS datetime2);
GO
~~START~~
datetime2
~~ERROR (Code: 33557097)~~

~~ERROR (Message: data out of range for datetime2)~~


-- Valid boundary: max datetime2 date
SELECT CAST(CAST('9999-12-31' AS DATE) AS datetime2);
GO
~~START~~
datetime2
9999-12-31 00:00:00.0000000
~~END~~


-- Out-of-range: date before datetime2 min (PostgreSQL min date, 4714-11-24 BC)
SELECT CAST(CAST('4714-11-24 BC' AS DATE) AS datetime2);
GO
~~START~~
datetime2
~~ERROR (Code: 33557097)~~

~~ERROR (Message: data out of range for datetime2)~~


-- Valid boundary: min datetime2 date
SELECT CAST(CAST('0001-01-01' AS DATE) AS datetime2);
GO
~~START~~
datetime2
0001-01-01 00:00:00.0000000
~~END~~

21 changes: 21 additions & 0 deletions test/JDBC/input/cast_date_to_datetime2.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- Test DATE to DATETIME2 cast with out-of-range dates (BABEL-4527)

-- Out-of-range: year 999999 (exceeds datetime2 max of 9999-12-31)
SELECT CAST(CAST('999999-12-31' AS DATE) AS datetime2);
GO

-- Out-of-range: year 10000 (just past valid range)
SELECT CAST(CAST('10000-01-01' AS DATE) AS datetime2);
GO

-- Valid boundary: max datetime2 date
SELECT CAST(CAST('9999-12-31' AS DATE) AS datetime2);
GO

-- Out-of-range: date before datetime2 min (PostgreSQL min date, 4714-11-24 BC)
SELECT CAST(CAST('4714-11-24 BC' AS DATE) AS datetime2);
GO

-- Valid boundary: min datetime2 date
SELECT CAST(CAST('0001-01-01' AS DATE) AS datetime2);
GO
Loading