Modified:
MYODBCC/MYODBCCLib/MYODBCC.cpp
MYODBCC/include/MYODBCC.h
MYSQLPlus/MYSQLPlusLib/MResult.cpp
MYSQLPlus/MYSQLPlusLib/MResult.h
Log:
Modified: MYODBCC/MYODBCCLib/MYODBCC.cpp
===================================================================
--- MYODBCC/MYODBCCLib/MYODBCC.cpp 2006-05-18 21:38:18 UTC (rev 257)
+++ MYODBCC/MYODBCCLib/MYODBCC.cpp 2006-05-19 06:50:17 UTC (rev 258)
@@ -1391,13 +1391,106 @@
return true;
}
#else
- BOOLEAN MYODBCC::doStrNCpy( SQLWCHAR *pszDest, size_t nChars, const SQLWCHAR *pszSrc
)
+ BOOLEAN MYODBCC::doStrNCpy( SQLWCHAR *pszDest, size_t nMaxChars, const SQLWCHAR
*pszSrc )
{
wcsncpy( pszDest, pszSrc, nChars );
return true;
}
#endif
+/*!
+ \brief Copies a C string.
+
+ The following occurs in this method;
+
+ 1. the dest string is always null terminated (unless buffer is not
provided)
+ 2. considers truncation
+
+ \return BOOLEAN
+
+ \retval true Copy completed with no warnings/errors
+ false Copy completed but result was truncated due to lack of space in
dest buffer
+*/
+BOOLEAN MYODBCC::doStringCopyOut( SQLCHAR *pszDest, SQLINTEGER nDestMaxChars, SQLCHAR
*pszSrc )
+{
+ SQLINTEGER nIndex = 0;
+
+ /* sanity checks */
+ if ( !pszDest || nDestMaxChars < 1 )
+ {
+ if ( *pszSrc )
+ return false;
+ return true;
+ }
+
+ if ( !pszSrc )
+ {
+ *pszDest = '\0';
+ return true; /* ok - but nothing to copy */
+ }
+
+ /* copy chars while room in pszDest or end of pszSrc */
+ for ( nIndex = 0; nIndex < nDestMaxChars; nIndex++ )
+ {
+ pszDest[nIndex] = pszSrc[nIndex];
+ if ( pszSrc[nIndex] == '\0' )
+ return true;
+ }
+
+ /* pszDest full - ensure last char is null terminator */
+ pszDest[nIndex-1] = '\0';
+
+ /* results are truncated */
+ return false;
+}
+
+/*!
+ \brief Copies a wide character C string.
+
+ The following occurs in this method;
+
+ 1. the dest string is always null terminated (unless buffer is not
provided)
+ 2. considers truncation
+
+ \return BOOLEAN
+
+ \retval true Copy completed with no warnings/errors
+ false Copy completed but result was truncated due to lack of space in
dest buffer
+*/
+BOOLEAN MYODBCC::doStringCopyOut( SQLWCHAR *pszDest, SQLINTEGER nDestMaxChars, SQLWCHAR
*pszSrc )
+{
+ SQLINTEGER nIndex = 0;
+
+ /* sanity checks */
+ if ( !pszDest || nDestMaxChars < 1 )
+ {
+ if ( *pszSrc )
+ return false;
+ return true;
+ }
+
+ if ( !pszSrc )
+ {
+ *pszDest = '\0';
+ return true; /* ok - but nothing to copy */
+ }
+
+ /* copy chars while room in pszDest or end of pszSrc */
+ for ( nIndex = 0; nIndex < nDestMaxChars; nIndex++ )
+ {
+ pszDest[nIndex] = pszSrc[nIndex];
+ if ( pszSrc[nIndex] == '\0' )
+ return true;
+ }
+
+ /* pszDest full - ensure last char is null terminator */
+ pszDest[nIndex-1] = '\0';
+
+ /* results are truncated */
+ return false;
+}
+
+
void MYODBCC::doFree( void *p )
{
if ( p )
Modified: MYODBCC/include/MYODBCC.h
===================================================================
--- MYODBCC/include/MYODBCC.h 2006-05-18 21:38:18 UTC (rev 257)
+++ MYODBCC/include/MYODBCC.h 2006-05-19 06:50:17 UTC (rev 258)
@@ -250,6 +250,9 @@
static BOOLEAN doStrNCpy( SQLWCHAR *pszDest, size_t nSizeInWords, const SQLWCHAR
*pszSrc );
#endif
+ static BOOLEAN doStringCopyOut( SQLCHAR *pszDest, SQLINTEGER nDestMaxChars, SQLCHAR
*pszSrc );
+ static BOOLEAN doStringCopyOut( SQLWCHAR *pszDest, SQLINTEGER nDestMaxChars, SQLWCHAR
*pszSrc );
+
static void doFree( void *p );
static BOOLEAN isConnectAttr( SQLINTEGER nAttribute );
Modified: MYSQLPlus/MYSQLPlusLib/MResult.cpp
===================================================================
--- MYSQLPlus/MYSQLPlusLib/MResult.cpp 2006-05-18 21:38:18 UTC (rev 257)
+++ MYSQLPlus/MYSQLPlusLib/MResult.cpp 2006-05-19 06:50:17 UTC (rev 258)
@@ -41,7 +41,6 @@
pnIndicator = NULL;
nTargetTypeAdjusted = SQL_C_CHAR;
- nBytesRemaining = 0;
nIndicator = SQL_NO_TOTAL;
variantData.clear();
pDescriptorRecordIRD = NULL;
@@ -56,7 +55,7 @@
MYODBCDbgEnter();
if ( this->nColumn == nColumn &&
- nBytesRemaining > 0 &&
+ !variantData.isNull() &&
this->nTargetType == nTargetType &&
MDescriptorRecordIRD::isVariableLength( nType ) )
{
@@ -1007,6 +1006,14 @@
| SQL_C_CHAR | Byte length of data < BufferLength | Data | Length
of data in bytes | n/a |
| | Byte length of data >= BufferLength | Truncated data | Length
of data in bytes | 01004 |
+-------------+-------------------------------------+-----------------+-------------------------+----------+
+
+ When character data is returned from the driver to the application, the driver
must always null-terminate it.
+ This gives the application the choice of whether to handle the data as a string
or a character array. If the
+ application buffer is not large enough to return all of the character data, the
driver truncates it to the byte
+ length of the buffer less the number of bytes required by the null-termination
character, null-terminates the
+ truncated data, and stores it in the buffer. Therefore, applications must always
allocate extra space for the
+ null-termination character in buffers used to retrieve character data. For
example, a 51-byte buffer is needed
+ to retrieve 50 characters of data.
*/
if ( !resultGetData.variantData.canConvert<QString>() )
@@ -1015,16 +1022,24 @@
QString stringData = resultGetData.variantData.toString();
if ( resultGetData.pTarget && resultGetData.nBytesMax )
{
- MYODBCC::doStrNCpy( (SQLCHAR*)resultGetData.pTarget, resultGetData.nBytesMax,
stringData.toAscii().data() );
- if ( resultGetData.nBytesMax >= stringData.length() )
+ if ( MYODBCC::doStringCopy( (SQLCHAR*)resultGetData.pTarget,
resultGetData.nBytesMax, stringData.toAscii().data() ) )
+ {
+ variantData.clear();
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining = 0;
+ }
+ else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
stringData.length() - resultGetData.nBytesMax;
+ variantData.setValue( stringData.mid( resultGetData.nBytesMax - 1 ) );
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
}
else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
stringData.length();
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
- resultGetData.nBytesRemaining = ( stringData.length() + 1 ) -
resultGetData.nBytesMax;
- if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
resultGetData.nBytesRemaining;
-
MYODBCDbgReturn( SQL_SUCCESS );
}
@@ -1041,6 +1056,14 @@
| SQL_C_WCHAR | Character length of data < BufferLength | Data |
Length of data in characters | n/a |
| | Character length of data >= BufferLength | Truncated data |
Length of data in characters | 01004 |
+-------------+------------------------------------------+-----------------+------------------------------+----------+
+
+ When character data is returned from the driver to the application, the driver
must always null-terminate it.
+ This gives the application the choice of whether to handle the data as a string
or a character array. If the
+ application buffer is not large enough to return all of the character data, the
driver truncates it to the byte
+ length of the buffer less the number of bytes required by the null-termination
character, null-terminates the
+ truncated data, and stores it in the buffer. Therefore, applications must always
allocate extra space for the
+ null-termination character in buffers used to retrieve character data. For
example, a 51-byte buffer is needed
+ to retrieve 50 characters of data.
*/
if ( !resultGetData.variantData.canConvert<QString>() )
@@ -1049,16 +1072,24 @@
QString stringData = resultGetData.variantData.toString();
if ( resultGetData.pTarget && resultGetData.nBytesMax )
{
- MYODBCC::doStrNCpy( (SQLWCHAR*)resultGetData.pTarget, resultGetData.nBytesMax /
sizeof(SQLWCHAR), stringData.utf16() );
- if ( resultGetData.nBytesMax >= stringData.length() / sizeof(SQLWCHAR) )
+ if ( MYODBCC::doStringCopy( (SQLWCHAR*)resultGetData.pTarget,
resultGetData.nBytesMax / sizeof(SQLWCHAR), stringData.utf16() ) )
+ {
+ variantData.clear();
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining = 0;
+ }
+ else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
stringData.length() * sizeof(SQLWCHAR) - resultGetData.nBytesMax;
+ variantData.setValue( stringData.mid( (resultGetData.nBytesMax - 1) /
sizeof(SQLWCHAR) ) );
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
}
else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
stringData.length() * sizeof(SQLWCHAR);
MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
- resultGetData.nBytesRemaining = ( stringData.length() + 1 ) - resultGetData.nBytesMax
/ sizeof(SQLWCHAR);
- if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
resultGetData.nBytesRemaining;
-
MYODBCDbgReturn( SQL_SUCCESS );
}
@@ -1231,13 +1262,32 @@
{
MYODBCDbgEnter();
+ if ( !resultGetData.variantData.canConvert<QByteArray>() )
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_07006 ) );
+
QByteArray bytearray = resultGetData.variantData.toByteArray();
- MYODBCC::doMemCpy( resultGetData.pTarget, bytearray.constData(),
resultGetData.nBytesMax );
+ if ( resultGetData.pTarget && resultGetData.nBytesMax )
+ {
+ MYODBCC::doMemCpy( resultGetData.pTarget, bytearray.constData(), min(
resultGetData.nBytesMax, bytearray.size() ) );
+ if ( bytearray.size() <= resultGetData.nBytesMax )
+ {
+ variantData.clear();
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining = 0;
+ }
+ else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
bytearray.size() - resultGetData.nBytesMax;
+ variantData.setValue( bytearray.mid( resultGetData.nBytesMax - 1 ) );
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
+ }
+ else
+ {
+ if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
bytearray.size();
+ MYODBCDbgReturn( getDiagnostic()->doAppend( MDiagnostic::DIA_01004 ) );
+ }
- resultGetData.nBytesRemaining = bytearray.size() - resultGetData.nBytesMax;
- if ( resultGetData.pnBytesRemaining ) *resultGetData.pnBytesRemaining =
resultGetData.nBytesRemaining;
-
MYODBCDbgReturn( SQL_SUCCESS );
}
Modified: MYSQLPlus/MYSQLPlusLib/MResult.h
===================================================================
--- MYSQLPlus/MYSQLPlusLib/MResult.h 2006-05-18 21:38:18 UTC (rev 257)
+++ MYSQLPlus/MYSQLPlusLib/MResult.h 2006-05-19 06:50:17 UTC (rev 258)
@@ -41,7 +41,6 @@
/* these are additional fields which assist in maintaining our getData state */
SQLSMALLINT nTargetTypeAdjusted; /*!< is nTargetType, SQL_C_DEFAULT
derived, or ARD derived */
- SQLINTEGER nBytesRemaining; /*!< cached ver of value at
pnBytesRemaining */
SQLINTEGER nIndicator; /*!< cached ver of value at
pnIndicator */
QVariant variantData; /*!< resultset cell data
*/
MDescriptorRecordIRD * pDescriptorRecordIRD; /*!< descriptor describing the
resultset column */
| Thread |
|---|
| • Connector/ODBC 5 commit: r258 - MYODBCC/MYODBCCLib MYODBCC/include MYSQLPlus/MYSQLPlusLib | pharvey | 19 May |