diff options
author | Lionel Elie Mamane <lionel@mamane.lu> | 2012-10-26 18:57:34 +0200 |
---|---|---|
committer | Lionel Elie Mamane <lionel@mamane.lu> | 2012-10-26 19:12:23 +0200 |
commit | 2c54307713160295ad51244eee41ef959a7fd55a (patch) | |
tree | 1cba5a7f1fdafd963e53174294156153a0f245b2 /connectivity | |
parent | 626da7211498429b55eba3b438d82e5119d3ec68 (diff) |
ODBC PreparedStatement Parameters: redesign setXXX handling
More type-safe way, instead of void* everywhere
void* instead of sal_Int8 for raw memory / multi-use buffers
Fixed more issues than I care to count, but at least:
- updates to a DECIMAL were truncated to integer because DecimalDigits set to 0
maybe/probably also NUMERIC
- setObjectWithInfo(... DataType::LONGVARCHAR ...) was passed as AT_EXEC, but the buffer was already free()d by then -> crash or wrong data
Change-Id: I0e6791a05b96fb345bfe3f911386263e6cfedde9
Diffstat (limited to 'connectivity')
-rw-r--r-- | connectivity/source/drivers/odbcbase/OPreparedStatement.cxx | 349 | ||||
-rw-r--r-- | connectivity/source/drivers/odbcbase/OResultSet.cxx | 4 | ||||
-rw-r--r-- | connectivity/source/drivers/odbcbase/OTools.cxx | 195 | ||||
-rw-r--r-- | connectivity/source/inc/odbc/OBoundParam.hxx | 78 | ||||
-rw-r--r-- | connectivity/source/inc/odbc/OPreparedStatement.hxx | 14 | ||||
-rw-r--r-- | connectivity/source/inc/odbc/OTools.hxx | 38 |
6 files changed, 251 insertions, 427 deletions
diff --git a/connectivity/source/drivers/odbcbase/OPreparedStatement.cxx b/connectivity/source/drivers/odbcbase/OPreparedStatement.cxx index 7689ac70ebe9..5e43eb17f6cc 100644 --- a/connectivity/source/drivers/odbcbase/OPreparedStatement.cxx +++ b/connectivity/source/drivers/odbcbase/OPreparedStatement.cxx @@ -37,6 +37,8 @@ #include "connectivity/FValue.hxx" #include "resource/common_res.hrc" #include "connectivity/sqlparse.hxx" +#include <boost/type_traits/remove_reference.hpp> +#include <boost/type_traits/is_same.hpp> using namespace ::comphelper; using namespace connectivity; @@ -52,6 +54,13 @@ using namespace com::sun::star::util; IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement"); +namespace +{ + // for now, never use wchar, + // but most of code is prepared to handle it + // in case we make this configurable + const bool useWChar = false; +} OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql) :OStatement_BASE2(_pConnection) @@ -233,8 +242,7 @@ sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, Run void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) { - ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding())); - setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x); + setParameter(parameterIndex, DataType::CHAR, invalid_scale, x); } // ------------------------------------------------------------------------- @@ -269,111 +277,189 @@ Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLE void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException) { - ::osl::MutexGuard aGuard( m_aMutex ); + // Set the parameter as if it were an integer + setInt (parameterIndex, x ? 1 : 0 ); +} +// ------------------------------------------------------------------------- +// The MutexGuard must _already_ be taken! +void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex) +{ checkDisposed(OStatement_BASE::rBHelper.bDisposed); + prepareStatement(); + checkParameterIndex(parameterIndex); + OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); +} +// ------------------------------------------------------------------------- +template <typename T> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex, const sal_Int32 i_nType, const SQLULEN i_nColSize, const T i_Value) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + setParameterPre(parameterIndex); - sal_Int32 value = 0; + typedef typename boost::remove_reference< T >::type TnoRef; - // If the parameter is sal_True, set the value to 1 - if (x) { - value = 1; - } + TnoRef *bindBuf = static_cast< TnoRef* >( allocBindBuf(parameterIndex, sizeof(i_Value)) ); + *bindBuf = i_Value; - // Set the parameter as if it were an integer - setInt (parameterIndex, value); + setParameter(parameterIndex, i_nType, i_nColSize, invalid_scale, bindBuf, sizeof(i_Value), sizeof(i_Value)); } // ------------------------------------------------------------------------- -void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData) + +void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const sal_Int16 _nScale, const ::rtl::OUString &_sData) { ::osl::MutexGuard aGuard( m_aMutex ); - checkDisposed(OStatement_BASE::rBHelper.bDisposed); - - prepareStatement(); - // Allocate a buffer to be used in binding. This will be - // a 'permanent' buffer that the bridge will fill in with - // the bound data in native format. + setParameterPre(parameterIndex); + assert (_nType == DataType::VARCHAR || _nType == DataType::CHAR || _nType == DataType::DECIMAL || _nType == DataType::NUMERIC); - checkParameterIndex(parameterIndex); - sal_Int32 nRealSize = _nSize; - SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType)); - switch(fSqlType) + sal_Int32 nCharLen; + sal_Int32 nByteLen; + void *pData; + if (useWChar) { - case SQL_CHAR: - case SQL_VARCHAR: - case SQL_DECIMAL: - case SQL_NUMERIC: - ++nRealSize; - break; - case SQL_BINARY: - case SQL_VARBINARY: - nRealSize=1; //dummy buffer, binary data isn't copied - break; - default: - break; + /* + * On Windows, wchar is 16 bits (UTF-16 encoding), the ODBC "W" variants functions take UTF-16 encoded strings + * and character lengths are number of UTF-16 codepoints. + * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms716246%28v=vs.85%29.aspx + * ODBC Programmer's reference > Developing Applications > Programming Considerations > Unicode > Unicode Function Arguments + * http://support.microsoft.com/kb/294169 + * + * UnixODBC can be configured at compile-time so that the "W" variants expect + * UTF-16 or UTF-32 encoded strings, and character lengths are number of codepoints. + * However, UTF-16 is the default, what all/most distributions do + * and the established API that most drivers implement. + * As wchar is often 32 bits, this differs from C-style strings of wchar! + * + * Our internal OUString storage is always UTF-16, so no conversion to do here. + */ + BOOST_STATIC_ASSERT( sizeof(sal_Unicode) == 2 ); + nCharLen = _sData.getLength(); + nByteLen = nCharLen * sizeof(sal_Unicode); + pData = allocBindBuf(parameterIndex, nByteLen); + memcpy(pData, _sData.getStr(), nByteLen); + } + else + { + ::rtl::OString sOData( ::rtl::OUStringToOString(_sData, getOwnConnection()->getTextEncoding()) ); + nCharLen = sOData.getLength(); + nByteLen = nCharLen; + pData = allocBindBuf(parameterIndex, nByteLen); + memcpy(pData, sOData.getStr(), nByteLen); } - sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize); + setParameter( parameterIndex, _nType, nCharLen, _nScale, pData, nByteLen, nByteLen ); +} +// ------------------------------------------------------------------------- +void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const Sequence< sal_Int8 > &x) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + setParameterPre(parameterIndex); - OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); - OTools::bindParameter( m_pConnection, - m_aStatementHandle, - parameterIndex, - bindBuf, - getLengthBuf(parameterIndex), - fSqlType, - sal_False, - m_pConnection->useOldDateFormat(), - _pData, - (Reference <XInterface>)*this, - getOwnConnection()->getTextEncoding()); + assert(_nType == DataType::BINARY || _nType == DataType::VARBINARY); + + // don't copy the sequence, just point the ODBC directly at the sequence's storage array + // Why BINARY/Sequence is treated differently than strings (which are copied), I'm not sure + OSL_VERIFY(allocBindBuf(parameterIndex, 0) == NULL); + boundParams[parameterIndex-1].setSequence(x); // this ensures that the sequence stays alive + + setParameter( parameterIndex, _nType, x.getLength(), invalid_scale, x.getConstArray(), x.getLength(), x.getLength() ); +} +// ------------------------------------------------------------------------- +void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const SQLULEN _nColumnSize, const sal_Int32 _nScale, const void* const _pData, const SQLULEN _nDataLen, const SQLLEN _nDataAllocLen) +{ + SQLSMALLINT fCType, fSqlType; + OTools::getBindTypes(useWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType); + + SQLLEN *pDataLen=boundParams[parameterIndex-1].getBindLengthBuffer(); + *pDataLen=_nDataLen; + + SQLRETURN nRetcode; + nRetcode = (*(T3SQLBindParameter)m_pConnection->getOdbcFunction(ODBC3SQLBindParameter))( + m_aStatementHandle, + // checkParameterIndex guarantees this is safe + static_cast<SQLUSMALLINT>(parameterIndex), + SQL_PARAM_INPUT, + fCType, + fSqlType, + _nColumnSize, + _nScale, + // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT + const_cast<void*>(_pData), + _nDataAllocLen, + pDataLen); + + OTools::ThrowException(m_pConnection, nRetcode, m_aStatementHandle, SQL_HANDLE_STMT, *this); } // ----------------------------------------------------------------------------- -void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException) +void SAL_CALL OPreparedStatement::setByte( const sal_Int32 parameterIndex, const sal_Int8 x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x); + setScalarParameter(parameterIndex, DataType::TINYINT, 3, x); } // ------------------------------------------------------------------------- - +// For older compilers (that do not support partial specialisation of class templates) +// uncomment if necessary (safe also on compilers that *do* support partial specialisation) +//BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(DATE_STRUCT); +//BOOST_STATIC_ASSERT((boost::is_same<DATE_STRUCT, boost::remove_reference<DATE_STRUCT&>::type>::value)); void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException) { - DATE_STRUCT x = OTools::DateToOdbcDate(aData); - setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x); + DATE_STRUCT x(OTools::DateToOdbcDate(aData)); + setScalarParameter<DATE_STRUCT&>(parameterIndex, DataType::DATE, 10, x); } // ------------------------------------------------------------------------- - void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException) { - TIME_STRUCT x = OTools::TimeToOdbcTime(aVal); - setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x); + const sal_uInt16 hundredths (aVal.HundredthSeconds); + SQLULEN nColSize; + if(hundredths == 0) + nColSize = 8; + else if(hundredths % 10 == 0) + nColSize = 10; + else + nColSize = 11; + TIME_STRUCT x(OTools::TimeToOdbcTime(aVal)); + setScalarParameter<TIME_STRUCT&>(parameterIndex, DataType::TIME, nColSize, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException) { - TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal); - setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x); + sal_uInt16 s(aVal.Seconds); + sal_uInt16 hundredths(aVal.HundredthSeconds); + SQLULEN nColSize; + if(hundredths == 0) + { + if (s == 0) + nColSize=16; + else + nColSize=19; + } + else if(hundredths % 10 == 0) + nColSize = 21; + else + nColSize = 22; + + TIMESTAMP_STRUCT x(OTools::DateTimeToTimestamp(aVal)); + setScalarParameter<TIMESTAMP_STRUCT&>(parameterIndex, DataType::TIMESTAMP, nColSize, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x); + setScalarParameter(parameterIndex, DataType::DOUBLE, 15, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x); + setScalarParameter(parameterIndex, DataType::FLOAT, 15, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x); + setScalarParameter(parameterIndex, DataType::INTEGER, 10, x); } // ------------------------------------------------------------------------- @@ -381,57 +467,44 @@ void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x { try { - setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x); + setScalarParameter(parameterIndex, DataType::BIGINT, 19, x); } catch(SQLException&) { - setString(parameterIndex,ORowSetValue(x)); + setString(parameterIndex, ORowSetValue(x)); } } // ------------------------------------------------------------------------- -void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException) +void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, const sal_Int32 _nType ) throw(SQLException, RuntimeException) { ::osl::MutexGuard aGuard( m_aMutex ); - checkDisposed(OStatement_BASE::rBHelper.bDisposed); - + setParameterPre(paramterIndex): - prepareStatement(); - // Get the buffer needed for the length - checkParameterIndex(parameterIndex); + OSL_VERIFY(allocBindBuf(parameterIndex, 0) == NULL); + SQLLEN * const lenBuf = getLengthBuf (parameterIndex); + *lenBuf = SQL_NULL_DATA; - sal_Int8* lenBuf = getLengthBuf (parameterIndex); - *(SQLLEN*)lenBuf = SQL_NULL_DATA; - - - SQLLEN prec = 0; - SQLULEN nColumnSize = 0; - if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR) - { - prec = 1; - nColumnSize = 1; - } - SQLSMALLINT fCType = 0; - SQLSMALLINT fSqlType = 0; + SQLSMALLINT fCType; + SQLSMALLINT fSqlType; - SQLSMALLINT nDecimalDigits = 0; - OTools::getBindTypes( sal_False, + OTools::getBindTypes( useWChar, m_pConnection->useOldDateFormat(), - (SQLSMALLINT)sqlType, + OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType); SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle, - (SQLUSMALLINT)parameterIndex, - (SQLSMALLINT)SQL_PARAM_INPUT, + static_cast<SQLUSMALLINT>(parameterIndex), + SQL_PARAM_INPUT, fCType, fSqlType, - nColumnSize, - nDecimalDigits, + 0, + 0, NULL, - prec, - (SQLLEN*)lenBuf + 0, + lenBuf ); OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this); } @@ -440,14 +513,14 @@ void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 s void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException) { if ( x.is() ) - setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR); + setStream(parameterIndex, x->getCharacterStream(), x->length(), DataType::LONGVARCHAR); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException) { if ( x.is() ) - setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR); + setStream(parameterIndex, x->getBinaryStream(), x->length(), DataType::LONGVARBINARY); } // ------------------------------------------------------------------------- @@ -462,12 +535,6 @@ void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Re ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this ); } // ------------------------------------------------------------------------- -void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x ) -{ - ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding())); - setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x); -} -// ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException) { checkDisposed(OStatement_BASE::rBHelper.bDisposed); @@ -479,31 +546,29 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c switch (sqlType) { + case DataType::CHAR: case DataType::VARCHAR: case DataType::LONGVARCHAR: if(x.hasValue()) { ::rtl::OUString sStr; x >>= sStr; - ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding())); - setParameter(parameterIndex,sqlType,aString.getLength(),&aString); + setParameter(parameterIndex, sqlType, scale, sStr); } else setNull(parameterIndex,sqlType); break; case DataType::DECIMAL: - { - ORowSetValue aValue; - aValue.fill(x); - setDecimal(parameterIndex,aValue); - } - break; case DataType::NUMERIC: + if(x.hasValue()) { ORowSetValue aValue; aValue.fill(x); - setString(parameterIndex,aValue); + // TODO: make sure that this calls the string overload + setParameter(parameterIndex, sqlType, scale, aValue); } + else + setNull(parameterIndex,sqlType); break; default: ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale); @@ -513,9 +578,6 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException) { - ::osl::MutexGuard aGuard( m_aMutex ); - checkDisposed(OStatement_BASE::rBHelper.bDisposed); - setNull(parameterIndex,sqlType); } // ------------------------------------------------------------------------- @@ -531,20 +593,21 @@ void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x); + setScalarParameter(parameterIndex, DataType::SMALLINT, 5, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { - setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x); - boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive + setParameter(parameterIndex, DataType::BINARY, x); } // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) { + // LEM: It is quite unclear to me what the interface here is. + // The XInputStream provides *bytes*, not characters. setStream(parameterIndex, x, length, DataType::LONGVARCHAR); } // ------------------------------------------------------------------------- @@ -557,6 +620,7 @@ void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, con void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) { + ::osl::MutexGuard aGuard( m_aMutex ); prepareStatement(); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS); @@ -566,6 +630,7 @@ void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, Runtim // ------------------------------------------------------------------------- void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) { + ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::clearBatch", *this ); // clearParameters( ); // m_aBatchList.erase(); } @@ -573,11 +638,14 @@ void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeExce void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) { + ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::addBatch", *this ); } // ------------------------------------------------------------------------- Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) { + ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::executeBatch", *this ); + // not reached, but keep -Werror happy return Sequence< sal_Int32 > (); } // ------------------------------------------------------------------------- @@ -607,12 +675,6 @@ void OPreparedStatement::initBoundParam () throw(SQLException) boundParams = new OBoundParam[numParams]; - // initialize each bound parameter - - for (sal_Int32 i = 0; i < numParams; i++) - { - boundParams[i].initialize (); - } } } // ------------------------------------------------------------------------- @@ -623,14 +685,13 @@ void OPreparedStatement::initBoundParam () throw(SQLException) // parameter. //-------------------------------------------------------------------- -sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen) +void* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen) { - sal_Int8* b = NULL; + void* b = NULL; // Sanity check the parameter number - if ((index >= 1) && - (index <= numParams) && bufLen > 0 ) + if ((index >= 1) && (index <= numParams)) { b = boundParams[index - 1].allocBindDataBuffer(bufLen); } @@ -644,9 +705,9 @@ sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen) // Gets the length buffer for the given parameter index //-------------------------------------------------------------------- -sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index) +SQLLEN* OPreparedStatement::getLengthBuf (sal_Int32 index) { - sal_Int8* b = NULL; + SQLLEN* b = NULL; // Sanity check the parameter number @@ -737,7 +798,7 @@ void OPreparedStatement::setStream( sal_Int32 ParameterIndex, const Reference< XInputStream>& x, SQLLEN length, - sal_Int32 SQLtype) + sal_Int32 _nType) throw(SQLException) { ::osl::MutexGuard aGuard( m_aMutex ); @@ -749,35 +810,33 @@ void OPreparedStatement::setStream( checkParameterIndex(ParameterIndex); // Get the buffer needed for the length - sal_Int8* lenBuf = getLengthBuf(ParameterIndex); + SQLLEN * const lenBuf = getLengthBuf(ParameterIndex); // Allocate a new buffer for the parameter data. This buffer // will be returned by SQLParamData (it is set to the parameter - // number, a 4-sal_Int8 integer) + // number, a sal_Int32) - sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4); + sal_Int32* dataBuf = static_cast<sal_Int32*>( allocBindBuf(ParameterIndex, sizeof(ParameterIndex)) ); + *dataBuf = ParameterIndex; // Bind the parameter with SQL_LEN_DATA_AT_EXEC - SQLSMALLINT Ctype = SQL_C_CHAR; - SQLLEN atExec = SQL_LEN_DATA_AT_EXEC (length); - memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex)); - memcpy (lenBuf, &atExec, sizeof (atExec)); + *lenBuf = SQL_LEN_DATA_AT_EXEC (length); - if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY)) - Ctype = SQL_C_BINARY; + SQLSMALLINT fCType, fSqlType; + OTools::getBindTypes(useWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); N3SQLBindParameter(m_aStatementHandle, - (SQLUSMALLINT)ParameterIndex, - (SQLUSMALLINT)SQL_PARAM_INPUT, - Ctype, - (SQLSMALLINT)SQLtype, - (SQLULEN)length, - 0, - dataBuf, - sizeof(ParameterIndex), - (SQLLEN*)lenBuf); + static_cast<SQLUSMALLINT>(ParameterIndex), + SQL_PARAM_INPUT, + fCType, + fSqlType, + length, + invalid_scale, + dataBuf, + sizeof(ParameterIndex), + lenBuf); // Save the input stream boundParams[ParameterIndex - 1].setInputStream (x, length); @@ -840,7 +899,9 @@ void OPreparedStatement::prepareStatement() // ----------------------------------------------------------------------------- void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex) { - if( !_parameterIndex || _parameterIndex > numParams) + if( _parameterIndex > numParams || + _parameterIndex < 1 || + _parameterIndex > std::numeric_limits<SQLUSMALLINT>::max() ) { ::connectivity::SharedResources aResources; const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX, diff --git a/connectivity/source/drivers/odbcbase/OResultSet.cxx b/connectivity/source/drivers/odbcbase/OResultSet.cxx index 7cfebcb23f4d..96d7d8ee4672 100644 --- a/connectivity/source/drivers/odbcbase/OResultSet.cxx +++ b/connectivity/source/drivers/odbcbase/OResultSet.cxx @@ -1058,7 +1058,7 @@ void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x ) throw( void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException) { sal_Int32 nType = m_aRow[columnIndex].getTypeKind(); - SQLSMALLINT nOdbcType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(nType)); + SQLSMALLINT nOdbcType = OTools::jdbcTypeToOdbc(nType); m_aRow[columnIndex] = x; m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarchar will be recognized by fillNeededData updateValue(columnIndex,nOdbcType,(void*)&x); @@ -1067,7 +1067,7 @@ void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUSt void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException) { sal_Int32 nType = m_aRow[columnIndex].getTypeKind(); - SQLSMALLINT nOdbcType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(nType)); + SQLSMALLINT nOdbcType = OTools::jdbcTypeToOdbc(nType); m_aRow[columnIndex] = x; m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarbinary will be recognized by fillNeededData updateValue(columnIndex,nOdbcType,(void*)&x); diff --git a/connectivity/source/drivers/odbcbase/OTools.cxx b/connectivity/source/drivers/odbcbase/OTools.cxx index b38dd2b29766..3e327803513a 100644 --- a/connectivity/source/drivers/odbcbase/OTools.cxx +++ b/connectivity/source/drivers/odbcbase/OTools.cxx @@ -150,190 +150,6 @@ void OTools::getValue( OConnection* _pConnection, _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False); _bWasNull = pcbValue == SQL_NULL_DATA; } -// ----------------------------------------------------------------------------- -void OTools::bindParameter( OConnection* _pConnection, - SQLHANDLE _hStmt, - sal_Int32 nPos, - sal_Int8*& pDataBuffer, - sal_Int8* pLenBuffer, - SQLSMALLINT _nODBCtype, - sal_Bool _bUseWChar, - sal_Bool _bUseOldTimeDate, - const void* _pValue, - const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, - rtl_TextEncoding _nTextEncoding) - throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindParameter" ); - SQLRETURN nRetcode; - SQLSMALLINT fSqlType; - SQLSMALLINT fCType; - SQLLEN nMaxLen = 0; - SQLLEN* pLen = (SQLLEN*)pLenBuffer; - SQLULEN nColumnSize=0; - SQLSMALLINT nDecimalDigits=0; - bool atExec; - - OTools::getBindTypes(_bUseWChar,_bUseOldTimeDate,_nODBCtype,fCType,fSqlType); - - OTools::bindData(_nODBCtype,_bUseWChar,pDataBuffer,pLen,_pValue,_nTextEncoding,nColumnSize, atExec); - if ((nColumnSize == 0) && (fSqlType == SQL_CHAR || fSqlType == SQL_VARCHAR || fSqlType == SQL_LONGVARCHAR)) - nColumnSize = 1; - - if (atExec) - memcpy(pDataBuffer,&nPos,sizeof(nPos)); - - nRetcode = (*(T3SQLBindParameter)_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(_hStmt, - (SQLUSMALLINT)nPos, - SQL_PARAM_INPUT, - fCType, - fSqlType, - nColumnSize, - nDecimalDigits, - pDataBuffer, - nMaxLen, - pLen); - - OTools::ThrowException(_pConnection,nRetcode,_hStmt,SQL_HANDLE_STMT,_xInterface); -} -// ----------------------------------------------------------------------------- -void OTools::bindData( SQLSMALLINT _nOdbcType, - sal_Bool _bUseWChar, - sal_Int8 *&_pData, - SQLLEN*& pLen, - const void* _pValue, - rtl_TextEncoding _nTextEncoding, - SQLULEN& _nColumnSize, - bool &atExec) -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::bindData" ); - _nColumnSize = 0; - atExec = false; - - switch (_nOdbcType) - { - case SQL_CHAR: - case SQL_VARCHAR: - case SQL_DECIMAL: - if(_bUseWChar) - { - *pLen = SQL_NTS; - ::rtl::OUString sStr(*(::rtl::OUString*)_pValue); - _nColumnSize = sStr.getLength(); - *((rtl::OUString*)_pData) = sStr; - - // Pointer on Char* - _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); - } - else - { - ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); - *pLen = SQL_NTS; - _nColumnSize = aString.getLength(); - memcpy(_pData,aString.getStr(),aString.getLength()); - ((sal_Int8*)_pData)[aString.getLength()] = '\0'; - } - break; - - case SQL_BIGINT: - *((sal_Int64*)_pData) = *(sal_Int64*)_pValue; - *pLen = sizeof(sal_Int64); - _nColumnSize = *pLen; - break; - - case SQL_NUMERIC: - if(_bUseWChar) - { - ::rtl::OUString aString = rtl::OUString::valueOf(*(double*)_pValue); - _nColumnSize = aString.getLength(); - *pLen = _nColumnSize; - *((rtl::OUString*)_pData) = aString; - // Pointer on Char* - _pData = (sal_Int8*)((rtl::OUString*)_pData)->getStr(); - } - else - { - ::rtl::OString aString = ::rtl::OString::valueOf(*(double*)_pValue); - _nColumnSize = aString.getLength(); - *pLen = _nColumnSize; - memcpy(_pData,aString.getStr(),aString.getLength()); - ((sal_Int8*)_pData)[_nColumnSize] = '\0'; - } break; - case SQL_BIT: - case SQL_TINYINT: - *((sal_Int8*)_pData) = *(sal_Int8*)_pValue; - *pLen = sizeof(sal_Int8); - break; - - case SQL_SMALLINT: - *((sal_Int16*)_pData) = *(sal_Int16*)_pValue; - *pLen = sizeof(sal_Int16); - break; - case SQL_INTEGER: - *((sal_Int32*)_pData) = *(sal_Int32*)_pValue; - *pLen = sizeof(sal_Int32); - break; - case SQL_FLOAT: - *((float*)_pData) = *(float*)_pValue; - *pLen = sizeof(float); - break; - case SQL_REAL: - case SQL_DOUBLE: - *((double*)_pData) = *(double*)_pValue; - *pLen = sizeof(double); - break; - case SQL_BINARY: - case SQL_VARBINARY: - { - const ::com::sun::star::uno::Sequence< sal_Int8 >* pSeq = static_cast< const ::com::sun::star::uno::Sequence< sal_Int8 >* >(_pValue); - OSL_ENSURE(pSeq,"OTools::bindData: Sequence is null!"); - - if(pSeq) - { - _pData = (sal_Int8*)pSeq->getConstArray(); - *pLen = pSeq->getLength(); - } - } - break; - case SQL_LONGVARBINARY: - { - sal_Int32 nLen = 0; - nLen = ((const ::com::sun::star::uno::Sequence< sal_Int8 > *)_pValue)->getLength(); - *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); - } - atExec = true; - break; - case SQL_LONGVARCHAR: - { - sal_Int32 nLen = 0; - if(_bUseWChar) - nLen = sizeof(sal_Unicode) * ((::rtl::OUString*)_pValue)->getLength(); - else - { - ::rtl::OString aString(::rtl::OUStringToOString(*(::rtl::OUString*)_pValue,_nTextEncoding)); - nLen = aString.getLength(); - } - *pLen = (SQLLEN)SQL_LEN_DATA_AT_EXEC(nLen); - atExec = true; - } break; - case SQL_DATE: - *(DATE_STRUCT*)_pData = *(DATE_STRUCT*)_pValue; - *pLen = (SQLLEN)sizeof(DATE_STRUCT); - _nColumnSize = 10; - break; - case SQL_TIME: - *(TIME_STRUCT*)_pData = *(TIME_STRUCT*)_pValue; - *pLen = (SQLLEN)sizeof(TIME_STRUCT); - _nColumnSize = 8; - break; - case SQL_TIMESTAMP: - *(TIMESTAMP_STRUCT*)_pData = *(TIMESTAMP_STRUCT*)_pValue; - *pLen = (SQLLEN)sizeof(TIMESTAMP_STRUCT); - // 20+sub-zero precision; we have hundredths of seconds - _nColumnSize = 22; - break; - } -} // ------------------------------------------------------------------------- void OTools::bindValue( OConnection* _pConnection, SQLHANDLE _aStatementHandle, @@ -342,7 +158,7 @@ void OTools::bindValue( OConnection* _pConnection, SQLSMALLINT _nMaxLen, const void* _pValue, void* _pData, - SQLLEN *pLen, + SQLLEN * const pLen, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, rtl_TextEncoding _nTextEncoding, sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) @@ -779,7 +595,7 @@ void OTools::GetInfo(OConnection* _pConnection, _aConnectionHandle,SQL_HANDLE_DBC,_xInterface); } // ------------------------------------------------------------------------- -sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) +sal_Int32 OTools::MapOdbcType2Jdbc(SQLSMALLINT _nType) { sal_Int32 nValue = DataType::VARCHAR; switch(_nType) @@ -857,7 +673,7 @@ sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) // jdbcTypeToOdbc // Convert the JDBC SQL type to the correct ODBC type //-------------------------------------------------------------------- -sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) +SQLSMALLINT OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" ); // For the most part, JDBC types match ODBC types. We'll @@ -876,6 +692,11 @@ sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) case DataType::TIMESTAMP: odbcType = SQL_TIMESTAMP; break; + // ODBC doesn't have any notion of CLOB or BLOB + case DataType::CLOB: + odbcType = SQL_LONGVARCHAR; + case DataType::BLOB: + odbcType = SQL_LONGVARBINARY; } return odbcType; diff --git a/connectivity/source/inc/odbc/OBoundParam.hxx b/connectivity/source/inc/odbc/OBoundParam.hxx index 8e587b4f2fc2..fca532bcade9 100644 --- a/connectivity/source/inc/odbc/OBoundParam.hxx +++ b/connectivity/source/inc/odbc/OBoundParam.hxx @@ -20,6 +20,7 @@ #define _CONNECTIVITY_OBOUNPARAM_HXX_ #include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/sdbc/DataType.hpp> #include "odbc/odbcbasedllapi.hxx" namespace connectivity @@ -31,50 +32,29 @@ namespace connectivity public: OBoundParam() + : binaryData(NULL) + , paramInputStreamLen(0) + , sqlType(::com::sun::star::sdbc::DataType::SQLNULL) + , outputParameter(false) { - paramLength = NULL; - binaryData = NULL; - pA1=0; - pA2=0; - pB1=0; - pB2=0; - pC1=0; - pC2=0; - pS1=0; - pS2=0; } ~OBoundParam() { - delete [] binaryData; - delete [] paramLength; + free(binaryData); } //-------------------------------------------------------------------- - // initialize - // Perform an necessary initialization - //-------------------------------------------------------------------- - void initialize () - { - // Allocate storage for the length. Note - the length is - // stored in native format, and will have to be converted - // to a Java sal_Int32. The jdbcodbc 'C' bridge provides an - // interface to do this. - - paramLength = new sal_Int8[sizeof(SQLLEN)]; - } - - //-------------------------------------------------------------------- // allocBindDataBuffer // Allocates and returns a new bind data buffer of the specified // length //-------------------------------------------------------------------- - sal_Int8* allocBindDataBuffer (sal_Int32 bufLen) + void* allocBindDataBuffer (sal_Int32 bufLen) { - if ( binaryData ) - delete [] binaryData; - binaryData = new sal_Int8[bufLen]; - - // Reset the input stream, we are doing a new bind + // Reset the input stream and sequence, we are doing a new bind setInputStream (NULL, 0); + aSequence.realloc(0); + + free(binaryData); + binaryData = (bufLen > 0) ? malloc(bufLen) : NULL; return binaryData; } @@ -83,7 +63,7 @@ namespace connectivity // getBindDataBuffer // Returns the data buffer to be used when binding to a parameter //-------------------------------------------------------------------- - sal_Int8* getBindDataBuffer () + void* getBindDataBuffer () { return binaryData; } @@ -92,9 +72,9 @@ namespace connectivity // getBindLengthBuffer // Returns the length buffer to be used when binding to a parameter //-------------------------------------------------------------------- - sal_Int8* getBindLengthBuffer () + SQLLEN* getBindLengthBuffer () { - return paramLength; + return ¶mLength; } //-------------------------------------------------------------------- @@ -176,20 +156,20 @@ namespace connectivity // Data attributes //==================================================================== - sal_Int8* binaryData; // Storage area to be used - // when binding the parameter + void *binaryData; // Storage area to be used + // when binding the parameter - sal_Int8* paramLength; // Storage area to be used - // for the bound length of the - // parameter. Note that this - // data is in native format. + SQLLEN paramLength; // Storage area to be used + // for the bound length of the + // parameter. Note that this + // data is in native format. ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream> paramInputStream; ::com::sun::star::uno::Sequence< sal_Int8 > aSequence; // When an input stream is - // bound to a parameter, the - // input stream is saved - // until needed. + // bound to a parameter, a + // reference to the input stream is saved + // until not needed anymore. sal_Int32 paramInputStreamLen; // Length of input stream @@ -197,16 +177,6 @@ namespace connectivity // register an OUT parameter sal_Bool outputParameter; // true for OUTPUT parameters - - - sal_Int32 pA1; //pointers - sal_Int32 pA2; - sal_Int32 pB1; - sal_Int32 pB2; - sal_Int32 pC1; - sal_Int32 pC2; - sal_Int32 pS1; - sal_Int32 pS2;// reserved for strings(UTFChars) }; } } diff --git a/connectivity/source/inc/odbc/OPreparedStatement.hxx b/connectivity/source/inc/odbc/OPreparedStatement.hxx index 0d34099f39ab..139ea3fda327 100644 --- a/connectivity/source/inc/odbc/OPreparedStatement.hxx +++ b/connectivity/source/inc/odbc/OPreparedStatement.hxx @@ -46,6 +46,7 @@ namespace connectivity public OPreparedStatement_BASE { protected: + static const short invalid_scale = -1; struct Parameter { ::com::sun::star::uno::Any aValue; @@ -74,15 +75,20 @@ namespace connectivity void putParamData (sal_Int32 index) throw(::com::sun::star::sdbc::SQLException); void setStream (sal_Int32 ParameterIndex,const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream>& x, SQLLEN length,sal_Int32 SQLtype) throw(::com::sun::star::sdbc::SQLException); - sal_Int8* getLengthBuf (sal_Int32 index); - sal_Int8* allocBindBuf ( sal_Int32 index, sal_Int32 bufLen); + SQLLEN* getLengthBuf (sal_Int32 index); + void* allocBindBuf ( sal_Int32 index, sal_Int32 bufLen); void initBoundParam () throw(::com::sun::star::sdbc::SQLException); - void setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData); + void setParameterPre(sal_Int32 parameterIndex); + template <typename T> void setScalarParameter(sal_Int32 parameterIndex, sal_Int32 _nType, SQLULEN _nColumnSize, const T i_Value); + void setParameter(sal_Int32 parameterIndex, sal_Int32 _nType, SQLULEN _nColumnSize, sal_Int32 _nScale, const void* _pData, SQLULEN _nDataLen, SQLLEN _nDataAllocLen); + void setParameter(sal_Int32 parameterIndex, sal_Int32 _nType, sal_Int32 _nColumnSize, sal_Int32 _nByteSize, void* _pData); + // Wrappers for special cases + void setParameter(sal_Int32 parameterIndex, sal_Int32 _nType, sal_Int16 _nScale, const ::rtl::OUString &_sData); + void setParameter(sal_Int32 parameterIndex, sal_Int32 _nType, const com::sun::star::uno::Sequence< sal_Int8 > &_Data); sal_Bool isPrepared() const { return m_bPrepared;} void prepareStatement(); void checkParameterIndex(sal_Int32 _parameterIndex); - void setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x ); /** creates the driver specific resultset (factory) diff --git a/connectivity/source/inc/odbc/OTools.hxx b/connectivity/source/inc/odbc/OTools.hxx index 0688496a9bf1..a971d4c8edaa 100644 --- a/connectivity/source/inc/odbc/OTools.hxx +++ b/connectivity/source/inc/odbc/OTools.hxx @@ -138,8 +138,8 @@ namespace connectivity sal_Bool &_rValue, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); - static sal_Int32 MapOdbcType2Jdbc(sal_Int32 _nType); - static sal_Int32 jdbcTypeToOdbc(sal_Int32 jdbcType); + static sal_Int32 MapOdbcType2Jdbc(SQLSMALLINT _nType); + static SQLSMALLINT jdbcTypeToOdbc(sal_Int32 jdbcType); static DATE_STRUCT DateToOdbcDate(const ::com::sun::star::util::Date& x) { @@ -206,40 +206,6 @@ namespace connectivity void* _pValue, SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); - /** - bindData copies data from pValue to pData - @param _nOdbcType [in] the ODBC sql type - @param _bUseWChar [in] true when Unicode should be used - @param _pData [in/out] data copy destination - @param pLen [out] buffer length of data written to _pData - @param _pValue [in] contains the data to be copied - @param _nTextEncoding [in] the text encoding - @param _nColumnSize [out] columnSize of data written to _pData - @param atExec [out] data was not copied, but setup for data-at-execution; - caller is responsible for writing a token in _pData - */ - static void bindData( SQLSMALLINT _nOdbcType, - sal_Bool _bUseWChar, - sal_Int8 *&_pData, - SQLLEN*& pLen, - const void* _pValue, - rtl_TextEncoding _nTextEncoding, - SQLULEN& _nColumnSize, - bool &atExec); - - static void bindParameter( OConnection* _pConnection, - SQLHANDLE _hStmt, - sal_Int32 nPos, - sal_Int8*& pDataBuffer, - sal_Int8* pLenBuffer, - SQLSMALLINT _nODBCtype, - sal_Bool _bUseWChar, - sal_Bool _bUseOldTimeDate, - const void* _pValue, - const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, - rtl_TextEncoding _nTextEncoding) - throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); - static void bindValue( OConnection* _pConnection, SQLHANDLE _aStatementHandle, sal_Int32 columnIndex, |