LCOV - code coverage report
Current view: top level - connectivity/source/drivers/odbc - OPreparedStatement.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 0 372 0.0 %
Date: 2015-06-13 12:38:46 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <string.h>
      22             : #include <osl/diagnose.h>
      23             : #include "diagnose_ex.h"
      24             : #include "odbc/OPreparedStatement.hxx"
      25             : #include "odbc/OBoundParam.hxx"
      26             : #include <com/sun/star/sdbc/DataType.hpp>
      27             : #include "odbc/OTools.hxx"
      28             : #include "odbc/ODriver.hxx"
      29             : #include "odbc/OResultSet.hxx"
      30             : #include "odbc/OResultSetMetaData.hxx"
      31             : #include <cppuhelper/typeprovider.hxx>
      32             : #include <comphelper/processfactory.hxx>
      33             : #include <comphelper/sequence.hxx>
      34             : #include <com/sun/star/lang/DisposedException.hpp>
      35             : #include <connectivity/dbtools.hxx>
      36             : #include <comphelper/types.hxx>
      37             : #include <connectivity/FValue.hxx>
      38             : #include "resource/common_res.hrc"
      39             : #include <connectivity/sqlparse.hxx>
      40             : #include <boost/scoped_ptr.hpp>
      41             : #include <boost/type_traits/remove_reference.hpp>
      42             : #include <boost/type_traits/is_same.hpp>
      43             : 
      44             : using namespace ::comphelper;
      45             : using namespace connectivity;
      46             : using namespace connectivity::odbc;
      47             : using namespace com::sun::star::uno;
      48             : using namespace com::sun::star::lang;
      49             : using namespace com::sun::star::beans;
      50             : using namespace com::sun::star::sdbc;
      51             : using namespace com::sun::star::sdbcx;
      52             : using namespace com::sun::star::container;
      53             : using namespace com::sun::star::io;
      54             : using namespace com::sun::star::util;
      55             : 
      56           0 : IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
      57             : 
      58             : namespace
      59             : {
      60             :     // for now, never use wchar,
      61             :     // but most of code is prepared to handle it
      62             :     // in case we make this configurable
      63             :     const bool useWChar = false;
      64             : }
      65             : 
      66           0 : OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const OUString& sql)
      67             :     :OStatement_BASE2(_pConnection)
      68             :     ,numParams(0)
      69             :     ,boundParams(NULL)
      70           0 :     ,m_bPrepared(false)
      71             : {
      72           0 :     m_sSqlStatement = sql;
      73             :     try
      74             :     {
      75           0 :         if(_pConnection->isParameterSubstitutionEnabled())
      76             :         {
      77           0 :             OSQLParser aParser( comphelper::getComponentContext(_pConnection->getDriver()->getORB()) );
      78           0 :             OUString sErrorMessage;
      79           0 :             OUString sNewSql;
      80           0 :             boost::scoped_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
      81           0 :             if ( pNode.get() )
      82             :             {   // special handling for parameters
      83           0 :                 OSQLParseNode::substituteParameterNames(pNode.get());
      84           0 :                 pNode->parseNodeToStr( sNewSql, _pConnection );
      85           0 :                 m_sSqlStatement = sNewSql;
      86           0 :             }
      87             :         }
      88             :     }
      89           0 :     catch(Exception&)
      90             :     {
      91             :     }
      92           0 : }
      93             : 
      94           0 : void SAL_CALL OPreparedStatement::acquire() throw()
      95             : {
      96           0 :     OStatement_BASE2::acquire();
      97           0 : }
      98             : 
      99           0 : void SAL_CALL OPreparedStatement::release() throw()
     100             : {
     101           0 :     OStatement_BASE2::release();
     102           0 : }
     103             : 
     104           0 : Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
     105             : {
     106           0 :     Any aRet = OStatement_BASE2::queryInterface(rType);
     107           0 :     return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
     108             : }
     109             : 
     110           0 : ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes(  ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     111             : {
     112           0 :     return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
     113             : }
     114             : 
     115             : 
     116           0 : Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData(  ) throw(SQLException, RuntimeException, std::exception)
     117             : {
     118           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     119           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     120             : 
     121             : 
     122           0 :     prepareStatement();
     123             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     124           0 :     if(!m_xMetaData.is())
     125           0 :         m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
     126           0 :     return m_xMetaData;
     127             : }
     128             : 
     129             : 
     130           0 : void SAL_CALL OPreparedStatement::close(  ) throw(SQLException, RuntimeException, std::exception)
     131             : {
     132           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     133           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     134             : 
     135             : 
     136             :     // Close/clear our result set
     137           0 :     clearMyResultSet ();
     138             : 
     139             :     // Reset last warning message
     140             : 
     141             :     try {
     142           0 :         clearWarnings ();
     143           0 :         OStatement_BASE2::close();
     144           0 :         FreeParams();
     145             :     }
     146           0 :     catch (SQLException &) {
     147             :         // If we get an error, ignore
     148           0 :     }
     149             : 
     150             :     // Remove this Statement object from the Connection object's
     151             :     // list
     152           0 : }
     153             : 
     154             : 
     155           0 : sal_Bool SAL_CALL OPreparedStatement::execute(  ) throw(SQLException, RuntimeException, std::exception)
     156             : {
     157           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     158           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     159             : 
     160             :     // Reset warnings
     161             : 
     162           0 :     clearWarnings ();
     163             : 
     164             :     // Reset the statement handle, warning and saved Resultset
     165             : 
     166           0 :     reset();
     167             : 
     168             :     // Call SQLExecute
     169           0 :     prepareStatement();
     170             : 
     171             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     172             :     try
     173             :     {
     174           0 :         SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
     175             : 
     176           0 :         OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
     177           0 :         bool needData = nReturn == SQL_NEED_DATA;
     178             : 
     179             :         // Now loop while more data is needed (i.e. a data-at-
     180             :         // execution parameter was given).  For each parameter
     181             :         // that needs data, put the data from the input stream.
     182             : 
     183           0 :         while (needData) {
     184             : 
     185             :             // Get the parameter number that requires data
     186             : 
     187           0 :             sal_Int32* paramIndex = 0;
     188           0 :             nReturn = N3SQLParamData(m_aStatementHandle, reinterpret_cast<SQLPOINTER*>(&paramIndex));
     189             : 
     190             :             // If the parameter index is -1, there is no
     191             :             // more data required
     192             : 
     193           0 :             if ( !paramIndex || ( *paramIndex == -1 ) )
     194           0 :                 needData = false;
     195             :             else
     196             :             {
     197             :                 // Now we have the proper parameter
     198             :                 // index, get the data from the input
     199             :                 // stream and do a SQLPutData
     200           0 :                 putParamData (*paramIndex);
     201             :             }
     202             :         }
     203             : 
     204             :     }
     205           0 :     catch (const SQLWarning&)
     206             :     {
     207             :     }
     208             : 
     209             :     // Now determine if there is a result set associated with
     210             :     // the SQL statement that was executed.  Get the column
     211             :     // count, and if it is not zero, there is a result set.
     212             : 
     213             : 
     214           0 :     return getColumnCount() > 0;
     215             : }
     216             : 
     217             : 
     218           0 : sal_Int32 SAL_CALL OPreparedStatement::executeUpdate(  ) throw(SQLException, RuntimeException, std::exception)
     219             : {
     220           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     221           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     222             : 
     223           0 :     sal_Int32 numRows = -1;
     224             : 
     225           0 :     prepareStatement();
     226             :     // Execute the statement.  If execute returns sal_False, a
     227             :     // row count exists.
     228             : 
     229           0 :     if (!execute())
     230           0 :         numRows = getUpdateCount ();
     231             :     else
     232             :     {
     233             :         // No update count was produced (a ResultSet was).  Raise
     234             :         // an exception
     235           0 :         m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
     236             :     }
     237           0 :     return numRows;
     238             : }
     239             : 
     240             : 
     241           0 : void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x ) throw(SQLException, RuntimeException, std::exception)
     242             : {
     243           0 :     setParameter(parameterIndex, DataType::CHAR, invalid_scale, x);
     244           0 : }
     245             : 
     246             : 
     247           0 : Reference< XConnection > SAL_CALL OPreparedStatement::getConnection(  ) throw(SQLException, RuntimeException, std::exception)
     248             : {
     249           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     250           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     251             : 
     252           0 :     return Reference< XConnection >(m_pConnection);
     253             : }
     254             : 
     255             : 
     256           0 : Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery(  ) throw(SQLException, RuntimeException, std::exception)
     257             : {
     258           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     259           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     260             : 
     261           0 :     Reference< XResultSet > rs = NULL;
     262             : 
     263           0 :     prepareStatement();
     264             : 
     265           0 :     if (execute())
     266           0 :         rs = getResultSet(false);
     267             :     else
     268             :     {
     269             :         // No ResultSet was produced.  Raise an exception
     270           0 :         m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
     271             :     }
     272           0 :     return rs;
     273             : }
     274             : 
     275             : 
     276           0 : void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException, std::exception)
     277             : {
     278             :     // Set the parameter as if it were an integer
     279           0 :     setInt (parameterIndex, x ? 1 : 0 );
     280           0 : }
     281             : 
     282             : // The MutexGuard must _already_ be taken!
     283           0 : void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex)
     284             : {
     285           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     286           0 :     prepareStatement();
     287           0 :     checkParameterIndex(parameterIndex);
     288             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     289           0 : }
     290             : 
     291             : 
     292           0 : template <typename T> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex, const sal_Int32 i_nType, const SQLULEN i_nColSize, const T i_Value)
     293             : {
     294           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     295           0 :     setParameterPre(parameterIndex);
     296             : 
     297             :     typedef typename boost::remove_reference< T >::type TnoRef;
     298             : 
     299           0 :     TnoRef *bindBuf = static_cast< TnoRef* >( allocBindBuf(parameterIndex, sizeof(i_Value)) );
     300           0 :     *bindBuf = i_Value;
     301             : 
     302           0 :     setParameter(parameterIndex, i_nType, i_nColSize, invalid_scale, bindBuf, sizeof(i_Value), sizeof(i_Value));
     303           0 : }
     304             : 
     305             : 
     306           0 : void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const sal_Int16 _nScale, const OUString &_sData)
     307             : {
     308           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     309           0 :     setParameterPre(parameterIndex);
     310             : 
     311             :     assert (_nType == DataType::VARCHAR || _nType == DataType::CHAR || _nType == DataType::DECIMAL || _nType == DataType::NUMERIC);
     312             : 
     313             :     sal_Int32 nCharLen;
     314             :     sal_Int32 nByteLen;
     315             :     void *pData;
     316             :     if (useWChar)
     317             :     {
     318             :         /*
     319             :          * On Windows, wchar is 16 bits (UTF-16 encoding), the ODBC "W" variants functions take UTF-16 encoded strings
     320             :          * and character lengths are number of UTF-16 codepoints.
     321             :          * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms716246%28v=vs.85%29.aspx
     322             :          * ODBC Programmer's reference > Developing Applications > Programming Considerations > Unicode >  Unicode Function Arguments
     323             :          *            http://support.microsoft.com/kb/294169
     324             :          *
     325             :          * UnixODBC can be configured at compile-time so that the "W" variants expect
     326             :          * UTF-16 or UTF-32 encoded strings, and character lengths are number of codepoints.
     327             :          * However, UTF-16 is the default, what all/most distributions do
     328             :          * and the established API that most drivers implement.
     329             :          * As wchar is often 32 bits, this differs from C-style strings of wchar!
     330             :          *
     331             :          * On MacOS X, the "W" variants use wchar_t, which is UCS4
     332             :          *
     333             :          * Our internal OUString storage is always UTF-16, so no conversion to do here.
     334             :          */
     335             :         static_assert(sizeof (SQLWCHAR) == 2 || sizeof (SQLWCHAR) == 4, "must be 2 or 4");
     336             :         if (sizeof (SQLWCHAR) == 2)
     337             :         {
     338             :             nCharLen = _sData.getLength();
     339             :             nByteLen = 2 * nCharLen;
     340             :             pData = allocBindBuf(parameterIndex, nByteLen);
     341             :             memcpy(pData, _sData.getStr(), nByteLen);
     342             :         }
     343             :         else
     344             :         {
     345             :             pData = allocBindBuf(parameterIndex, _sData.getLength() * 4);
     346             :             sal_uInt32* pCursor = static_cast<sal_uInt32*>(pData);
     347             :             nCharLen = 0;
     348             :             for (sal_Int32 i = 0; i != _sData.getLength();)
     349             :             {
     350             :                 *pCursor++ = _sData.iterateCodePoints(&i);
     351             :                 nCharLen += 1;
     352             :             }
     353             :             nByteLen = 4 * nCharLen;
     354             :         }
     355             :     }
     356             :     else
     357             :     {
     358             :         assert(getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS2 &&
     359             :                getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS4);
     360             :         OString sOData(
     361           0 :             OUStringToOString(_sData, getOwnConnection()->getTextEncoding()));
     362           0 :         nCharLen = nByteLen = sOData.getLength();
     363           0 :         pData = allocBindBuf(parameterIndex, nByteLen);
     364           0 :         memcpy(pData, sOData.getStr(), nByteLen);
     365             :     }
     366             : 
     367           0 :     setParameter( parameterIndex, _nType, nCharLen, _nScale, pData, nByteLen, nByteLen );
     368           0 : }
     369             : 
     370           0 : void OPreparedStatement::setParameter(const sal_Int32 parameterIndex, const sal_Int32 _nType, const Sequence< sal_Int8 > &x)
     371             : {
     372           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     373           0 :     setParameterPre(parameterIndex);
     374             : 
     375             :     assert(_nType == DataType::BINARY || _nType == DataType::VARBINARY);
     376             : 
     377             :     // don't copy the sequence, just point the ODBC directly at the sequence's storage array
     378             :     // Why BINARY/Sequence is treated differently than strings (which are copied), I'm not sure
     379           0 :     OSL_VERIFY(allocBindBuf(parameterIndex, 0) == NULL);
     380           0 :     boundParams[parameterIndex-1].setSequence(x); // this ensures that the sequence stays alive
     381             : 
     382           0 :     setParameter( parameterIndex, _nType, x.getLength(), invalid_scale, x.getConstArray(), x.getLength(), x.getLength() );
     383           0 : }
     384             : 
     385           0 : 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)
     386             : {
     387             :     SQLSMALLINT fCType, fSqlType;
     388           0 :     OTools::getBindTypes(useWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
     389             : 
     390           0 :     SQLLEN& rDataLen = boundParams[parameterIndex-1].getBindLengthBuffer();
     391           0 :     rDataLen = _nDataLen;
     392             : 
     393             :     SQLRETURN nRetcode;
     394           0 :     nRetcode = (*reinterpret_cast<T3SQLBindParameter>(m_pConnection->getOdbcFunction(ODBC3SQLFunctionId::BindParameter)))(
     395             :                   m_aStatementHandle,
     396             :                   // checkParameterIndex guarantees this is safe
     397             :                   static_cast<SQLUSMALLINT>(parameterIndex),
     398             :                   SQL_PARAM_INPUT,
     399             :                   fCType,
     400             :                   fSqlType,
     401             :                   _nColumnSize,
     402             :                   _nScale,
     403             :                   // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
     404             :                   const_cast<void*>(_pData),
     405             :                   _nDataAllocLen,
     406           0 :                   &rDataLen);
     407             : 
     408           0 :     OTools::ThrowException(m_pConnection, nRetcode, m_aStatementHandle, SQL_HANDLE_STMT, *this);
     409           0 : }
     410             : 
     411           0 : void SAL_CALL OPreparedStatement::setByte( const sal_Int32 parameterIndex, const sal_Int8 x ) throw(SQLException, RuntimeException, std::exception)
     412             : {
     413           0 :     setScalarParameter(parameterIndex, DataType::TINYINT, 3, x);
     414           0 : }
     415             : 
     416           0 : void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException, std::exception)
     417             : {
     418           0 :     DATE_STRUCT x(OTools::DateToOdbcDate(aData));
     419           0 :     setScalarParameter<DATE_STRUCT&>(parameterIndex, DataType::DATE, 10, x);
     420           0 : }
     421             : 
     422           0 : void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& aVal ) throw(SQLException, RuntimeException, std::exception)
     423             : {
     424             :     SQLULEN nColSize;
     425           0 :     if(aVal.NanoSeconds == 0)
     426           0 :         nColSize = 8;
     427           0 :     else if(aVal.NanoSeconds % 100000000 == 0)
     428           0 :         nColSize = 10;
     429           0 :     else if(aVal.NanoSeconds % 10000000 == 0)
     430           0 :         nColSize = 11;
     431           0 :     else if(aVal.NanoSeconds % 1000000 == 0)
     432           0 :         nColSize = 12;
     433           0 :     else if(aVal.NanoSeconds % 100000 == 0)
     434           0 :         nColSize = 13;
     435           0 :     else if(aVal.NanoSeconds % 10000 == 0)
     436           0 :         nColSize = 14;
     437           0 :     else if(aVal.NanoSeconds % 1000 == 0)
     438           0 :         nColSize = 15;
     439           0 :     else if(aVal.NanoSeconds % 100 == 0)
     440           0 :         nColSize = 16;
     441           0 :     else if(aVal.NanoSeconds % 10 == 0)
     442           0 :         nColSize = 17;
     443             :     else
     444           0 :         nColSize = 18;
     445           0 :     TIME_STRUCT x(OTools::TimeToOdbcTime(aVal));
     446           0 :     setScalarParameter<TIME_STRUCT&>(parameterIndex, DataType::TIME, nColSize, x);
     447           0 : }
     448             : 
     449             : 
     450           0 : void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException, std::exception)
     451             : {
     452             :     SQLULEN nColSize;
     453           0 :     if(aVal.NanoSeconds == 0)
     454             :     {
     455           0 :         if (aVal.Seconds == 0)
     456           0 :             nColSize=16;
     457             :         else
     458           0 :             nColSize=19;
     459             :     }
     460           0 :     else if(aVal.NanoSeconds % 100000000 == 0)
     461           0 :         nColSize = 21;
     462           0 :     else if(aVal.NanoSeconds % 10000000 == 0)
     463           0 :         nColSize = 22;
     464           0 :     else if(aVal.NanoSeconds % 1000000 == 0)
     465           0 :         nColSize = 23;
     466           0 :     else if(aVal.NanoSeconds % 100000 == 0)
     467           0 :         nColSize = 24;
     468           0 :     else if(aVal.NanoSeconds % 10000 == 0)
     469           0 :         nColSize = 25;
     470           0 :     else if(aVal.NanoSeconds % 1000 == 0)
     471           0 :         nColSize = 26;
     472           0 :     else if(aVal.NanoSeconds % 100 == 0)
     473           0 :         nColSize = 27;
     474           0 :     else if(aVal.NanoSeconds % 10 == 0)
     475           0 :         nColSize = 28;
     476             :     else
     477           0 :         nColSize = 29;
     478             : 
     479           0 :     TIMESTAMP_STRUCT x(OTools::DateTimeToTimestamp(aVal));
     480           0 :     setScalarParameter<TIMESTAMP_STRUCT&>(parameterIndex, DataType::TIMESTAMP, nColSize, x);
     481           0 : }
     482             : 
     483             : 
     484           0 : void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException, std::exception)
     485             : {
     486           0 :     setScalarParameter(parameterIndex, DataType::DOUBLE, 15, x);
     487           0 : }
     488             : 
     489             : 
     490             : 
     491           0 : void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException, std::exception)
     492             : {
     493           0 :     setScalarParameter(parameterIndex, DataType::FLOAT, 15, x);
     494           0 : }
     495             : 
     496             : 
     497           0 : void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException, std::exception)
     498             : {
     499           0 :     setScalarParameter(parameterIndex, DataType::INTEGER, 10, x);
     500           0 : }
     501             : 
     502             : 
     503           0 : void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException, std::exception)
     504             : {
     505             :     try
     506             :     {
     507           0 :         setScalarParameter(parameterIndex, DataType::BIGINT, 19, x);
     508             :     }
     509           0 :     catch(SQLException&)
     510             :     {
     511           0 :         setString(parameterIndex, ORowSetValue(x));
     512             :     }
     513           0 : }
     514             : 
     515             : 
     516           0 : void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, const sal_Int32 _nType ) throw(SQLException, RuntimeException, std::exception)
     517             : {
     518           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     519           0 :     setParameterPre(parameterIndex);
     520             : 
     521           0 :     OSL_VERIFY(allocBindBuf(parameterIndex, 0) == NULL);
     522           0 :     SQLLEN * const lenBuf = getLengthBuf (parameterIndex);
     523           0 :     *lenBuf = SQL_NULL_DATA;
     524             : 
     525             : 
     526             :     SQLSMALLINT fCType;
     527             :     SQLSMALLINT fSqlType;
     528             : 
     529             :     OTools::getBindTypes(   useWChar,
     530           0 :                             m_pConnection->useOldDateFormat(),
     531           0 :                             OTools::jdbcTypeToOdbc(_nType),
     532             :                             fCType,
     533           0 :                             fSqlType);
     534             : 
     535           0 :     SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
     536             :                                             static_cast<SQLUSMALLINT>(parameterIndex),
     537             :                                             SQL_PARAM_INPUT,
     538             :                                             fCType,
     539             :                                             fSqlType,
     540             :                                             0,
     541             :                                             0,
     542             :                                             NULL,
     543             :                                             0,
     544             :                                             lenBuf
     545             :                                             );
     546           0 :     OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
     547           0 : }
     548             : 
     549             : 
     550           0 : void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException, std::exception)
     551             : {
     552           0 :     if ( x.is() )
     553           0 :         setStream(parameterIndex, x->getCharacterStream(), x->length(), DataType::LONGVARCHAR);
     554           0 : }
     555             : 
     556             : 
     557           0 : void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException, std::exception)
     558             : {
     559           0 :     if ( x.is() )
     560           0 :         setStream(parameterIndex, x->getBinaryStream(), x->length(), DataType::LONGVARBINARY);
     561           0 : }
     562             : 
     563             : 
     564           0 : void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
     565             : {
     566           0 :     ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setArray", *this );
     567           0 : }
     568             : 
     569             : 
     570           0 : void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException, std::exception)
     571             : {
     572           0 :     ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setRef", *this );
     573           0 : }
     574             : 
     575           0 : void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException, std::exception)
     576             : {
     577           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     578           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     579             : 
     580           0 :     prepareStatement();
     581             :     // For each known SQL Type, call the appropriate
     582             :         // set routine
     583             : 
     584           0 :     switch (sqlType)
     585             :     {
     586             :         case DataType::CHAR:
     587             :         case DataType::VARCHAR:
     588             :         case DataType::LONGVARCHAR:
     589           0 :             if(x.hasValue())
     590             :             {
     591           0 :                 OUString sStr;
     592           0 :                 x >>= sStr;
     593           0 :                 setParameter(parameterIndex, sqlType, scale, sStr);
     594             :             }
     595             :             else
     596           0 :                 setNull(parameterIndex,sqlType);
     597           0 :             break;
     598             :         case DataType::DECIMAL:
     599             :         case DataType::NUMERIC:
     600           0 :             if(x.hasValue())
     601             :             {
     602           0 :                 ORowSetValue aValue;
     603           0 :                 aValue.fill(x);
     604             :                 // TODO: make sure that this calls the string overload
     605           0 :                 setParameter(parameterIndex, sqlType, scale, aValue);
     606             :             }
     607             :             else
     608           0 :                 setNull(parameterIndex,sqlType);
     609           0 :             break;
     610             :         default:
     611           0 :             ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
     612           0 :         }
     613           0 : }
     614             : 
     615             : 
     616           0 : void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ ) throw(SQLException, RuntimeException, std::exception)
     617             : {
     618           0 :     setNull(parameterIndex,sqlType);
     619           0 : }
     620             : 
     621             : 
     622           0 : void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException, std::exception)
     623             : {
     624           0 :     if (!::dbtools::implSetObject(this, parameterIndex, x))
     625             :     {   // there is no other setXXX call which can handle the value in x
     626           0 :         throw SQLException();
     627             :     }
     628           0 : }
     629             : 
     630             : 
     631           0 : void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException, std::exception)
     632             : {
     633           0 :     setScalarParameter(parameterIndex, DataType::SMALLINT, 5, x);
     634           0 : }
     635             : 
     636             : 
     637           0 : void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException, std::exception)
     638             : {
     639           0 :     setParameter(parameterIndex, DataType::BINARY, x);
     640           0 : }
     641             : 
     642             : 
     643             : 
     644           0 : void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException, std::exception)
     645             : {
     646             :     // LEM: It is quite unclear to me what the interface here is.
     647             :     // The XInputStream provides *bytes*, not characters.
     648           0 :     setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
     649           0 : }
     650             : 
     651             : 
     652           0 : void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException, std::exception)
     653             : {
     654           0 :     setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
     655           0 : }
     656             : 
     657             : 
     658           0 : void SAL_CALL OPreparedStatement::clearParameters(  ) throw(SQLException, RuntimeException, std::exception)
     659             : {
     660           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     661           0 :     prepareStatement();
     662             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     663           0 :     SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
     664           0 :     nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
     665           0 :     OSL_UNUSED(nRet);
     666           0 : }
     667             : 
     668           0 : void SAL_CALL OPreparedStatement::clearBatch(  ) throw(SQLException, RuntimeException, std::exception)
     669             : {
     670           0 :     ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::clearBatch", *this );
     671             :     //  clearParameters(  );
     672             :     //  m_aBatchList.erase();
     673           0 : }
     674             : 
     675             : 
     676           0 : void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException, std::exception)
     677             : {
     678           0 :     ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::addBatch", *this );
     679           0 : }
     680             : 
     681             : 
     682           0 : Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch(  ) throw(SQLException, RuntimeException, std::exception)
     683             : {
     684           0 :     ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::executeBatch", *this );
     685             :     // not reached, but keep -Werror happy
     686           0 :     return Sequence< sal_Int32 > ();
     687             : }
     688             : 
     689             : 
     690             : 
     691             : // methods
     692             : 
     693             : 
     694             : 
     695             : // initBoundParam
     696             : // Initialize the bound parameter objects
     697             : 
     698             : 
     699           0 : void OPreparedStatement::initBoundParam () throw(SQLException)
     700             : {
     701             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     702             :     // Get the number of parameters
     703           0 :     numParams = 0;
     704           0 :     N3SQLNumParams (m_aStatementHandle,&numParams);
     705             : 
     706             :     // There are parameter markers, allocate the bound
     707             :     // parameter objects
     708             : 
     709           0 :     if (numParams > 0)
     710             :     {
     711             :         // Allocate an array of bound parameter objects
     712             : 
     713           0 :         boundParams = new OBoundParam[numParams];
     714             : 
     715             :     }
     716           0 : }
     717             : 
     718             : 
     719             : 
     720             : // allocBindBuf
     721             : // Allocate storage for the permanent data buffer for the bound
     722             : // parameter.
     723             : 
     724             : 
     725           0 : void* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
     726             : {
     727           0 :     void* b = NULL;
     728             : 
     729             :     // Sanity check the parameter number
     730             : 
     731           0 :     if ((index >= 1) && (index <= numParams))
     732             :     {
     733           0 :         b = boundParams[index - 1].allocBindDataBuffer(bufLen);
     734             :     }
     735             : 
     736           0 :     return b;
     737             : }
     738             : 
     739             : 
     740             : 
     741             : // getLengthBuf
     742             : // Gets the length buffer for the given parameter index
     743             : 
     744             : 
     745           0 : SQLLEN* OPreparedStatement::getLengthBuf (sal_Int32 index)
     746             : {
     747           0 :     SQLLEN* b = NULL;
     748             : 
     749             :     // Sanity check the parameter number
     750             : 
     751           0 :     if ((index >= 1) &&
     752           0 :         (index <= numParams))
     753             :     {
     754           0 :         b = &boundParams[index - 1].getBindLengthBuffer ();
     755             :     }
     756             : 
     757           0 :     return b;
     758             : }
     759             : 
     760             : 
     761             : 
     762             : // putParamData
     763             : // Puts parameter data from a previously bound input stream.  The
     764             : // input stream was bound using SQL_LEN_DATA_AT_EXEC.
     765           0 : void OPreparedStatement::putParamData (sal_Int32 index)
     766             :     throw (SQLException, RuntimeException)
     767             : {
     768             :     // Sanity check the parameter index
     769           0 :     if ((index < 1) ||
     770           0 :         (index > numParams))
     771             :     {
     772           0 :         return;
     773             :     }
     774             : 
     775             :     // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
     776           0 :     Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH );
     777             : 
     778             :     // Get the information about the input stream
     779             : 
     780           0 :     Reference< XInputStream> inputStream =  boundParams[index - 1].getInputStream ();
     781           0 :     if ( !inputStream.is() )
     782             :     {
     783           0 :         ::connectivity::SharedResources aResources;
     784           0 :         const OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
     785           0 :         throw SQLException (sError, *this,OUString(),0,Any());
     786             :     }
     787             : 
     788           0 :     sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
     789             : 
     790             :     // Loop while more data from the input stream
     791           0 :     sal_Int32 haveRead = 0;
     792             :     try
     793             :     {
     794             : 
     795           0 :         do
     796             :         {
     797           0 :             sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
     798             : 
     799             :             // Read some data from the input stream
     800           0 :             haveRead = inputStream->readBytes( buf, toReadThisRound );
     801             :             OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
     802             : 
     803           0 :             if ( !haveRead )
     804             :                 // no more data in the stream - the given stream length was a maximum which could not be
     805             :                 // fulfilled by the stream
     806           0 :                 break;
     807             : 
     808             :             // Put the data
     809             :             OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
     810           0 :             N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
     811             : 
     812             :             // decrement the number of bytes still needed
     813           0 :             maxBytesLeft -= haveRead;
     814             :         }
     815           0 :         while ( maxBytesLeft > 0 );
     816             :     }
     817           0 :     catch (const IOException& ex)
     818             :     {
     819             : 
     820             :         // If an I/O exception was generated, turn
     821             :         // it into a SQLException
     822             : 
     823           0 :         throw SQLException(ex.Message,*this,OUString(),0,Any());
     824           0 :     }
     825             : }
     826             : 
     827             : // setStream
     828             : // Sets an input stream as a parameter, using the given SQL type
     829           0 : void OPreparedStatement::setStream(
     830             :                                     sal_Int32 ParameterIndex,
     831             :                                     const Reference< XInputStream>& x,
     832             :                                     SQLLEN length,
     833             :                                     sal_Int32 _nType)
     834             :                                     throw (SQLException, RuntimeException)
     835             : {
     836           0 :     ::osl::MutexGuard aGuard( m_aMutex );
     837           0 :     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
     838             : 
     839             : 
     840           0 :     prepareStatement();
     841             : 
     842           0 :     checkParameterIndex(ParameterIndex);
     843             :     // Get the buffer needed for the length
     844             : 
     845           0 :     SQLLEN * const lenBuf = getLengthBuf(ParameterIndex);
     846             : 
     847             :     // Allocate a new buffer for the parameter data.  This buffer
     848             :     // will be returned by SQLParamData (it is set to the parameter
     849             :     // number, a sal_Int32)
     850             : 
     851           0 :     sal_Int32* dataBuf = static_cast<sal_Int32*>( allocBindBuf(ParameterIndex, sizeof(ParameterIndex)) );
     852           0 :     *dataBuf = ParameterIndex;
     853             : 
     854             :     // Bind the parameter with SQL_LEN_DATA_AT_EXEC
     855           0 :     *lenBuf = SQL_LEN_DATA_AT_EXEC (length);
     856             : 
     857             :     SQLSMALLINT fCType, fSqlType;
     858           0 :     OTools::getBindTypes(useWChar, m_pConnection->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType), fCType, fSqlType);
     859             : 
     860             : 
     861             :     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     862           0 :     N3SQLBindParameter(m_aStatementHandle,
     863             :                        static_cast<SQLUSMALLINT>(ParameterIndex),
     864             :                        SQL_PARAM_INPUT,
     865             :                        fCType,
     866             :                        fSqlType,
     867             :                        length,
     868             :                        invalid_scale,
     869             :                        dataBuf,
     870             :                        sizeof(ParameterIndex),
     871           0 :                        lenBuf);
     872             : 
     873             :     // Save the input stream
     874           0 :     boundParams[ParameterIndex - 1].setInputStream (x, length);
     875           0 : }
     876             : 
     877             : 
     878             : 
     879             : 
     880           0 : void OPreparedStatement::FreeParams()
     881             : {
     882           0 :     numParams = 0;
     883           0 :     delete [] boundParams;
     884           0 :     boundParams = NULL;
     885           0 : }
     886             : 
     887           0 : void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception, std::exception)
     888             : {
     889             :     try
     890             :     {
     891           0 :         switch(nHandle)
     892             :         {
     893             :             case PROPERTY_ID_RESULTSETCONCURRENCY:
     894           0 :                 if(!isPrepared())
     895           0 :                     setResultSetConcurrency(comphelper::getINT32(rValue));
     896           0 :                 break;
     897             :             case PROPERTY_ID_RESULTSETTYPE:
     898           0 :                 if(!isPrepared())
     899           0 :                     setResultSetType(comphelper::getINT32(rValue));
     900           0 :                 break;
     901             :             case PROPERTY_ID_FETCHDIRECTION:
     902           0 :                 if(!isPrepared())
     903           0 :                     setFetchDirection(comphelper::getINT32(rValue));
     904           0 :                 break;
     905             :             case PROPERTY_ID_USEBOOKMARKS:
     906           0 :                 if(!isPrepared())
     907           0 :                     setUsingBookmarks(comphelper::getBOOL(rValue));
     908           0 :                 break;
     909             :             default:
     910           0 :                 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
     911             :         }
     912             :     }
     913           0 :     catch(const SQLException&)
     914             :     {
     915             :         //  throw Exception(e.Message,*this);
     916             :     }
     917           0 : }
     918             : 
     919           0 : void OPreparedStatement::prepareStatement()
     920             : {
     921           0 :     if(!isPrepared())
     922             :     {
     923             :         OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
     924           0 :         OString aSql(OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
     925           0 :         SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength());
     926           0 :         OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
     927           0 :         m_bPrepared = true;
     928           0 :         initBoundParam();
     929             :     }
     930           0 : }
     931             : 
     932           0 : void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
     933             : {
     934           0 :     if( _parameterIndex > numParams ||
     935           0 :         _parameterIndex < 1 ||
     936           0 :         _parameterIndex > std::numeric_limits<SQLUSMALLINT>::max() )
     937             :     {
     938           0 :         ::connectivity::SharedResources aResources;
     939             :         const OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
     940             :             "$pos$", OUString::number(_parameterIndex),
     941             :             "$count$", OUString::number(numParams)
     942           0 :             ));
     943           0 :         SQLException aNext(sError,*this, OUString(),0,Any());
     944             : 
     945           0 :         ::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
     946             :     }
     947           0 : }
     948             : 
     949           0 : OResultSet* OPreparedStatement::createResulSet()
     950             : {
     951           0 :     OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
     952           0 :     pReturn->setMetaData(getMetaData());
     953           0 :     return pReturn;
     954             : }
     955             : 
     956             : 
     957             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11