Skip to content

Commit

Permalink
Support sending sql_variant date value as nvarchar
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Kasko <[email protected]>
  • Loading branch information
staticlibs committed May 29, 2024
1 parent 03bec51 commit 74a594a
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 20 deletions.
26 changes: 26 additions & 0 deletions contrib/babelfishpg_tds/src/backend/tds/tdstimestamp.c
Original file line number Diff line number Diff line change
Expand Up @@ -551,3 +551,29 @@ TdsGetTimestampFromDayTime(uint32 numDays, uint64 numMicro, int tz,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("timestamp out of range")));
}

char*
TdsTimeGetDateAsString(Datum value)
{
struct pg_tm ti,
*tm = &ti;
char *result;

memset(tm, '\0', sizeof(struct pg_tm));
GetDateFromDatum(value, tm);
/*
* Adjust the timestamp converting it from Postgres' datetime where tm_mon
* is counted from 1 and tm_year is relative to 1 BCE to POSIX datetime
* where tm_mon counts from 0 and tm_year is relative to 1900.
*/
tm->tm_year -= 1900;
tm->tm_mon -= 1;

result = palloc(10 + 1);
if (!pg_strftime(result, 10 + 1, "%Y-%m-%d", tm))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("date out of range")));

return result;
}
68 changes: 57 additions & 11 deletions contrib/babelfishpg_tds/src/backend/tds/tdstypeio.c
Original file line number Diff line number Diff line change
Expand Up @@ -4153,22 +4153,68 @@ TdsSendTypeSqlvariant(FmgrInfo *finfo, Datum value, void *vMetaData)
}
else if (isBaseDate)
{
/*
* dataformat : totalLen(4B) + baseType(1B) + metadatalen(1B) +
* data(3B)
*/

if (variantBaseType == VARIANT_TYPE_DATE)
{
memset(&dateval, 0, sizeof(dateval));
memcpy(&dateval, buf, sizeof(dateval));
numDays = TdsDayDifference(dateval);
dataLen = 3;
totalLen = dataLen + VARIANT_TYPE_METALEN_FOR_DATE;
rc = TdsPutUInt32LE(totalLen);
rc |= TdsPutInt8(variantBaseType);
rc |= TdsPutInt8(VARIANT_TYPE_BASE_METALEN_FOR_DATE);
rc |= TdsPutDate(numDays);

if (GetClientTDSVersion() <= TDS_VERSION_7_2)
{
/*
* DATENTYPE type was introduced in TDS 7.3, with earlier protocol
* versions date is sent as NVARCHARTYPE.
*
* dataformat: totalLen(4B) + baseType(1B) + metadatalen(1B) +
* encodingLen(5B) + dataLen(2B) + data(dataLen)
*/
StringInfoData strbuf;
int actualDataLen = 0; /* Number of bytes that would be
* needed to store given string in
* given encoding. */
char *dateStr = NULL;

dateStr = TdsTimeGetDateAsString(dateval);
initStringInfo(&strbuf);
TdsUTF8toUTF16StringInfo(&strbuf, dateStr, 10);
pfree(dateStr);

actualDataLen = strbuf.len;
totalLen = actualDataLen + VARIANT_TYPE_METALEN_FOR_CHAR_DATATYPES;

rc = TdsPutUInt32LE(totalLen);
rc |= TdsPutInt8(VARIANT_TYPE_NVARCHAR);
rc |= TdsPutInt8(VARIANT_TYPE_BASE_METALEN_FOR_CHAR_DATATYPES);

/*
* 5B of fixed collation TODO: [BABEL-1069] Remove collation related
* hardcoding from sql_variant sender for char class basetypes
*/
rc |= TdsPutInt8(9);
rc |= TdsPutInt8(4);
rc |= TdsPutInt8(208);
rc |= TdsPutInt8(0);
rc |= TdsPutInt8(52);

rc |= TdsPutUInt16LE(actualDataLen);

rc |= TdsPutbytes(strbuf.data, actualDataLen);
pfree(strbuf.data);
}
else
{
/*
* dataformat : totalLen(4B) + baseType(1B) + metadatalen(1B) +
* data(3B)
*/
numDays = TdsDayDifference(dateval);
dataLen = 3;
totalLen = dataLen + VARIANT_TYPE_METALEN_FOR_DATE;
rc = TdsPutUInt32LE(totalLen);
rc |= TdsPutInt8(variantBaseType);
rc |= TdsPutInt8(VARIANT_TYPE_BASE_METALEN_FOR_DATE);
rc |= TdsPutDate(numDays);
}
}

/*
Expand Down
1 change: 1 addition & 0 deletions contrib/babelfishpg_tds/src/include/tds_timestamp.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ extern void TdsTimeGetDatumFromDays(uint32 numDays, uint64 *val);
extern void TdsTimeGetDatumFromDatetime(uint32 numDays, uint32 numTicks,
Timestamp *timestamp);
extern uint32 TdsGetDayDifferenceHelper(int day, int mon, int year, bool isDateType);
extern char* TdsTimeGetDateAsString(Datum value);

/*
* structure for datatimeoffset support with separate time zone field
Expand Down
8 changes: 4 additions & 4 deletions test/JDBC/expected/jtds-TestDatetime.out
Original file line number Diff line number Diff line change
Expand Up @@ -369,19 +369,19 @@ datetime
~~END~~

select convert(datetime, '9999-12-31 23:59:59.999');
~~ERROR (Code: 517)~~
~~ERROR (Code: 33557097)~~

~~ERROR (Message: data out of range for datetime)~~
~~ERROR (Message: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.)~~

select convert(datetime, '1752-12-31 23:59:59.997');
~~ERROR (Code: 33557097)~~

~~ERROR (Message: The conversion of a VARCHAR data type to a DATETIME data type resulted in an out-of-range value.)~~
~~ERROR (Message: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.)~~

select convert(datetime, '0000-00-00 00:00:00.000');
~~ERROR (Code: 33557097)~~

~~ERROR (Message: The conversion of a VARCHAR data type to a DATETIME data type resulted in an out-of-range value.)~~
~~ERROR (Message: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.)~~

select convert(datetime, NULL);
~~START~~
Expand Down
4 changes: 0 additions & 4 deletions test/JDBC/expected/jtds-TestSimpleErrors.out
Original file line number Diff line number Diff line change
Expand Up @@ -2762,10 +2762,6 @@ GO
~~ROW COUNT: 1~~

GO
~~ERROR (Code: 0)~~

~~ERROR (Message: The SQL statement must not be null or empty.)~~

select * from simpleErrorTable ORDER BY c
GO
~~START~~
Expand Down
2 changes: 1 addition & 1 deletion test/JDBC/jtds_jdbc_schedule
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jtds-TestBinary
TestImage-vu-prepare
TestImage-vu-verify
TestImage-vu-cleanup
# Failure: Message: Data truncation
# Failure: date type support for TDS 7.1 has been added, time and datetime2 support pending
# TestSQLVariant-vu-prepare
# TestSQLVariant-vu-verify
# TestSQLVariant-vu-cleanup
Expand Down
4 changes: 4 additions & 0 deletions test/JDBC/src/main/java/com/sqlsamples/JDBCStatement.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ void testStatementWithFile(String SQL, BufferedWriter bw, String strLine, Logger
bw.write(strLine);
bw.newLine();

if (SQL.isEmpty()) {
return;
}

SQLWarning sqlwarn = null;
boolean resultSetExist = false;
boolean warningExist = false;
Expand Down

0 comments on commit 74a594a

Please sign in to comment.