Files
libreoffice/connectivity/source/drivers/odbc/OPreparedStatement.cxx

1023 lines
36 KiB
C++
Raw Normal View History

2000-09-18 15:18:56 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 15:18:56 +00:00
*
* Copyright 2008 by Sun Microsystems, Inc.
2000-09-18 15:18:56 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 15:18:56 +00:00
*
* $RCSfile: OPreparedStatement.cxx,v $
2008-10-01 12:28:29 +00:00
* $Revision: 1.49.56.2 $
2000-09-18 15:18:56 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 15:18:56 +00:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2000-09-18 15:18:56 +00:00
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2000-09-18 15:18:56 +00:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2000-09-18 15:18:56 +00:00
*
************************************************************************/
2000-11-29 11:39:57 +00:00
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_connectivity.hxx"
2000-11-29 11:39:57 +00:00
#include <stdio.h>
#include <string.h>
2000-09-18 15:18:56 +00:00
#include <osl/diagnose.h>
#include "odbc/OPreparedStatement.hxx"
#include "odbc/OBoundParam.hxx"
#include <com/sun/star/sdbc/DataType.hpp>
#include "odbc/OTools.hxx"
#include "odbc/ODriver.hxx"
#include "odbc/OResultSet.hxx"
2000-09-18 15:18:56 +00:00
#include "odbc/OResultSetMetaData.hxx"
#include <cppuhelper/typeprovider.hxx>
2000-10-11 09:48:50 +00:00
#include <comphelper/sequence.hxx>
2000-09-18 15:18:56 +00:00
#include <com/sun/star/lang/DisposedException.hpp>
2001-06-22 09:58:46 +00:00
#include "connectivity/dbtools.hxx"
2001-05-18 07:33:49 +00:00
#include <comphelper/types.hxx>
2001-09-20 11:51:56 +00:00
#include "connectivity/FValue.hxx"
2008-10-01 12:28:29 +00:00
#include "resource/common_res.hrc"
#include "connectivity/sqlparse.hxx"
2000-09-18 15:18:56 +00:00
2001-05-18 07:33:49 +00:00
using namespace ::comphelper;
2000-09-18 15:18:56 +00:00
using namespace connectivity;
using namespace connectivity::odbc;
using namespace com::sun::star::uno;
using namespace com::sun::star::lang;
using namespace com::sun::star::beans;
using namespace com::sun::star::sdbc;
using namespace com::sun::star::sdbcx;
using namespace com::sun::star::container;
using namespace com::sun::star::io;
using namespace com::sun::star::util;
int OBoundParam::ASCII = 1;
int OBoundParam::UNICODE = 2;
int OBoundParam::BINARY = 3;
IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const TTypeInfoVector& _TypeInfo,const ::rtl::OUString& sql)
:OStatement_BASE2(_pConnection)
,m_aTypeInfo(_TypeInfo)
,numParams(0)
,boundParams(NULL)
2000-11-15 15:02:53 +00:00
,m_bPrepared(sal_False)
2000-09-18 15:18:56 +00:00
{
m_sSqlStatement = sql;
try
{
if(_pConnection->isParameterSubstitutionEnabled())
{
OSQLParser aParser(_pConnection->getDriver()->getORB());
::rtl::OUString sErrorMessage;
::rtl::OUString sNewSql;
OSQLParseNode* pNode = aParser.parseTree(sErrorMessage,sql);
if(pNode)
{ // special handling for parameters
OSQLParseNode::substituteParameterNames(pNode);
pNode->parseNodeToStr( sNewSql, _pConnection );
delete pNode;
m_sSqlStatement = sNewSql;
}
}
}
catch(Exception&)
{
}
2000-09-18 15:18:56 +00:00
}
2001-04-30 09:16:19 +00:00
// -----------------------------------------------------------------------------
2001-10-17 13:55:07 +00:00
void SAL_CALL OPreparedStatement::acquire() throw()
2001-04-30 09:16:19 +00:00
{
OStatement_BASE2::acquire();
}
// -----------------------------------------------------------------------------
2001-10-17 13:55:07 +00:00
void SAL_CALL OPreparedStatement::release() throw()
2001-04-30 09:16:19 +00:00
{
OStatement_BASE2::release();
}
// -----------------------------------------------------------------------------
2000-09-18 15:18:56 +00:00
Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
{
Any aRet = OStatement_BASE2::queryInterface(rType);
return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
{
2000-11-15 15:02:53 +00:00
return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
2001-06-26 10:31:18 +00:00
prepareStatement();
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
2001-01-09 11:35:05 +00:00
if(!m_xMetaData.is())
m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
2000-09-18 15:18:56 +00:00
return m_xMetaData;
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
2000-09-18 15:18:56 +00:00
// Close/clear our result set
clearMyResultSet ();
// Reset last warning message
try {
clearWarnings ();
2000-11-08 14:08:24 +00:00
OStatement_BASE2::close();
FreeParams();
2000-09-18 15:18:56 +00:00
}
2000-11-15 15:02:53 +00:00
catch (SQLException &) {
2000-09-18 15:18:56 +00:00
// If we get an error, ignore
}
// Remove this Statement object from the Connection object's
// list
}
// -------------------------------------------------------------------------
sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
2000-09-18 15:18:56 +00:00
sal_Bool needData = sal_False;
// Reset warnings
clearWarnings ();
// Reset the statement handle, warning and saved Resultset
reset();
// Call SQLExecute
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-09-18 15:18:56 +00:00
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
2000-09-18 15:18:56 +00:00
try
{
SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
2000-09-18 15:18:56 +00:00
needData = nReturn == SQL_NEED_DATA;
// Now loop while more data is needed (i.e. a data-at-
// execution parameter was given). For each parameter
// that needs data, put the data from the input stream.
while (needData) {
// Get the parameter number that requires data
sal_Int32* paramIndex = 0;
nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
// If the parameter index is -1, there is no
// more data required
if (*paramIndex == -1)
needData = sal_False;
else
{
// Now we have the proper parameter
// index, get the data from the input
// stream and do a SQLPutData
putParamData (*paramIndex);
}
}
}
catch (const SQLWarning&)
2000-09-18 15:18:56 +00:00
{
}
// Now loop while more data is needed (i.e. a data-at-
// execution parameter was given). For each parameter
// that needs data, put the data from the input stream.
while (needData) {
// Get the parameter number that requires data
sal_Int32* paramIndex = 0;
N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)&paramIndex);
// If the parameter index is -1, there is no more
// data required
if (*paramIndex == -1) {
needData = sal_False;
}
else {
// Now we have the proper parameter index,
// get the data from the input stream
// and do a SQLPutData
putParamData(*paramIndex);
}
}
// Now determine if there is a result set associated with
// the SQL statement that was executed. Get the column
// count, and if it is not zero, there is a result set.
2001-05-14 10:42:44 +00:00
return getColumnCount() > 0;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-09-18 15:18:56 +00:00
sal_Int32 numRows = -1;
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-09-18 15:18:56 +00:00
// Execute the statement. If execute returns sal_False, a
// row count exists.
if (!execute())
numRows = getUpdateCount ();
2008-10-01 12:28:29 +00:00
else
{
2000-09-18 15:18:56 +00:00
// No update count was produced (a ResultSet was). Raise
// an exception
2008-10-01 12:28:29 +00:00
m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
2000-09-18 15:18:56 +00:00
}
return numRows;
}
// -------------------------------------------------------------------------
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);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-09-18 15:18:56 +00:00
return (Reference< XConnection >)m_pConnection;
}
// -------------------------------------------------------------------------
Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-09-18 15:18:56 +00:00
Reference< XResultSet > rs = NULL;
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-11-15 15:02:53 +00:00
2000-09-18 15:18:56 +00:00
if (execute())
rs = getResultSet(sal_False);
2008-10-01 12:28:29 +00:00
else
{
2000-09-18 15:18:56 +00:00
// No ResultSet was produced. Raise an exception
2008-10-01 12:28:29 +00:00
m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
2000-09-18 15:18:56 +00:00
}
return rs;
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
2000-09-18 15:18:56 +00:00
sal_Int32 value = 0;
// If the parameter is sal_True, set the value to 1
if (x) {
value = 1;
}
// Set the parameter as if it were an integer
setInt (parameterIndex, value);
}
// -------------------------------------------------------------------------
#define PREP_BIND_PARAM(_ty,_jt) \
OTools::bindParameter(m_pConnection, \
m_aStatementHandle, \
2000-09-18 15:18:56 +00:00
parameterIndex, \
bindBuf, \
getLengthBuf(parameterIndex), \
(SWORD)_jt, \
2001-08-06 06:41:49 +00:00
sal_False,m_pConnection->useOldDateFormat(),_pData,(Reference <XInterface>)*this,getOwnConnection()->getTextEncoding())
2000-09-18 15:18:56 +00:00
2001-08-06 06:41:49 +00:00
void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData)
2000-09-18 15:18:56 +00:00
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-09-18 15:18:56 +00:00
// 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.
2001-08-06 06:41:49 +00:00
2001-06-26 10:31:18 +00:00
checkParameterIndex(parameterIndex);
sal_Int32 nRealSize = _nSize;
SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType));
switch(fSqlType)
{
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_DECIMAL:
case SQL_NUMERIC:
++nRealSize;
break;
default:
break;
}
2000-09-18 15:18:56 +00:00
sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
2001-08-06 06:41:49 +00:00
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
2001-08-06 06:41:49 +00:00
OTools::bindParameter( m_pConnection,
m_aStatementHandle,
parameterIndex,
bindBuf,
getLengthBuf(parameterIndex),
fSqlType,
2001-08-06 06:41:49 +00:00
sal_False,
m_pConnection->useOldDateFormat(),
_pData,
(Reference <XInterface>)*this,
getOwnConnection()->getTextEncoding());
}
// -----------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
{
setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
{
DATE_STRUCT x = OTools::DateToOdbcDate(aData);
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
{
TIME_STRUCT x = OTools::TimeToOdbcTime(aVal);
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
{
TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal);
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
{
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
{
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
{
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
2001-09-20 11:51:56 +00:00
void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
2001-09-20 11:51:56 +00:00
try
{
setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x);
}
catch(SQLException&)
{
setString(parameterIndex,ORowSetValue(x));
}
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException)
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-09-18 15:18:56 +00:00
// Get the buffer needed for the length
2001-06-26 10:31:18 +00:00
checkParameterIndex(parameterIndex);
2000-09-18 15:18:56 +00:00
sal_Int8* lenBuf = getLengthBuf (parameterIndex);
2000-12-01 12:01:52 +00:00
*(SDWORD*)lenBuf = SQL_NULL_DATA;
SQLINTEGER prec = 0;
SQLUINTEGER nColumnSize = 0;
2000-12-01 12:01:52 +00:00
if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
{
2000-09-18 15:18:56 +00:00
prec = 1;
nColumnSize = 1;
}
2000-09-18 15:18:56 +00:00
2000-11-30 14:21:36 +00:00
SQLSMALLINT fCType = 0;
SQLSMALLINT fSqlType = 0;
2000-11-30 14:21:36 +00:00
SQLSMALLINT nDecimalDigits = 0;
2001-11-30 13:09:45 +00:00
OTools::getBindTypes( sal_False,
m_pConnection->useOldDateFormat(),
(SQLSMALLINT)sqlType,
2001-11-30 13:09:45 +00:00
fCType,
fSqlType);
2000-11-30 14:21:36 +00:00
SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
(SQLUSMALLINT)parameterIndex,
(SQLSMALLINT)SQL_PARAM_INPUT,
fCType,
fSqlType,
nColumnSize,
nDecimalDigits,
NULL,
prec,
(SDWORD*)lenBuf
);
OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
::dbtools::throwFunctionNotSupportedException( "XParameters::setClob", *this );
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
::dbtools::throwFunctionNotSupportedException( "XParameters::setBlob", *this );
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
{
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-06-26 10:31:18 +00:00
prepareStatement();
2000-09-18 15:18:56 +00:00
// For each known SQL Type, call the appropriate
// set routine
switch (sqlType)
{
case DataType::VARCHAR:
case DataType::LONGVARCHAR:
2001-06-22 09:58:46 +00:00
if(x.hasValue())
2001-08-06 06:41:49 +00:00
{
::rtl::OUString sStr;
x >>= sStr;
::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
2001-08-06 06:41:49 +00:00
}
2001-06-22 09:58:46 +00:00
else
setNull(parameterIndex,sqlType);
2000-09-18 15:18:56 +00:00
break;
case DataType::DECIMAL:
case DataType::NUMERIC:
{
ORowSetValue aValue;
aValue.fill(x);
setString(parameterIndex,aValue);
}
break;
2000-09-18 15:18:56 +00:00
default:
2001-06-22 09:58:46 +00:00
::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
2000-09-18 15:18:56 +00:00
}
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
2000-09-18 15:18:56 +00:00
{
2000-11-15 15:02:53 +00:00
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-09-18 15:18:56 +00:00
setNull(parameterIndex,sqlType);
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
{
2001-06-26 10:31:18 +00:00
if (!::dbtools::implSetObject(this, parameterIndex, x))
{ // there is no other setXXX call which can handle the value in x
throw SQLException();
}
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
{
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
{
2001-08-06 06:41:49 +00:00
setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
{
setStream (parameterIndex, x, length, DataType::LONGVARCHAR,OBoundParam::ASCII);
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
{
setStream (parameterIndex, x, length, DataType::LONGVARBINARY,OBoundParam::BINARY);
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
{
2001-06-26 10:31:18 +00:00
prepareStatement();
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
{
// clearParameters( );
// m_aBatchList.erase();
}
// -------------------------------------------------------------------------
void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
{
}
// -------------------------------------------------------------------------
Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException)
{
return Sequence< sal_Int32 > ();
}
// -------------------------------------------------------------------------
//====================================================================
// methods
//====================================================================
//--------------------------------------------------------------------
// initBoundParam
// Initialize the bound parameter objects
//--------------------------------------------------------------------
void OPreparedStatement::initBoundParam () throw(SQLException)
{
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
2000-09-18 15:18:56 +00:00
// Get the number of parameters
numParams = 0;
N3SQLNumParams (m_aStatementHandle,&numParams);
2000-09-18 15:18:56 +00:00
// There are parameter markers, allocate the bound
// parameter objects
if (numParams > 0)
{
// Allocate an array of bound parameter objects
boundParams = new OBoundParam[numParams];
// Allocate and initialize each bound parameter
for (sal_Int32 i = 0; i < numParams; i++)
{
boundParams[i] = OBoundParam();
boundParams[i].initialize ();
}
}
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// allocBindBuf
// Allocate storage for the permanent data buffer for the bound
// parameter.
//--------------------------------------------------------------------
sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
{
sal_Int8* b = NULL;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams) && bufLen > 0 )
2000-09-18 15:18:56 +00:00
{
b = boundParams[index - 1].allocBindDataBuffer(bufLen);
}
return b;
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// getDataBuf
// Gets the data buffer for the given parameter index
//--------------------------------------------------------------------
sal_Int8* OPreparedStatement::getDataBuf (sal_Int32 index)
{
sal_Int8* b = NULL;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams))
{
b = boundParams[index - 1].getBindDataBuffer ();
}
return b;
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// getLengthBuf
// Gets the length buffer for the given parameter index
//--------------------------------------------------------------------
sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
{
sal_Int8* b = NULL;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams))
{
b = boundParams[index - 1].getBindLengthBuffer ();
}
return b;
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// getParamLength
// Returns the length of the given parameter number. When each
// parameter was bound, a 4-sal_Int8 buffer was given to hold the
// length (stored in native format). Get the buffer, convert the
// buffer from native format, and return it. If the length is -1,
// the column is considered to be NULL.
//--------------------------------------------------------------------
sal_Int32 OPreparedStatement::getParamLength ( sal_Int32 index)
{
sal_Int32 paramLen = SQL_NULL_DATA;
// Sanity check the parameter number
if ((index >= 1) &&
(index <= numParams)) {
// Now get the length of the parameter from the
// bound param array. -1 is returned if it is NULL.
long n = 0;
memcpy (&n, boundParams[index -1].getBindLengthBuffer (), sizeof (n));
paramLen = n;
}
return paramLen;
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// putParamData
// Puts parameter data from a previously bound input stream. The
// input stream was bound using SQL_LEN_DATA_AT_EXEC.
//--------------------------------------------------------------------
void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException)
{
2001-05-14 10:42:44 +00:00
// Sanity check the parameter index
if ((index < 1) ||
(index > numParams))
{
return;
}
2000-09-18 15:18:56 +00:00
// We'll transfer up to maxLen at a time
sal_Int32 maxLen = MAX_PUT_DATA_LENGTH;
sal_Int32 bufLen;
sal_Int32 realLen;
// sal_Int8* buf = new sal_Int8[maxLen];
Sequence< sal_Int8 > buf(maxLen);
sal_Bool endOfStream = sal_False;
// Get the information about the input stream
Reference< XInputStream> inputStream = boundParams[index - 1].getInputStream ();
if ( !inputStream.is() )
{
2008-10-01 12:28:29 +00:00
::connectivity::SharedResources aResources;
const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
throw SQLException (sError, *this,::rtl::OUString(),0,Any());
}
2000-09-18 15:18:56 +00:00
sal_Int32 inputStreamLen = boundParams[index - 1].getInputStreamLen ();
sal_Int32 inputStreamType = boundParams[index - 1].getStreamType ();
// Loop while more data from the input stream
2001-05-14 10:42:44 +00:00
try
2000-09-18 15:18:56 +00:00
{
2001-05-14 10:42:44 +00:00
while (!endOfStream)
{
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// Read some data from the input stream
2000-09-18 15:18:56 +00:00
bufLen = inputStream->readBytes(buf,maxLen);
2001-05-14 10:42:44 +00:00
// -1 as the number of bytes read indicates that
// there is no more data in the input stream
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
if (bufLen == -1)
{
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// Sanity check to ensure that all the data we said we
// had was read. If not, raise an exception
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
if (inputStreamLen != 0)
{
2008-10-01 12:28:29 +00:00
::connectivity::SharedResources aResources;
const ::rtl::OUString sError( aResources.getResourceString(STR_INPUTSTREAM_WRONG_LEN));
throw SQLException (sError, *this,::rtl::OUString(),0,Any());
2001-05-14 10:42:44 +00:00
}
endOfStream = sal_True;
break;
}
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// If we got more bytes than necessary, truncate
// the buffer by re-setting the buffer length. Also,
// indicate that we don't need to read any more.
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
if (bufLen > inputStreamLen)
{
bufLen = inputStreamLen;
endOfStream = sal_True;
2000-09-18 15:18:56 +00:00
}
2001-05-14 10:42:44 +00:00
realLen = bufLen;
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// For UNICODE streams, strip off the high sal_Int8 and set the
// number of actual bytes present. It is assumed that
// there are 2 bytes present for every UNICODE character - if
// not, then that's not our problem
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
if (inputStreamType == OBoundParam::UNICODE)
{
realLen = bufLen / 2;
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
for (sal_Int32 ii = 0; ii < realLen; ii++)
buf[ii] = buf[(ii * 2) + 1];
}
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// Put the data
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
N3SQLPutData (m_aStatementHandle, buf.getArray(), realLen);
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// Decrement the number of bytes still needed
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
inputStreamLen -= bufLen;
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// If there is no more data to be read, exit loop
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
if (inputStreamLen == 0)
endOfStream = sal_True;
}
}
catch (const IOException& ex)
{
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
// If an I/O exception was generated, turn
// it into a SQLException
2000-09-18 15:18:56 +00:00
2001-05-14 10:42:44 +00:00
throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any());
2000-09-18 15:18:56 +00:00
}
}
// -------------------------------------------------------------------------
//--------------------------------------------------------------------
// getPrecision
// Given a SQL type, return the maximum precision for the column.
// Returns -1 if not known
//--------------------------------------------------------------------
sal_Int32 OPreparedStatement::getPrecision ( sal_Int32 sqlType)
{
::osl::MutexGuard aGuard( m_aMutex );
2001-05-14 10:42:44 +00:00
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
2000-09-18 15:18:56 +00:00
sal_Int32 prec = -1;
if (m_aTypeInfo.size())
{
2001-05-14 10:42:44 +00:00
OTypeInfo aInfo;
aInfo.nType = (sal_Int16)sqlType;
TTypeInfoVector::const_iterator aIter = ::std::find(m_aTypeInfo.begin(),m_aTypeInfo.end(),aInfo);
2000-09-18 15:18:56 +00:00
if(aIter != m_aTypeInfo.end())
prec = (*aIter).nPrecision;
}
return prec;
}
//--------------------------------------------------------------------
// setStream
// Sets an input stream as a parameter, using the given SQL type
//--------------------------------------------------------------------
void OPreparedStatement::setStream (
sal_Int32 ParameterIndex,
const Reference< XInputStream>& x,
sal_Int32 length,
sal_Int32 SQLtype,
sal_Int32 streamType)
throw(SQLException)
2000-09-18 15:18:56 +00:00
{
2001-08-06 06:41:49 +00:00
::osl::MutexGuard aGuard( m_aMutex );
checkDisposed(OStatement_BASE::rBHelper.bDisposed);
prepareStatement();
2001-06-26 10:31:18 +00:00
checkParameterIndex(ParameterIndex);
2000-09-18 15:18:56 +00:00
// Get the buffer needed for the length
sal_Int8* 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)
sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4);
// Bind the parameter with SQL_LEN_DATA_AT_EXEC
SQLSMALLINT Ctype = SQL_C_CHAR;
2000-09-18 15:18:56 +00:00
SDWORD 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))
Ctype = SQL_C_BINARY;
2001-03-20 15:54:34 +00:00
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
N3SQLBindParameter(m_aStatementHandle,
(SQLUSMALLINT)ParameterIndex,
(SQLSMALLINT)SQL_PARAM_INPUT,
Ctype,
(SQLSMALLINT)SQLtype,
(SQLUINTEGER)length,
0,
dataBuf,
sizeof(ParameterIndex),
(SDWORD*)lenBuf);
2000-09-18 15:18:56 +00:00
// Save the input stream
boundParams[ParameterIndex - 1].setInputStream (x, length);
// Set the stream type
boundParams[ParameterIndex - 1].setStreamType (streamType);
}
// -------------------------------------------------------------------------
// -------------------------------------------------------------------------
void OPreparedStatement::FreeParams()
{
numParams = 0;
2001-01-09 11:35:05 +00:00
delete [] boundParams;
2000-11-15 15:02:53 +00:00
boundParams = NULL;
2000-09-18 15:18:56 +00:00
}
// -------------------------------------------------------------------------
2000-11-15 15:02:53 +00:00
void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
{
2001-09-18 10:22:34 +00:00
try
2000-11-15 15:02:53 +00:00
{
2001-09-18 10:22:34 +00:00
switch(nHandle)
{
case PROPERTY_ID_RESULTSETCONCURRENCY:
if(!isPrepared())
setResultSetConcurrency(comphelper::getINT32(rValue));
break;
case PROPERTY_ID_RESULTSETTYPE:
if(!isPrepared())
setResultSetType(comphelper::getINT32(rValue));
break;
case PROPERTY_ID_FETCHDIRECTION:
if(!isPrepared())
setFetchDirection(comphelper::getINT32(rValue));
break;
case PROPERTY_ID_USEBOOKMARKS:
if(!isPrepared())
setUsingBookmarks(comphelper::getBOOL(rValue));
break;
default:
OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
}
}
catch(const SQLException&)
2001-09-18 10:22:34 +00:00
{
// throw Exception(e.Message,*this);
2000-11-15 15:02:53 +00:00
}
}
// -----------------------------------------------------------------------------
void OPreparedStatement::prepareStatement()
{
2001-06-26 10:31:18 +00:00
if(!isPrepared())
{
OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength());
OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
m_bPrepared = sal_True;
2001-06-26 10:31:18 +00:00
initBoundParam();
}
}
// -----------------------------------------------------------------------------
void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
{
if( !_parameterIndex || _parameterIndex > numParams)
{
2008-10-01 12:28:29 +00:00
::connectivity::SharedResources aResources;
const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
"$pos$", ::rtl::OUString::valueOf(_parameterIndex),
"$count$", ::rtl::OUString::valueOf((sal_Int32)numParams)
));
SQLException aNext(sError,*this, ::rtl::OUString(),0,Any());
::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
}
2000-11-15 15:02:53 +00:00
}
// -----------------------------------------------------------------------------
OResultSet* OPreparedStatement::createResulSet()
{
OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
pReturn->setMetaData(getMetaData());
return pReturn;
}
// -----------------------------------------------------------------------------