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

Generated by: LCOV version 1.10