Github user DaveBirdsall commented on a diff in the pull request:
https://github.com/apache/trafodion/pull/1310#discussion_r166437524
--- Diff: core/conn/unixodbc/odbc/odbcclient/unixcli/cli/ctosqlconv.cpp ---
@@ -157,852 +157,982 @@ unsigned long ODBC::Ascii_To_Interval_Helper(char
*source,
unsigned long ODBC::ConvertCToSQL(SQLINTEGER ODBCAppVersion,
- SQLSMALLINT
CDataType,
- SQLPOINTER
srcDataPtr,
- SQLINTEGER
srcLength,
- SQLSMALLINT
ODBCDataType,
- SQLSMALLINT
SQLDataType,
- SQLSMALLINT
SQLDatetimeCode,
- SQLPOINTER
targetDataPtr,
- SQLINTEGER
targetLength,
- SQLINTEGER
targetPrecision,
- SQLSMALLINT
targetScale,
- SQLSMALLINT
targetUnsigned,
- SQLINTEGER
targetCharSet,
- BOOL
byteSwap,
-// FPSQLDriverToDataSource
fpSQLDriverToDataSource,
-// DWORD
translateOption,
- ICUConverter* iconv,
- UCHAR
*errorMsg,
- SWORD
errorMsgMax,
- SQLINTEGER
EnvironmentType,
- BOOL
RWRSFormat,
- SQLINTEGER
datetimeIntervalPrecision)
+ SQLSMALLINT CDataType,
+ SQLPOINTER srcDataPtr,
+ SQLINTEGER srcLength,
+ SQLPOINTER targetDataPtr,
+ CDescRec *targetDescPtr,
+ BOOL byteSwap,
+#ifdef unixcli
+ ICUConverter* iconv,
+#else
+ FPSQLDriverToDataSource fpSQLDriverToDataSource,
+ DWORD translateOption,
+#endif
+ UCHAR *errorMsg,
+ SWORD errorMsgMax,
+ SQLINTEGER EnvironmentType,
+ BOOL RWRSFormat,
+ SQLINTEGER datetimeIntervalPrecision)
{
- unsigned long retCode = SQL_SUCCESS;
- SQLPOINTER DataPtr = NULL;
- SQLPOINTER outDataPtr = targetDataPtr;
- SQLINTEGER DataLen = DRVR_PENDING;
- short Offset = 0; // Used for VARCHAR fields
- SQLINTEGER OutLen = targetLength;
- short targetType = 0; //for bignum datatype
+ unsigned long retCode = SQL_SUCCESS;
+ if(pdwGlobalTraceVariable && *pdwGlobalTraceVariable){
+ TraceOut(TR_ODBC_DEBUG,"ConvertCToSQL(%d, %d, %#x, %d, %d, %d, %d,
%#x, %d, %d, %d, %d, %d, %d, %#x, %d, %d, %d)",
+ ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr->m_ODBCDataType,
+ targetDescPtr->m_SQLDataType,
+ targetDescPtr->m_SQLDatetimeCode,
+ targetDataPtr,
+ targetDescPtr->m_SQLOctetLength,
+ targetDescPtr->m_ODBCPrecision,
+ targetDescPtr->m_ODBCScale,
+ targetDescPtr->m_SQLUnsigned,
+ targetDescPtr->m_SQLCharset,
+ byteSwap,
+ errorMsg,
+ errorMsgMax,
+ EnvironmentType,
+ RWRSFormat);
+ }
+ else
+ RESET_TRACE();
+ if (CDataType == SQL_C_DEFAULT)
+ {
+ retCode = getCDefault(targetDescPtr->m_ODBCDataType,
ODBCAppVersion, targetDescPtr->m_SQLCharset, CDataType);
+ if (retCode != SQL_SUCCESS)
+ return retCode;
+ }
- int dec;
- int sign;
- int tempLen;
- int tempLen1;
- int temp;
+ if (errorMsg)
+ *errorMsg = '\0';
+
+ switch (targetDescPtr->m_ODBCDataType)
+ {
+ case SQL_VARCHAR:
+ case SQL_LONGVARCHAR:
+ case SQL_WVARCHAR:
+ case SQL_CHAR:
+ if( targetDescPtr->m_SQLDataType == SQLTYPECODE_BOOLEAN )
+ {
+ retCode = convToSQLBool(srcDataPtr,srcLength, CDataType,
targetDataPtr);
+ break;
+ }
+ case SQL_WCHAR:
+ retCode = ConvertToCharTypes(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ errorMsg);
+ break;
- short i;
- short datetime_parts[8];
- char *tempPtr;
- double dTmp;
- double dTmp1;
- double scaleOffset;
- SCHAR tTmp;
- UCHAR utTmp;
- SSHORT sTmp;
- USHORT usTmp;
- SLONG_P lTmp;
- ULONG_P ulTmp;
- CHAR cTmpBuf[256];
- CHAR cTmpBuf2[256];
- CHAR cTmpBufInterval[256];
- CHAR cTmpFraction[10];
- __int64 tempVal64;
- __int64 integralPart;
- __int64 decimalPart;
- __int64 tempScaleVal64;
- unsigned __int64 integralMax;
- unsigned __int64 decimalMax;
- float fltTmp;
- BOOL useDouble = TRUE;
- BOOL negative = FALSE;
- long decimalDigits;
- long leadZeros;
- SQLUINTEGER ulFraction;
- SQLSMALLINT cTmpDataType;
-
- DATE_STRUCT *dateTmp;
- TIME_STRUCT *timeTmp;
- TIMESTAMP_STRUCT *timestampTmp;
- SQL_INTERVAL_STRUCT *intervalTmp;
- DATE_TYPES SQLDate;
- TIME_TYPES SQLTime;
- TIMESTAMP_TYPES SQLTimestamp;
- DATE_TYPES *pSQLDate;
- TIME_TYPES *pSQLTime;
- TIMESTAMP_TYPES *pSQLTimestamp;
- SQLINTEGER translateLength;
- SQLSMALLINT tODBCDataType;
- BOOL signedInteger = FALSE;
- BOOL unsignedInteger = FALSE;
- BOOL dataTruncatedWarning = FALSE;
- int AdjustedLength = 0;
- char srcDataLocale[256];
-
- if(pdwGlobalTraceVariable && *pdwGlobalTraceVariable){
- TraceOut(TR_ODBC_DEBUG,"ConvertCToSQL(%d, %d, %#x, %d, %d, %d,
%d, %#x, %d, %d, %d, %d, %d, %d, %#x, %d, %d, %d)",
- ODBCAppVersion,
- CDataType,
- srcDataPtr,
- srcLength,
- ODBCDataType,
- SQLDataType,
- SQLDatetimeCode,
- targetDataPtr,
- targetLength,
- targetPrecision,
- targetScale,
- targetUnsigned,
- targetCharSet,
- byteSwap,
- errorMsg,
- errorMsgMax,
- EnvironmentType,
- RWRSFormat);
- }
- else
- RESET_TRACE();
-/*
-1. Because MS programs do not support BIGINT type, the server has to
convert it to NUMERIC:
- ODBCDataType = SQL_NUMERIC;
- ODBCPrecision = 19;
- SignType = TRUE;
- Before conversion we have to change it back to:
- ODBCDataType = SQL_BIGINT;
-
-2. Because ODBC does not support unsigned types for SMALLINT and INTEGER,
- the server has to convert it to:
- a)SQLTYPECODE_SMALLINT_UNSIGNED:
- ODBCPrecision = 10;
- ODBCDataType = SQL_INTEGER;
- SignType = TRUE;
- b)SQLTYPECODE_INTEGER_UNSIGNED:
- ODBCPrecision = 19;
- ODBCDataType = SQL_NUMERIC;
- SignType = TRUE;
-
- Before conversion we have to change it back to datatype, precision and
sign described by SQL:
- a)
- ODBCPrecision = 5;
- ODBCDataType = SQL_SMALLINT;
- SignType = FALSE;
- b)
- ODBCPrecision = 10;
- ODBCDataType = SQL_INTEGER;
- SignType = FALSE;
-*/
- tODBCDataType = ODBCDataType;
- if (ODBCDataType == SQL_NUMERIC && SQLDataType == SQLTYPECODE_LARGEINT
&&
- targetPrecision == 19 && targetScale==0)
- {
- ODBCDataType = SQL_BIGINT;
- }
+ case SQL_TINYINT:
+ case SQL_SMALLINT:
+ case SQL_INTEGER:
+ case SQL_FLOAT:
+ case SQL_REAL:
+ case SQL_DOUBLE:
+ case SQL_DECIMAL:
+ retCode = ConvertToNumberSimple(CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ errorMsg);
+ break;
- if (ODBCDataType == SQL_INTEGER && SQLDataType ==
SQLTYPECODE_SMALLINT_UNSIGNED &&
- targetPrecision == 10 && targetScale==0)
- {
- targetPrecision = 5;
- ODBCDataType = SQL_SMALLINT;
- targetUnsigned = true;
- }
+ case SQL_BIGINT:
+ retCode = ConvertToBigint(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ errorMsg);
+ break;
- if (ODBCDataType == SQL_NUMERIC && SQLDataType ==
SQLTYPECODE_INTEGER_UNSIGNED &&
- targetPrecision == 19 && targetScale==0)
- {
- targetPrecision = 10;
- ODBCDataType = SQL_INTEGER;
- targetUnsigned = true;
- }
+ case SQL_NUMERIC:
+ retCode = ConvertToNumeric(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ errorMsg);
+ break;
- if (ODBCDataType == SQL_BIGINT && SQLDataType ==
SQLTYPECODE_INTEGER_UNSIGNED &&
- targetPrecision == 19 && targetScale==0)
- {
- targetPrecision = 10;
- ODBCDataType = SQL_INTEGER;
- targetUnsigned = true;
- }
+ case SQL_DATE:
+ case SQL_TYPE_DATE:
+ retCode = ConvertToDateType(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ RWRSFormat,
+ errorMsg);
+ break;
- if (CDataType == SQL_C_DEFAULT)
- {
- getCDefault(tODBCDataType, ODBCAppVersion, targetCharSet,
CDataType);
- if (ODBCAppVersion >= 3 && targetUnsigned)
- {
- switch(CDataType)
- {
- case SQL_C_SHORT:
- case SQL_C_SSHORT:
- CDataType = SQL_C_USHORT;
- break;
- case SQL_C_TINYINT:
- case SQL_C_STINYINT:
- CDataType = SQL_C_UTINYINT;
- break;
- case SQL_C_LONG:
- case SQL_C_SLONG:
- CDataType = SQL_C_ULONG;
- break;
- }
- }
- }
+ case SQL_TIME:
+ case SQL_TYPE_TIME:
+ retCode = ConvertToTimeType(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ RWRSFormat,
+ errorMsg);
+ break;
-//--------------------------------------------------------------------------------------
+ case SQL_TIMESTAMP:
+ case SQL_TYPE_TIMESTAMP:
+ retCode = ConvertToTimeStampType(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ RWRSFormat,
+ errorMsg);
+ break;
- if (errorMsg)
- *errorMsg = '\0';
- //if (targetPrecision < 19)
- if( !(((SQLDataType == SQLTYPECODE_NUMERIC) && (targetPrecision > 18))
||
- ((SQLDataType == SQLTYPECODE_NUMERIC_UNSIGNED) &&
(targetPrecision > 9))))
- getMaxNum(targetPrecision, targetScale, integralMax, decimalMax);
+ case SQL_INTERVAL_MONTH:
+ case SQL_INTERVAL_YEAR:
+ case SQL_INTERVAL_YEAR_TO_MONTH:
+ case SQL_INTERVAL_DAY:
+ case SQL_INTERVAL_HOUR:
+ case SQL_INTERVAL_MINUTE:
+ case SQL_INTERVAL_SECOND:
+ case SQL_INTERVAL_DAY_TO_HOUR:
+ case SQL_INTERVAL_DAY_TO_MINUTE:
+ case SQL_INTERVAL_DAY_TO_SECOND:
+ case SQL_INTERVAL_HOUR_TO_MINUTE:
+ case SQL_INTERVAL_HOUR_TO_SECOND:
+ case SQL_INTERVAL_MINUTE_TO_SECOND:
+ retCode = ConvertToTimeIntervalType(ODBCAppVersion,
+ CDataType,
+ srcDataPtr,
+ srcLength,
+ targetDescPtr,
+ iconv,
+ targetDataPtr,
+ RWRSFormat,
+ errorMsg,
+ datetimeIntervalPrecision);
+ break;
- switch (ODBCDataType)
- {
- case SQL_VARCHAR:
- case SQL_LONGVARCHAR:
- case SQL_WVARCHAR:
- {
- if(targetPrecision > SHRT_MAX)
- {
- Offset = sizeof(UINT);
- }
- else
- {
- Offset = sizeof(USHORT);
- }
- }
- case SQL_CHAR:
- if( SQLDataType == SQLTYPECODE_BOOLEAN )
+ default:
+ return IDS_07_006;
+ }
+
+ return retCode;
+}
+
+unsigned long ODBC::convToSQLBool(SQLPOINTER srcDataPtr,SQLINTEGER
srcLength, SQLSMALLINT CDataType, SQLPOINTER targetDataPtr)
+{
+
+ CHAR cTmpBuf[TMPLEN] = {0};
+ double dTmp = 0;
+ char temptarget = 0;
+ unsigned long retCode = SQL_SUCCESS;
+ errno = 0;
+
+ switch (CDataType)
+ {
+ case SQL_C_CHAR:
+ case SQL_C_WCHAR:
+ temptarget = strtol((char*)srcDataPtr,NULL,10);
+ if (errno == ERANGE)
+ return IDS_22_003;
+ break;
+
+ case SQL_C_TINYINT:
+ case SQL_C_STINYINT:
+ temptarget = *(SCHAR *)srcDataPtr;
+ break;
+
+ case SQL_C_BIT:
+ case SQL_C_UTINYINT:
+ temptarget = *(UCHAR *)srcDataPtr;
+ break;
+
+ case SQL_C_SHORT:
+ case SQL_C_SSHORT:
+ temptarget = *(SSHORT *)srcDataPtr;
+ break;
+
+ case SQL_C_USHORT:
+ temptarget = *(USHORT *)srcDataPtr;
+ break;
+
+ case SQL_C_LONG:
+ case SQL_C_SLONG:
+ temptarget = *(SLONG_P *)srcDataPtr;
+ break;
+ case SQL_C_ULONG:
+ temptarget = *(ULONG_P *)srcDataPtr;
+ break;
+
+ case SQL_C_SBIGINT:
+ temptarget = *(__int64 *)srcDataPtr;
+ break;
+
+ case SQL_C_UBIGINT:
+ temptarget = *(unsigned __int64 *)srcDataPtr;
+ break;
+
+ case SQL_C_NUMERIC:
+ retCode = ConvertCNumericToChar((SQL_NUMERIC_STRUCT*)srcDataPtr,
cTmpBuf);
+ if (retCode != SQL_SUCCESS)
+ return retCode;
+ retCode = ConvertCharToNumeric((char*)cTmpBuf, srcLength, dTmp);
+ if (retCode != SQL_SUCCESS)
+ return retCode;
+ temptarget = dTmp;
+ break;
+
+ default:
+ return IDS_07_006;
+ }
+
+ if (temptarget < 0)
+ return IDS_22_003_02;
+ if (temptarget > 1)
+ return IDS_22_003;
+
+ memcpy(targetDataPtr, &temptarget, sizeof(SCHAR));
+
+ return SQL_SUCCESS;
+}
+
+
+
+unsigned long ODBC::MemcpyToNumeric(SQLPOINTER DataPtr,
+ SQLINTEGER & DataLen,
+ CDescRec* targetDescPtr,
+ SQLSMALLINT CDataType,
+ BOOL useDouble,
+ double dTmp,
+ BOOL negative,
+ __int64 decimalPart,
+ __int64 integralPart,
+ long leadZeros,
+ ICUConverter* iconv,
+ SQLPOINTER & outDataPtr,
+ unsigned long retTmp
+ )
+{
+
+ SQLSMALLINT targetUnsigned = targetDescPtr->m_SQLUnsigned;
+ SQLSMALLINT targetScale = targetDescPtr->m_ODBCScale;
+ SQLSMALLINT SQLDataType = targetDescPtr->m_SQLDataType;
+ SQLINTEGER targetPrecision = targetDescPtr->m_ODBCPrecision;
+ double dTmp1 = 0;
+ double scaleOffset = 0;
+ CHAR tTmp = 0;
+ USHORT usTmp = 0;
+ UCHAR utTmp = 0;
+ SHORT sTmp = 0;
+ ULONG_P ulTmp = 0;
+ SLONG_P lTmp = 0;
+ __int64 tempVal64 = 0;
+ __int64 tempScaleVal64 = 0;
+ unsigned __int64 uVal64 = 0;
+ short i = 0;
+ long decimalDigits = 0;
+ unsigned long retCode = retTmp;
+
+ if (DataPtr == NULL)
+ {
+ if (useDouble)
{
- switch (CDataType)
+ if( targetUnsigned && ( dTmp < 0 || negative ))
+ return IDS_22_003_02; //negValue in unsigned column
+
+ dTmp1 = pow((double)10, targetPrecision - targetScale + 1);
+ if (dTmp < -dTmp1 || dTmp > dTmp1)
+ return IDS_22_003;
+ scaleOffset = pow(10, targetScale); // This value always
multplied to srcValue
+ // since SQL stores it as a implied decimal point
+ // 1.0 for NUMERIC (4,2) value is stored as 100
+ dTmp *= scaleOffset;
+ switch (SQLDataType)
+ {
+ case SQLTYPECODE_TINYINT_UNSIGNED:
+ utTmp = (UCHAR)dTmp;
+ DataPtr = &utTmp;
+ DataLen = sizeof(UCHAR);
+ break;
+ case SQLTYPECODE_TINYINT:
+ tTmp = (SCHAR)dTmp;
+ DataPtr = &tTmp;
+ DataLen = sizeof(SCHAR);
+ break;
+
+ case SQLTYPECODE_SMALLINT_UNSIGNED:
+ usTmp = (USHORT)dTmp;
+ DataPtr = &usTmp;
+ DataLen = sizeof(USHORT);
+ break;
+ case SQLTYPECODE_SMALLINT:
+ sTmp = (SHORT)dTmp;
+ DataPtr = &sTmp;
+ DataLen = sizeof(SHORT);
+ break;
+
+ case SQLTYPECODE_INTEGER_UNSIGNED:
+ ulTmp = (ULONG_P)dTmp;
+ DataPtr = &ulTmp;
+ DataLen = sizeof(ULONG_P);
+ break;
+ case SQLTYPECODE_INTEGER:
+ lTmp = (LONG)dTmp;
+ DataPtr = &lTmp;
+ DataLen = sizeof(LONG);
+ break;
+
+ case SQLTYPECODE_LARGEINT_UNSIGNED:
+ tempVal64 = (unsigned __int64)dTmp;
+ DataPtr = &tempVal64;
+ DataLen = sizeof(unsigned __int64);
+ break;
+ case SQLTYPECODE_LARGEINT:
+ tempVal64 = (__int64)dTmp;
+ DataPtr = &tempVal64;
+ DataLen = sizeof(__int64);
+ break;
+
+ default:
+ return IDS_07_006;
+ }
+ }
+ else
+ {
+ if( targetUnsigned && negative )
+ return IDS_22_003_02; //negValue in unsigned column
+
+ if (targetScale)
+ {
+ for (i = 0,tempVal64 = 1; i < targetScale ; i++)
+ tempVal64 *= 10;
+ tempVal64 = tempVal64 * integralPart;
+ decimalDigits = 0;
+ if (decimalPart > 0)
+ decimalDigits = getDigitCount(decimalPart);
+ scaleOffset = 0;
+ if (leadZeros < targetScale)
+ scaleOffset = targetScale - decimalDigits - leadZeros;
+ if (scaleOffset < 0)
+ {
+ //NUMERIC_VALUE_OUT_OF_RANGE_ERROR
+ return IDS_22_003;
+ }
+
+ for (i =0, tempScaleVal64 = decimalPart ; i < scaleOffset
; i++)
+ tempScaleVal64 *= 10;
+ tempVal64 += tempScaleVal64;
+ }
+ else
+ {
+ //NUMERIC_DATA_TRUNCATED_ERROR
+ if (decimalPart != 0)
+ retCode = IDS_01_S07;
+ tempVal64 = integralPart;
+ }
+ if (negative)
+ tempVal64 = -tempVal64;
+
+ switch( SQLDataType )
{
+ case SQLTYPECODE_TINYINT_UNSIGNED:
+ if (tempVal64 < 0)
+ return IDS_22_003_02;
+ if ((UCHAR)tempVal64 > UCHAR_MAX)
+ return IDS_22_003;
+ utTmp = (UCHAR)tempVal64;
+ if (tempVal64 != utTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &utTmp;
+ DataLen = sizeof(UCHAR);
+ break;
+ case SQLTYPECODE_TINYINT:
+ if (tempVal64 < CHAR_MIN || tempVal64 > CHAR_MAX)
+ return IDS_22_003;
+ tTmp = (SCHAR)tempVal64;
+ if (tempVal64 != tTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &tTmp;
+ DataLen = sizeof(SCHAR);
+ break;
+
+ case SQLTYPECODE_SMALLINT_UNSIGNED:
+ if (tempVal64 < 0)
+ return IDS_22_003_02;
+ if ((USHORT)tempVal64 > USHRT_MAX)
+ return IDS_22_003;
+ usTmp = (USHORT)tempVal64;
+ if (tempVal64 != usTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &usTmp;
+ DataLen = sizeof(USHORT);
+ break;
+ case SQLTYPECODE_SMALLINT:
+ if (tempVal64 < SHRT_MIN || tempVal64 > SHRT_MAX)
+ return IDS_22_003;
+ sTmp = (SHORT)tempVal64;
+ if (tempVal64 != sTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &sTmp;
+ DataLen = sizeof(SHORT);
+ break;
+
+ case SQLTYPECODE_INTEGER_UNSIGNED:
+ // solution 10-080804-4996
+ // for 64 bit Solaris/AIX (with XlC cplr),
+ // tempVal64 is a signed LONG LONG,
+ // ULONG_MAX is unsigned LONG of 'FFFFFFF....',
+ // somehow it will evaluate tempVal64 GT ULONG_MAX
+ // so cast the tempVal64 to (ULONG)
+ if (tempVal64 < 0)
+ return IDS_22_003_02;
+ if ((ULONG_P)tempVal64 > ULONG_MAX)
+ return IDS_22_003;
+ ulTmp = (ULONG_P)tempVal64;
+ if (tempVal64 != ulTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &ulTmp;
+ DataLen = sizeof(ULONG_P);
+ break;
+ case SQLTYPECODE_INTEGER:
+ if (tempVal64 < LONG_MIN || tempVal64 > LONG_MAX)
+ return IDS_22_003;
+ lTmp = (LONG)tempVal64;
+ if (tempVal64 != lTmp)
+ retCode = IDS_01_S07;
+ DataPtr = &lTmp;
+ DataLen = sizeof(LONG);
+ break;
+
+ case SQLTYPECODE_LARGEINT_UNSIGNED:
+ if(tempVal64 < 0)
+ return IDS_22_003_02;
+ if((unsigned __int64)tempVal64 > ULLONG_MAX)
+ return IDS_22_003;
+ uVal64 = (unsigned __int64)tempVal64;
+ if(tempVal64 != uVal64)
+ retCode = IDS_01_S07;
+ DataPtr = &uVal64;
+ DataLen = sizeof(unsigned __int64);
+ break;
+ case SQLTYPECODE_LARGEINT:
+ DataPtr = &tempVal64;
+ DataLen = sizeof(__int64);
+ break;
+
+ default:
+ return IDS_07_006;
+ break;
+ }
+
+ }
+ }
+
+ memcpy(outDataPtr, DataPtr, DataLen);
+
+ return retCode;
+}
+
+unsigned long ODBC::ConvertToNumeric(SQLINTEGER ODBCAppVersion,
+ SQLSMALLINT CDataType,
+ SQLPOINTER srcDataPtr,
+ SQLINTEGER srcLength,
+ CDescRec* targetDescPtr,
+ ICUConverter* iconv,
+ SQLPOINTER targetDataPtr,
+ UCHAR *errorMsg)
+{
+ SQLSMALLINT ODBCDataType = targetDescPtr->m_ODBCDataType;
+ SQLSMALLINT SQLDataType = targetDescPtr->m_SQLDataType;
+ SQLSMALLINT targetScale = targetDescPtr->m_ODBCScale;
+ SQLSMALLINT targetUnsigned = targetDescPtr->m_SQLUnsigned;
+ SQLINTEGER targetPrecision = targetDescPtr->m_ODBCPrecision;
+ SQLINTEGER targetCharSet = targetDescPtr->m_SQLCharset;
+ SQLINTEGER translateLength = 0;
+ SQLINTEGER targetLength = targetDescPtr->m_SQLOctetLength;
+ SQL_INTERVAL_STRUCT *intervalTmp = NULL;
+ char srcDataLocale[CHARTMPLEN] = {0};
+ int tempLen = 0;
+ int numberLen = 0;
+ CHAR cTmpBuf[CHARTMPLEN] = {0};
+ CHAR cTmpBuf2[CHARTMPLEN] = {0};
+ BOOL dataTruncatedWarning = FALSE;
+ unsigned long retCode = SQL_SUCCESS;
+ double dTmp = 0;
+ __int64 integralPart = 0;
+ __int64 decimalPart = 0;
+ SQLINTEGER DataLen = DRVR_PENDING;
+ SQLPOINTER DataPtr = NULL;
+ BOOL useDouble = TRUE;
+ long leadZeros = 0;
+ unsigned __int64 integralMax = 0;
+ unsigned __int64 decimalMax = 0;
+ BOOL negative = FALSE;
+ long decimalDigits = 0;
+
+
+ if(SQLDataType == SQLTYPECODE_NUMERIC || SQLDataType ==
SQLTYPECODE_NUMERIC_UNSIGNED)//for bignum support
+ { //Bignum
+ switch (CDataType)
+ {
+ case SQL_C_DEFAULT:
+ if (ODBCAppVersion >= SQL_OV_ODBC3)
+ {
+
+ } // Want it fall thru and treat it
like SQL_C_CHAR
case SQL_C_WCHAR:
if (iconv->isAppUTF16())
{
if (srcLength != SQL_NTS)
srcLength = srcLength/2;
+ // translate from UTF16
if (iconv->WCharToUTF8((UChar*)srcDataPtr, srcLength,
srcDataLocale, sizeof(srcDataLocale), (int*)&translateLength, (char*)errorMsg)
!= SQL_SUCCESS)
return IDS_193_DRVTODS_ERROR;
srcDataPtr = srcDataLocale;
srcLength = translateLength;
}
+ case SQL_C_BINARY:
case SQL_C_CHAR:
- retCode = ConvertCharToNumeric(srcDataPtr, srcLength,
dTmp);
- if (retCode != SQL_SUCCESS)
- return retCode;
+ if (srcLength == SQL_NTS)
+ tempLen = strlen((const char *)srcDataPtr);
+ else
+ tempLen = srcLength;
+ if (tempLen > CHARTMPLEN - 1)
+ strncpy(cTmpBuf, (char *)srcDataPtr, CHARTMPLEN - 1);
--- End diff --
No, I mean adding a line "cTmpBuf[CHARTMPLEN-1] = '\0';" after the strncpy.
The "if" at 723 guarantees that no trailing null character is copied, so it
seems like we need to add one if we take the code path of statement 724.
---