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

Generated by: LCOV version 1.10