Kaydet (Commit) 2c543077 authored tarafından Lionel Elie Mamane's avatar Lionel Elie Mamane

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
üst 626da721
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include "connectivity/FValue.hxx" #include "connectivity/FValue.hxx"
#include "resource/common_res.hrc" #include "resource/common_res.hrc"
#include "connectivity/sqlparse.hxx" #include "connectivity/sqlparse.hxx"
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_same.hpp>
using namespace ::comphelper; using namespace ::comphelper;
using namespace connectivity; using namespace connectivity;
...@@ -52,6 +54,13 @@ using namespace com::sun::star::util; ...@@ -52,6 +54,13 @@ using namespace com::sun::star::util;
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement"); 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) OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql)
:OStatement_BASE2(_pConnection) :OStatement_BASE2(_pConnection)
...@@ -233,8 +242,7 @@ sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, Run ...@@ -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) 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, invalid_scale, x);
setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -269,111 +277,189 @@ Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLE ...@@ -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) 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); 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 TnoRef *bindBuf = static_cast< TnoRef* >( allocBindBuf(parameterIndex, sizeof(i_Value)) );
if (x) { *bindBuf = i_Value;
value = 1;
}
// Set the parameter as if it were an integer setParameter(parameterIndex, i_nType, i_nColSize, invalid_scale, bindBuf, sizeof(i_Value), sizeof(i_Value));
setInt (parameterIndex, 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 ); ::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OStatement_BASE::rBHelper.bDisposed); setParameterPre(parameterIndex);
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.
assert (_nType == DataType::VARCHAR || _nType == DataType::CHAR || _nType == DataType::DECIMAL || _nType == DataType::NUMERIC);
checkParameterIndex(parameterIndex); sal_Int32 nCharLen;
sal_Int32 nRealSize = _nSize; sal_Int32 nByteLen;
SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType)); void *pData;
switch(fSqlType) if (useWChar)
{ {
case SQL_CHAR: /*
case SQL_VARCHAR: * On Windows, wchar is 16 bits (UTF-16 encoding), the ODBC "W" variants functions take UTF-16 encoded strings
case SQL_DECIMAL: * and character lengths are number of UTF-16 codepoints.
case SQL_NUMERIC: * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms716246%28v=vs.85%29.aspx
++nRealSize; * ODBC Programmer's reference > Developing Applications > Programming Considerations > Unicode > Unicode Function Arguments
break; * http://support.microsoft.com/kb/294169
case SQL_BINARY: *
case SQL_VARBINARY: * UnixODBC can be configured at compile-time so that the "W" variants expect
nRealSize=1; //dummy buffer, binary data isn't copied * UTF-16 or UTF-32 encoded strings, and character lengths are number of codepoints.
break; * However, UTF-16 is the default, what all/most distributions do
default: * and the established API that most drivers implement.
break; * 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);
}
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);
sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize); assert(_nType == DataType::BINARY || _nType == DataType::VARBINARY);
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); // don't copy the sequence, just point the ODBC directly at the sequence's storage array
OTools::bindParameter( m_pConnection, // 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, m_aStatementHandle,
parameterIndex, // checkParameterIndex guarantees this is safe
bindBuf, static_cast<SQLUSMALLINT>(parameterIndex),
getLengthBuf(parameterIndex), SQL_PARAM_INPUT,
fCType,
fSqlType, fSqlType,
sal_False, _nColumnSize,
m_pConnection->useOldDateFormat(), _nScale,
_pData, // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
(Reference <XInterface>)*this, const_cast<void*>(_pData),
getOwnConnection()->getTextEncoding()); _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) void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
{ {
DATE_STRUCT x = OTools::DateToOdbcDate(aData); DATE_STRUCT x(OTools::DateToOdbcDate(aData));
setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x); setScalarParameter<DATE_STRUCT&>(parameterIndex, DataType::DATE, 10, x);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException) void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
{ {
TIME_STRUCT x = OTools::TimeToOdbcTime(aVal); const sal_uInt16 hundredths (aVal.HundredthSeconds);
setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x); 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) void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
{ {
TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal); sal_uInt16 s(aVal.Seconds);
setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x); 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) 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) 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) 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 ...@@ -381,57 +467,44 @@ void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x
{ {
try try
{ {
setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x); setScalarParameter(parameterIndex, DataType::BIGINT, 19, x);
} }
catch(SQLException&) 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 ); ::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OStatement_BASE::rBHelper.bDisposed); setParameterPre(paramterIndex):
OSL_VERIFY(allocBindBuf(parameterIndex, 0) == NULL);
SQLLEN * const lenBuf = getLengthBuf (parameterIndex);
*lenBuf = SQL_NULL_DATA;
prepareStatement();
// Get the buffer needed for the length
checkParameterIndex(parameterIndex);
sal_Int8* lenBuf = getLengthBuf (parameterIndex); SQLSMALLINT fCType;
*(SQLLEN*)lenBuf = SQL_NULL_DATA; SQLSMALLINT fSqlType;
OTools::getBindTypes( useWChar,
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 nDecimalDigits = 0;
OTools::getBindTypes( sal_False,
m_pConnection->useOldDateFormat(), m_pConnection->useOldDateFormat(),
(SQLSMALLINT)sqlType, OTools::jdbcTypeToOdbc(_nType),
fCType, fCType,
fSqlType); fSqlType);
SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle, SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
(SQLUSMALLINT)parameterIndex, static_cast<SQLUSMALLINT>(parameterIndex),
(SQLSMALLINT)SQL_PARAM_INPUT, SQL_PARAM_INPUT,
fCType, fCType,
fSqlType, fSqlType,
nColumnSize, 0,
nDecimalDigits, 0,
NULL, NULL,
prec, 0,
(SQLLEN*)lenBuf lenBuf
); );
OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this); 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 ...@@ -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) void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException)
{ {
if ( x.is() ) 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) void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException)
{ {
if ( x.is() ) 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 ...@@ -462,12 +535,6 @@ void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Re
::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this ); ::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) 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); checkDisposed(OStatement_BASE::rBHelper.bDisposed);
...@@ -479,31 +546,29 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c ...@@ -479,31 +546,29 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c
switch (sqlType) switch (sqlType)
{ {
case DataType::CHAR:
case DataType::VARCHAR: case DataType::VARCHAR:
case DataType::LONGVARCHAR: case DataType::LONGVARCHAR:
if(x.hasValue()) if(x.hasValue())
{ {
::rtl::OUString sStr; ::rtl::OUString sStr;
x >>= sStr; x >>= sStr;
::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding())); setParameter(parameterIndex, sqlType, scale, sStr);
setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
} }
else else
setNull(parameterIndex,sqlType); setNull(parameterIndex,sqlType);
break; break;
case DataType::DECIMAL: case DataType::DECIMAL:
{
ORowSetValue aValue;
aValue.fill(x);
setDecimal(parameterIndex,aValue);
}
break;
case DataType::NUMERIC: case DataType::NUMERIC:
if(x.hasValue())
{ {
ORowSetValue aValue; ORowSetValue aValue;
aValue.fill(x); 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; break;
default: default:
::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale); ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
...@@ -513,9 +578,6 @@ void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, c ...@@ -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) 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); setNull(parameterIndex,sqlType);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -531,20 +593,21 @@ void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any ...@@ -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) 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) void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
{ {
setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x); setParameter(parameterIndex, DataType::BINARY, x);
boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException) 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); setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -557,6 +620,7 @@ void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, con ...@@ -557,6 +620,7 @@ void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, con
void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException) void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
{ {
::osl::MutexGuard aGuard( m_aMutex );
prepareStatement(); prepareStatement();
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS); SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
...@@ -566,6 +630,7 @@ void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, Runtim ...@@ -566,6 +630,7 @@ void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, Runtim
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException) void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
{ {
::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::clearBatch", *this );
// clearParameters( ); // clearParameters( );
// m_aBatchList.erase(); // m_aBatchList.erase();
} }
...@@ -573,11 +638,14 @@ void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeExce ...@@ -573,11 +638,14 @@ void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeExce
void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException) void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
{ {
::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::addBatch", *this );
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException) 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 > (); return Sequence< sal_Int32 > ();
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
...@@ -607,12 +675,6 @@ void OPreparedStatement::initBoundParam () throw(SQLException) ...@@ -607,12 +675,6 @@ void OPreparedStatement::initBoundParam () throw(SQLException)
boundParams = new OBoundParam[numParams]; 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) ...@@ -623,14 +685,13 @@ void OPreparedStatement::initBoundParam () throw(SQLException)
// parameter. // 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 // Sanity check the parameter number
if ((index >= 1) && if ((index >= 1) && (index <= numParams))
(index <= numParams) && bufLen > 0 )
{ {
b = boundParams[index - 1].allocBindDataBuffer(bufLen); b = boundParams[index - 1].allocBindDataBuffer(bufLen);
} }
...@@ -644,9 +705,9 @@ sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen) ...@@ -644,9 +705,9 @@ sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
// Gets the length buffer for the given parameter index // 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 // Sanity check the parameter number
...@@ -737,7 +798,7 @@ void OPreparedStatement::setStream( ...@@ -737,7 +798,7 @@ void OPreparedStatement::setStream(
sal_Int32 ParameterIndex, sal_Int32 ParameterIndex,
const Reference< XInputStream>& x, const Reference< XInputStream>& x,
SQLLEN length, SQLLEN length,
sal_Int32 SQLtype) sal_Int32 _nType)
throw(SQLException) throw(SQLException)
{ {
::osl::MutexGuard aGuard( m_aMutex ); ::osl::MutexGuard aGuard( m_aMutex );
...@@ -749,35 +810,33 @@ void OPreparedStatement::setStream( ...@@ -749,35 +810,33 @@ void OPreparedStatement::setStream(
checkParameterIndex(ParameterIndex); checkParameterIndex(ParameterIndex);
// Get the buffer needed for the length // 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 // Allocate a new buffer for the parameter data. This buffer
// will be returned by SQLParamData (it is set to the parameter // 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 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
SQLSMALLINT Ctype = SQL_C_CHAR; *lenBuf = SQL_LEN_DATA_AT_EXEC (length);
SQLLEN atExec = SQL_LEN_DATA_AT_EXEC (length);
memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex));
memcpy (lenBuf, &atExec, sizeof (atExec));
if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY)) SQLSMALLINT fCType, fSqlType;
Ctype = SQL_C_BINARY; OTools::getBindTypes(useWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!"); OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
N3SQLBindParameter(m_aStatementHandle, N3SQLBindParameter(m_aStatementHandle,
(SQLUSMALLINT)ParameterIndex, static_cast<SQLUSMALLINT>(ParameterIndex),
(SQLUSMALLINT)SQL_PARAM_INPUT, SQL_PARAM_INPUT,
Ctype, fCType,
(SQLSMALLINT)SQLtype, fSqlType,
(SQLULEN)length, length,
0, invalid_scale,
dataBuf, dataBuf,
sizeof(ParameterIndex), sizeof(ParameterIndex),
(SQLLEN*)lenBuf); lenBuf);
// Save the input stream // Save the input stream
boundParams[ParameterIndex - 1].setInputStream (x, length); boundParams[ParameterIndex - 1].setInputStream (x, length);
...@@ -840,7 +899,9 @@ void OPreparedStatement::prepareStatement() ...@@ -840,7 +899,9 @@ void OPreparedStatement::prepareStatement()
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex) void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
{ {
if( !_parameterIndex || _parameterIndex > numParams) if( _parameterIndex > numParams ||
_parameterIndex < 1 ||
_parameterIndex > std::numeric_limits<SQLUSMALLINT>::max() )
{ {
::connectivity::SharedResources aResources; ::connectivity::SharedResources aResources;
const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX, const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
......
...@@ -1058,7 +1058,7 @@ void SAL_CALL OResultSet::updateDouble( sal_Int32 columnIndex, double x ) throw( ...@@ -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) void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
{ {
sal_Int32 nType = m_aRow[columnIndex].getTypeKind(); 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] = x;
m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarchar will be recognized by fillNeededData m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarchar will be recognized by fillNeededData
updateValue(columnIndex,nOdbcType,(void*)&x); updateValue(columnIndex,nOdbcType,(void*)&x);
...@@ -1067,7 +1067,7 @@ void SAL_CALL OResultSet::updateString( sal_Int32 columnIndex, const ::rtl::OUSt ...@@ -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) void SAL_CALL OResultSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
{ {
sal_Int32 nType = m_aRow[columnIndex].getTypeKind(); 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] = x;
m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarbinary will be recognized by fillNeededData m_aRow[columnIndex].setTypeKind(nType); // OJ: otherwise longvarbinary will be recognized by fillNeededData
updateValue(columnIndex,nOdbcType,(void*)&x); updateValue(columnIndex,nOdbcType,(void*)&x);
......
...@@ -150,190 +150,6 @@ void OTools::getValue( OConnection* _pConnection, ...@@ -150,190 +150,6 @@ void OTools::getValue( OConnection* _pConnection,
_aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False); _aStatementHandle,SQL_HANDLE_STMT,_xInterface,sal_False);
_bWasNull = pcbValue == SQL_NULL_DATA; _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, void OTools::bindValue( OConnection* _pConnection,
SQLHANDLE _aStatementHandle, SQLHANDLE _aStatementHandle,
...@@ -342,7 +158,7 @@ void OTools::bindValue( OConnection* _pConnection, ...@@ -342,7 +158,7 @@ void OTools::bindValue( OConnection* _pConnection,
SQLSMALLINT _nMaxLen, SQLSMALLINT _nMaxLen,
const void* _pValue, const void* _pValue,
void* _pData, void* _pData,
SQLLEN *pLen, SQLLEN * const pLen,
const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface, const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xInterface,
rtl_TextEncoding _nTextEncoding, rtl_TextEncoding _nTextEncoding,
sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException) sal_Bool _bUseOldTimeDate) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
...@@ -779,7 +595,7 @@ void OTools::GetInfo(OConnection* _pConnection, ...@@ -779,7 +595,7 @@ void OTools::GetInfo(OConnection* _pConnection,
_aConnectionHandle,SQL_HANDLE_DBC,_xInterface); _aConnectionHandle,SQL_HANDLE_DBC,_xInterface);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) sal_Int32 OTools::MapOdbcType2Jdbc(SQLSMALLINT _nType)
{ {
sal_Int32 nValue = DataType::VARCHAR; sal_Int32 nValue = DataType::VARCHAR;
switch(_nType) switch(_nType)
...@@ -857,7 +673,7 @@ sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType) ...@@ -857,7 +673,7 @@ sal_Int32 OTools::MapOdbcType2Jdbc(sal_Int32 _nType)
// jdbcTypeToOdbc // jdbcTypeToOdbc
// Convert the JDBC SQL type to the correct ODBC type // 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" ); RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "odbc", "Ocke.Janssen@sun.com", "OTools::jdbcTypeToOdbc" );
// For the most part, JDBC types match ODBC types. We'll // For the most part, JDBC types match ODBC types. We'll
...@@ -876,6 +692,11 @@ sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType) ...@@ -876,6 +692,11 @@ sal_Int32 OTools::jdbcTypeToOdbc(sal_Int32 jdbcType)
case DataType::TIMESTAMP: case DataType::TIMESTAMP:
odbcType = SQL_TIMESTAMP; odbcType = SQL_TIMESTAMP;
break; 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; return odbcType;
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define _CONNECTIVITY_OBOUNPARAM_HXX_ #define _CONNECTIVITY_OBOUNPARAM_HXX_
#include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/sdbc/DataType.hpp>
#include "odbc/odbcbasedllapi.hxx" #include "odbc/odbcbasedllapi.hxx"
namespace connectivity namespace connectivity
...@@ -31,50 +32,29 @@ namespace connectivity ...@@ -31,50 +32,29 @@ namespace connectivity
public: public:
OBoundParam() 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() ~OBoundParam()
{ {
delete [] binaryData; free(binaryData);
delete [] paramLength;
} }
//--------------------------------------------------------------------
// 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 // allocBindDataBuffer
// Allocates and returns a new bind data buffer of the specified // Allocates and returns a new bind data buffer of the specified
// length // length
//-------------------------------------------------------------------- //--------------------------------------------------------------------
sal_Int8* allocBindDataBuffer (sal_Int32 bufLen) void* allocBindDataBuffer (sal_Int32 bufLen)
{ {
if ( binaryData ) // Reset the input stream and sequence, we are doing a new bind
delete [] binaryData;
binaryData = new sal_Int8[bufLen];
// Reset the input stream, we are doing a new bind
setInputStream (NULL, 0); setInputStream (NULL, 0);
aSequence.realloc(0);
free(binaryData);
binaryData = (bufLen > 0) ? malloc(bufLen) : NULL;
return binaryData; return binaryData;
} }
...@@ -83,7 +63,7 @@ namespace connectivity ...@@ -83,7 +63,7 @@ namespace connectivity
// getBindDataBuffer // getBindDataBuffer
// Returns the data buffer to be used when binding to a parameter // Returns the data buffer to be used when binding to a parameter
//-------------------------------------------------------------------- //--------------------------------------------------------------------
sal_Int8* getBindDataBuffer () void* getBindDataBuffer ()
{ {
return binaryData; return binaryData;
} }
...@@ -92,9 +72,9 @@ namespace connectivity ...@@ -92,9 +72,9 @@ namespace connectivity
// getBindLengthBuffer // getBindLengthBuffer
// Returns the length buffer to be used when binding to a parameter // Returns the length buffer to be used when binding to a parameter
//-------------------------------------------------------------------- //--------------------------------------------------------------------
sal_Int8* getBindLengthBuffer () SQLLEN* getBindLengthBuffer ()
{ {
return paramLength; return &paramLength;
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------
...@@ -176,10 +156,10 @@ namespace connectivity ...@@ -176,10 +156,10 @@ namespace connectivity
// Data attributes // Data attributes
//==================================================================== //====================================================================
sal_Int8* binaryData; // Storage area to be used void *binaryData; // Storage area to be used
// when binding the parameter // when binding the parameter
sal_Int8* paramLength; // Storage area to be used SQLLEN paramLength; // Storage area to be used
// for the bound length of the // for the bound length of the
// parameter. Note that this // parameter. Note that this
// data is in native format. // data is in native format.
...@@ -187,9 +167,9 @@ namespace connectivity ...@@ -187,9 +167,9 @@ namespace connectivity
::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream> paramInputStream; ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream> paramInputStream;
::com::sun::star::uno::Sequence< sal_Int8 > aSequence; ::com::sun::star::uno::Sequence< sal_Int8 > aSequence;
// When an input stream is // When an input stream is
// bound to a parameter, the // bound to a parameter, a
// input stream is saved // reference to the input stream is saved
// until needed. // until not needed anymore.
sal_Int32 paramInputStreamLen; // Length of input stream sal_Int32 paramInputStreamLen; // Length of input stream
...@@ -197,16 +177,6 @@ namespace connectivity ...@@ -197,16 +177,6 @@ namespace connectivity
// register an OUT parameter // register an OUT parameter
sal_Bool outputParameter; // true for OUTPUT parameters 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)
}; };
} }
} }
......
...@@ -46,6 +46,7 @@ namespace connectivity ...@@ -46,6 +46,7 @@ namespace connectivity
public OPreparedStatement_BASE public OPreparedStatement_BASE
{ {
protected: protected:
static const short invalid_scale = -1;
struct Parameter struct Parameter
{ {
::com::sun::star::uno::Any aValue; ::com::sun::star::uno::Any aValue;
...@@ -74,15 +75,20 @@ namespace connectivity ...@@ -74,15 +75,20 @@ namespace connectivity
void putParamData (sal_Int32 index) throw(::com::sun::star::sdbc::SQLException); 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, 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); SQLLEN length,sal_Int32 SQLtype) throw(::com::sun::star::sdbc::SQLException);
sal_Int8* getLengthBuf (sal_Int32 index); SQLLEN* getLengthBuf (sal_Int32 index);
sal_Int8* allocBindBuf ( sal_Int32 index, sal_Int32 bufLen); void* allocBindBuf ( sal_Int32 index, sal_Int32 bufLen);
void initBoundParam () throw(::com::sun::star::sdbc::SQLException); 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;} sal_Bool isPrepared() const { return m_bPrepared;}
void prepareStatement(); void prepareStatement();
void checkParameterIndex(sal_Int32 _parameterIndex); void checkParameterIndex(sal_Int32 _parameterIndex);
void setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x );
/** /**
creates the driver specific resultset (factory) creates the driver specific resultset (factory)
......
...@@ -138,8 +138,8 @@ namespace connectivity ...@@ -138,8 +138,8 @@ namespace connectivity
sal_Bool &_rValue, 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); 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 MapOdbcType2Jdbc(SQLSMALLINT _nType);
static sal_Int32 jdbcTypeToOdbc(sal_Int32 jdbcType); static SQLSMALLINT jdbcTypeToOdbc(sal_Int32 jdbcType);
static DATE_STRUCT DateToOdbcDate(const ::com::sun::star::util::Date& x) static DATE_STRUCT DateToOdbcDate(const ::com::sun::star::util::Date& x)
{ {
...@@ -206,40 +206,6 @@ namespace connectivity ...@@ -206,40 +206,6 @@ namespace connectivity
void* _pValue, void* _pValue,
SQLLEN _nSize) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException); 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, static void bindValue( OConnection* _pConnection,
SQLHANDLE _aStatementHandle, SQLHANDLE _aStatementHandle,
sal_Int32 columnIndex, sal_Int32 columnIndex,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment