-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented CAST from VARBINARY to DATETIME in Babelfish. #3481
base: BABEL_3_X_DEV
Are you sure you want to change the base?
Changes from all commits
23f98da
40fc7fc
48a9eca
bf62659
d282c3b
f6c766b
d3edd97
f58fc54
ff0a4d7
c5ab93c
a1e6364
62123f0
dc6a5b2
223c741
4c372fa
1286899
2df9e5d
7340c48
fa01a8c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,7 @@ PG_FUNCTION_INFO_V1(datetime_recv); | |
PG_FUNCTION_INFO_V1(date_datetime); | ||
PG_FUNCTION_INFO_V1(time_datetime); | ||
PG_FUNCTION_INFO_V1(timestamp_datetime); | ||
PG_FUNCTION_INFO_V1(varbinary_datetime); | ||
PG_FUNCTION_INFO_V1(timestamptz_datetime); | ||
PG_FUNCTION_INFO_V1(datetime_varchar); | ||
PG_FUNCTION_INFO_V1(varchar_datetime); | ||
|
@@ -60,6 +61,7 @@ PG_FUNCTION_INFO_V1(timestamp_diff_big); | |
|
||
void CheckDatetimeRange(const Timestamp time); | ||
void CheckDatetimePrecision(fsec_t fsec); | ||
bool is_valid_datetime_for_4byte_varbinary(int64 total_usecs); | ||
|
||
#define DTK_NANO 32 | ||
|
||
|
@@ -754,6 +756,75 @@ timestamp_datetime(PG_FUNCTION_ARGS) | |
PG_RETURN_TIMESTAMP(result); | ||
} | ||
|
||
/* For 4 byte varbinary datetime range from 1900-01-01 00:00:00.000 to 1900-01-01 23:59:59:999*/ | ||
bool | ||
is_valid_datetime_for_4byte_varbinary(int64 total_usecs) | ||
{ | ||
return (total_usecs >= TSQL_DEFAULT_DATETIME && total_usecs <= MAX_4_BYTE_VARBINARY_DATETIME); | ||
} | ||
|
||
/* | ||
* varbinary_datetime() | ||
* Convert varbinary to datetime | ||
*/ | ||
Datum | ||
varbinary_datetime(PG_FUNCTION_ARGS) | ||
{ | ||
bytea *arg = PG_GETARG_BYTEA_PP(0); | ||
int32 size = VARSIZE_ANY_EXHDR(arg); | ||
int32 days; | ||
int32 time_part; | ||
int64 ms_value; | ||
int64 usecs; | ||
Timestamp result; | ||
unsigned char *buffer = (unsigned char *)VARDATA_ANY(arg); | ||
|
||
/* TSQL datetime is 8 bytes */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You mean input should be either 4 or 8 bytes, right? Lets update the comment. |
||
if (size != sizeof(int64) && size != sizeof(int32)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As spoken offline, Cast seems to accept multitude of binary lengths, I think MAX ones as well. Lets add support for all lens. |
||
ereport(ERROR, | ||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), | ||
errmsg("invalid binary size for datetime conversion"))); | ||
|
||
/* Extract days and time parts from the binary data */ | ||
if (size == sizeof(int32)) | ||
{ | ||
days = 0; | ||
time_part = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; | ||
} | ||
else | ||
{ | ||
days = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; | ||
time_part = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; | ||
} | ||
|
||
/* Convert time_part to microseconds */ | ||
ms_value = ((int64)time_part * 10LL) / 3LL; | ||
usecs = ms_value * 1000; | ||
|
||
if (days < 0) | ||
{ | ||
/* Handle pre-1900 dates */ | ||
int64 day_value = (int64) (((int64) days) & ((int64) 0xFFFFFFFF)); | ||
int64 total_usecs = (day_value - 0xFFFF2E46LL) * USECS_PER_DAY + usecs; | ||
result = MIN_DATETIME + total_usecs; | ||
} | ||
else | ||
{ | ||
/* Handle post-1900 dates */ | ||
int64 total_usecs = days * USECS_PER_DAY + usecs; | ||
result = TSQL_DEFAULT_DATETIME + total_usecs; | ||
} | ||
|
||
if (size == sizeof(int32) && !is_valid_datetime_for_4byte_varbinary(result)) | ||
ereport(ERROR, | ||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE), | ||
errmsg("data out of range for datetime"))); | ||
|
||
CheckDatetimeRange(result); | ||
|
||
PG_RETURN_TIMESTAMP(result); | ||
} | ||
|
||
/* timestamptz_datetime() | ||
* Convert timestamptz to datetime | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
-- Clean up | ||
drop table babel_datetime_vu_prepare_testing | ||
go | ||
drop table babel_datetime_vu_prepare_testing_1 | ||
go | ||
drop view babel_datetime_vu_view1 | ||
go | ||
~~ERROR (Code: 3701)~~ | ||
|
||
~~ERROR (Message: view "babel_datetime_vu_view1" does not exist)~~ | ||
|
||
drop view babel_datetime_vu_view2 | ||
go | ||
~~ERROR (Code: 3701)~~ | ||
|
||
~~ERROR (Message: view "babel_datetime_vu_view2" does not exist)~~ | ||
|
||
drop procedure babel_datetime_vu_procedure | ||
go |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.