1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
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
;
57 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
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;
67 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OUString
& sql
)
68 :OStatement_BASE2(_pConnection
)
73 m_sSqlStatement
= sql
;
76 if(_pConnection
->isParameterSubstitutionEnabled())
78 OSQLParser
aParser( comphelper::getComponentContext(_pConnection
->getDriver()->getORB()) );
79 OUString sErrorMessage
;
81 boost::scoped_ptr
<OSQLParseNode
> pNode( aParser
.parseTree(sErrorMessage
,sql
) );
83 { // special handling for parameters
84 OSQLParseNode::substituteParameterNames(pNode
.get());
85 pNode
->parseNodeToStr( sNewSql
, _pConnection
);
86 m_sSqlStatement
= sNewSql
;
95 void SAL_CALL
OPreparedStatement::acquire() throw()
97 OStatement_BASE2::acquire();
100 void SAL_CALL
OPreparedStatement::release() throw()
102 OStatement_BASE2::release();
105 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
, std::exception
)
107 Any aRet
= OStatement_BASE2::queryInterface(rType
);
108 return aRet
.hasValue() ? aRet
: OPreparedStatement_BASE::queryInterface(rType
);
111 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
, std::exception
)
113 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
117 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
, std::exception
)
119 ::osl::MutexGuard
aGuard( m_aMutex
);
120 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
124 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
125 if(!m_xMetaData
.is())
126 m_xMetaData
= new OResultSetMetaData(getOwnConnection(),m_aStatementHandle
);
131 void SAL_CALL
OPreparedStatement::close( ) throw(SQLException
, RuntimeException
, std::exception
)
133 ::osl::MutexGuard
aGuard( m_aMutex
);
134 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
137 // Close/clear our result set
140 // Reset last warning message
144 OStatement_BASE2::close();
147 catch (SQLException
&) {
148 // If we get an error, ignore
151 // Remove this Statement object from the Connection object's
156 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
, std::exception
)
158 ::osl::MutexGuard
aGuard( m_aMutex
);
159 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
162 bool needData
= false;
168 // Reset the statement handle, warning and saved Resultset
175 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
178 SQLRETURN nReturn
= N3SQLExecute(m_aStatementHandle
);
180 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
181 needData
= nReturn
== SQL_NEED_DATA
;
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.
189 // Get the parameter number that requires data
191 sal_Int32
* paramIndex
= 0;
192 nReturn
= N3SQLParamData(m_aStatementHandle
,(SQLPOINTER
*)¶mIndex
);
194 // If the parameter index is -1, there is no
195 // more data required
197 if ( !paramIndex
|| ( *paramIndex
== -1 ) )
201 // Now we have the proper parameter
202 // index, get the data from the input
203 // stream and do a SQLPutData
204 putParamData (*paramIndex
);
209 catch (const SQLWarning
&)
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.
218 return getColumnCount() > 0;
222 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
, std::exception
)
224 ::osl::MutexGuard
aGuard( m_aMutex
);
225 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
227 sal_Int32 numRows
= -1;
230 // Execute the statement. If execute returns sal_False, a
234 numRows
= getUpdateCount ();
237 // No update count was produced (a ResultSet was). Raise
239 m_pConnection
->throwGenericSQLException(STR_NO_ROWCOUNT
,*this);
245 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
, std::exception
)
247 setParameter(parameterIndex
, DataType::CHAR
, invalid_scale
, x
);
251 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
, std::exception
)
253 ::osl::MutexGuard
aGuard( m_aMutex
);
254 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
256 return (Reference
< XConnection
>)m_pConnection
;
260 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
, std::exception
)
262 ::osl::MutexGuard
aGuard( m_aMutex
);
263 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
265 Reference
< XResultSet
> rs
= NULL
;
270 rs
= getResultSet(false);
273 // No ResultSet was produced. Raise an exception
274 m_pConnection
->throwGenericSQLException(STR_NO_RESULTSET
,*this);
280 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
, std::exception
)
282 // Set the parameter as if it were an integer
283 setInt (parameterIndex
, x
? 1 : 0 );
286 // The MutexGuard must _already_ be taken!
287 void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex
)
289 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
291 checkParameterIndex(parameterIndex
);
292 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
296 template <typename T
> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex
, const sal_Int32 i_nType
, const SQLULEN i_nColSize
, const T i_Value
)
298 ::osl::MutexGuard
aGuard( m_aMutex
);
299 setParameterPre(parameterIndex
);
301 typedef typename
boost::remove_reference
< T
>::type TnoRef
;
303 TnoRef
*bindBuf
= static_cast< TnoRef
* >( allocBindBuf(parameterIndex
, sizeof(i_Value
)) );
306 setParameter(parameterIndex
, i_nType
, i_nColSize
, invalid_scale
, bindBuf
, sizeof(i_Value
), sizeof(i_Value
));
310 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const sal_Int16 _nScale
, const OUString
&_sData
)
312 ::osl::MutexGuard
aGuard( m_aMutex
);
313 setParameterPre(parameterIndex
);
315 assert (_nType
== DataType::VARCHAR
|| _nType
== DataType::CHAR
|| _nType
== DataType::DECIMAL
|| _nType
== DataType::NUMERIC
);
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
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!
335 * Our internal OUString storage is always UTF-16, so no conversion to do here.
337 BOOST_STATIC_ASSERT( sizeof(sal_Unicode
) == 2 );
338 BOOST_STATIC_ASSERT( sizeof(SQLWCHAR
) == 2 );
339 nCharLen
= _sData
.getLength();
340 nByteLen
= nCharLen
* sizeof(sal_Unicode
);
341 pData
= allocBindBuf(parameterIndex
, nByteLen
);
342 memcpy(pData
, _sData
.getStr(), nByteLen
);
346 OString
sOData( OUStringToOString(_sData
, getOwnConnection()->getTextEncoding()) );
347 nCharLen
= sOData
.getLength();
349 pData
= allocBindBuf(parameterIndex
, nByteLen
);
350 memcpy(pData
, sOData
.getStr(), nByteLen
);
353 setParameter( parameterIndex
, _nType
, nCharLen
, _nScale
, pData
, nByteLen
, nByteLen
);
356 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const Sequence
< sal_Int8
> &x
)
358 ::osl::MutexGuard
aGuard( m_aMutex
);
359 setParameterPre(parameterIndex
);
361 assert(_nType
== DataType::BINARY
|| _nType
== DataType::VARBINARY
);
363 // don't copy the sequence, just point the ODBC directly at the sequence's storage array
364 // Why BINARY/Sequence is treated differently than strings (which are copied), I'm not sure
365 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == NULL
);
366 boundParams
[parameterIndex
-1].setSequence(x
); // this ensures that the sequence stays alive
368 setParameter( parameterIndex
, _nType
, x
.getLength(), invalid_scale
, x
.getConstArray(), x
.getLength(), x
.getLength() );
371 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
)
373 SQLSMALLINT fCType
, fSqlType
;
374 OTools::getBindTypes(useWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
376 SQLLEN
*pDataLen
=boundParams
[parameterIndex
-1].getBindLengthBuffer();
380 nRetcode
= (*(T3SQLBindParameter
)m_pConnection
->getOdbcFunction(ODBC3SQLBindParameter
))(
382 // checkParameterIndex guarantees this is safe
383 static_cast<SQLUSMALLINT
>(parameterIndex
),
389 // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
390 const_cast<void*>(_pData
),
394 OTools::ThrowException(m_pConnection
, nRetcode
, m_aStatementHandle
, SQL_HANDLE_STMT
, *this);
397 void SAL_CALL
OPreparedStatement::setByte( const sal_Int32 parameterIndex
, const sal_Int8 x
) throw(SQLException
, RuntimeException
, std::exception
)
399 setScalarParameter(parameterIndex
, DataType::TINYINT
, 3, x
);
402 // For older compilers (that do not support partial specialisation of class templates)
403 // uncomment if necessary (safe also on compilers that *do* support partial specialisation)
404 //BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION(DATE_STRUCT);
405 //BOOST_STATIC_ASSERT((boost::is_same<DATE_STRUCT, boost::remove_reference<DATE_STRUCT&>::type>::value));
406 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& aData
) throw(SQLException
, RuntimeException
, std::exception
)
408 DATE_STRUCT
x(OTools::DateToOdbcDate(aData
));
409 setScalarParameter
<DATE_STRUCT
&>(parameterIndex
, DataType::DATE
, 10, x
);
413 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const Time
& aVal
) throw(SQLException
, RuntimeException
, std::exception
)
416 if(aVal
.NanoSeconds
== 0)
418 else if(aVal
.NanoSeconds
% 100000000 == 0)
420 else if(aVal
.NanoSeconds
% 10000000 == 0)
422 else if(aVal
.NanoSeconds
% 1000000 == 0)
424 else if(aVal
.NanoSeconds
% 100000 == 0)
426 else if(aVal
.NanoSeconds
% 10000 == 0)
428 else if(aVal
.NanoSeconds
% 1000 == 0)
430 else if(aVal
.NanoSeconds
% 100 == 0)
432 else if(aVal
.NanoSeconds
% 10 == 0)
436 TIME_STRUCT
x(OTools::TimeToOdbcTime(aVal
));
437 setScalarParameter
<TIME_STRUCT
&>(parameterIndex
, DataType::TIME
, nColSize
, x
);
441 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& aVal
) throw(SQLException
, RuntimeException
, std::exception
)
444 if(aVal
.NanoSeconds
== 0)
446 if (aVal
.Seconds
== 0)
451 else if(aVal
.NanoSeconds
% 100000000 == 0)
453 else if(aVal
.NanoSeconds
% 10000000 == 0)
455 else if(aVal
.NanoSeconds
% 1000000 == 0)
457 else if(aVal
.NanoSeconds
% 100000 == 0)
459 else if(aVal
.NanoSeconds
% 10000 == 0)
461 else if(aVal
.NanoSeconds
% 1000 == 0)
463 else if(aVal
.NanoSeconds
% 100 == 0)
465 else if(aVal
.NanoSeconds
% 10 == 0)
470 TIMESTAMP_STRUCT
x(OTools::DateTimeToTimestamp(aVal
));
471 setScalarParameter
<TIMESTAMP_STRUCT
&>(parameterIndex
, DataType::TIMESTAMP
, nColSize
, x
);
475 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
) throw(SQLException
, RuntimeException
, std::exception
)
477 setScalarParameter(parameterIndex
, DataType::DOUBLE
, 15, x
);
482 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
) throw(SQLException
, RuntimeException
, std::exception
)
484 setScalarParameter(parameterIndex
, DataType::FLOAT
, 15, x
);
488 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
, std::exception
)
490 setScalarParameter(parameterIndex
, DataType::INTEGER
, 10, x
);
494 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
) throw(SQLException
, RuntimeException
, std::exception
)
498 setScalarParameter(parameterIndex
, DataType::BIGINT
, 19, x
);
502 setString(parameterIndex
, ORowSetValue(x
));
507 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, const sal_Int32 _nType
) throw(SQLException
, RuntimeException
, std::exception
)
509 ::osl::MutexGuard
aGuard( m_aMutex
);
510 setParameterPre(parameterIndex
);
512 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == NULL
);
513 SQLLEN
* const lenBuf
= getLengthBuf (parameterIndex
);
514 *lenBuf
= SQL_NULL_DATA
;
518 SQLSMALLINT fSqlType
;
520 OTools::getBindTypes( useWChar
,
521 m_pConnection
->useOldDateFormat(),
522 OTools::jdbcTypeToOdbc(_nType
),
526 SQLRETURN nReturn
= N3SQLBindParameter( m_aStatementHandle
,
527 static_cast<SQLUSMALLINT
>(parameterIndex
),
537 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
541 void SAL_CALL
OPreparedStatement::setClob( sal_Int32 parameterIndex
, const Reference
< XClob
>& x
) throw(SQLException
, RuntimeException
, std::exception
)
544 setStream(parameterIndex
, x
->getCharacterStream(), x
->length(), DataType::LONGVARCHAR
);
548 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32 parameterIndex
, const Reference
< XBlob
>& x
) throw(SQLException
, RuntimeException
, std::exception
)
551 setStream(parameterIndex
, x
->getBinaryStream(), x
->length(), DataType::LONGVARBINARY
);
555 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
, std::exception
)
557 ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
561 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
, std::exception
)
563 ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
566 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
) throw(SQLException
, RuntimeException
, std::exception
)
568 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
569 ::osl::MutexGuard
aGuard( m_aMutex
);
572 // For each known SQL Type, call the appropriate
578 case DataType::VARCHAR
:
579 case DataType::LONGVARCHAR
:
584 setParameter(parameterIndex
, sqlType
, scale
, sStr
);
587 setNull(parameterIndex
,sqlType
);
589 case DataType::DECIMAL
:
590 case DataType::NUMERIC
:
595 // TODO: make sure that this calls the string overload
596 setParameter(parameterIndex
, sqlType
, scale
, aValue
);
599 setNull(parameterIndex
,sqlType
);
602 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
607 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
, std::exception
)
609 setNull(parameterIndex
,sqlType
);
613 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
, std::exception
)
615 if (!::dbtools::implSetObject(this, parameterIndex
, x
))
616 { // there is no other setXXX call which can handle the value in x
617 throw SQLException();
622 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
, std::exception
)
624 setScalarParameter(parameterIndex
, DataType::SMALLINT
, 5, x
);
628 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
, std::exception
)
630 setParameter(parameterIndex
, DataType::BINARY
, x
);
635 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
637 // LEM: It is quite unclear to me what the interface here is.
638 // The XInputStream provides *bytes*, not characters.
639 setStream(parameterIndex
, x
, length
, DataType::LONGVARCHAR
);
643 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
, std::exception
)
645 setStream(parameterIndex
, x
, length
, DataType::LONGVARBINARY
);
649 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
, std::exception
)
651 ::osl::MutexGuard
aGuard( m_aMutex
);
653 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
654 SQLRETURN nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_RESET_PARAMS
);
655 nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_UNBIND
);
659 void SAL_CALL
OPreparedStatement::clearBatch( ) throw(SQLException
, RuntimeException
, std::exception
)
661 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::clearBatch", *this );
662 // clearParameters( );
663 // m_aBatchList.erase();
667 void SAL_CALL
OPreparedStatement::addBatch( ) throw(SQLException
, RuntimeException
, std::exception
)
669 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::addBatch", *this );
673 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( ) throw(SQLException
, RuntimeException
, std::exception
)
675 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::executeBatch", *this );
676 // not reached, but keep -Werror happy
677 return Sequence
< sal_Int32
> ();
687 // Initialize the bound parameter objects
690 void OPreparedStatement::initBoundParam () throw(SQLException
)
692 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
693 // Get the number of parameters
695 N3SQLNumParams (m_aStatementHandle
,&numParams
);
697 // There are parameter markers, allocate the bound
702 // Allocate an array of bound parameter objects
704 boundParams
= new OBoundParam
[numParams
];
712 // Allocate storage for the permanent data buffer for the bound
716 void* OPreparedStatement::allocBindBuf( sal_Int32 index
,sal_Int32 bufLen
)
720 // Sanity check the parameter number
722 if ((index
>= 1) && (index
<= numParams
))
724 b
= boundParams
[index
- 1].allocBindDataBuffer(bufLen
);
733 // Gets the length buffer for the given parameter index
736 SQLLEN
* OPreparedStatement::getLengthBuf (sal_Int32 index
)
740 // Sanity check the parameter number
743 (index
<= numParams
))
745 b
= boundParams
[index
- 1].getBindLengthBuffer ();
754 // Puts parameter data from a previously bound input stream. The
755 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
758 void OPreparedStatement::putParamData (sal_Int32 index
) throw(SQLException
)
760 // Sanity check the parameter index
767 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
768 Sequence
< sal_Int8
> buf( MAX_PUT_DATA_LENGTH
);
770 // Get the information about the input stream
772 Reference
< XInputStream
> inputStream
= boundParams
[index
- 1].getInputStream ();
773 if ( !inputStream
.is() )
775 ::connectivity::SharedResources aResources
;
776 const OUString
sError( aResources
.getResourceString(STR_NO_INPUTSTREAM
));
777 throw SQLException (sError
, *this,OUString(),0,Any());
780 sal_Int32 maxBytesLeft
= boundParams
[index
- 1].getInputStreamLen ();
782 // Loop while more data from the input stream
783 sal_Int32 haveRead
= 0;
789 sal_Int32 toReadThisRound
= ::std::min( MAX_PUT_DATA_LENGTH
, maxBytesLeft
);
791 // Read some data from the input stream
792 haveRead
= inputStream
->readBytes( buf
, toReadThisRound
);
793 OSL_ENSURE( haveRead
== buf
.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
796 // no more data in the stream - the given stream length was a maximum which could not be
797 // fulfilled by the stream
801 OSL_ENSURE( m_aStatementHandle
, "OPreparedStatement::putParamData: StatementHandle is null!" );
802 N3SQLPutData ( m_aStatementHandle
, buf
.getArray(), buf
.getLength() );
804 // decrement the number of bytes still needed
805 maxBytesLeft
-= haveRead
;
807 while ( maxBytesLeft
> 0 );
809 catch (const IOException
& ex
)
812 // If an I/O exception was generated, turn
813 // it into a SQLException
815 throw SQLException(ex
.Message
,*this,OUString(),0,Any());
822 // Sets an input stream as a parameter, using the given SQL type
825 void OPreparedStatement::setStream(
826 sal_Int32 ParameterIndex
,
827 const Reference
< XInputStream
>& x
,
832 ::osl::MutexGuard
aGuard( m_aMutex
);
833 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
838 checkParameterIndex(ParameterIndex
);
839 // Get the buffer needed for the length
841 SQLLEN
* const lenBuf
= getLengthBuf(ParameterIndex
);
843 // Allocate a new buffer for the parameter data. This buffer
844 // will be returned by SQLParamData (it is set to the parameter
845 // number, a sal_Int32)
847 sal_Int32
* dataBuf
= static_cast<sal_Int32
*>( allocBindBuf(ParameterIndex
, sizeof(ParameterIndex
)) );
848 *dataBuf
= ParameterIndex
;
850 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
851 *lenBuf
= SQL_LEN_DATA_AT_EXEC (length
);
853 SQLSMALLINT fCType
, fSqlType
;
854 OTools::getBindTypes(useWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
857 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
858 N3SQLBindParameter(m_aStatementHandle
,
859 static_cast<SQLUSMALLINT
>(ParameterIndex
),
866 sizeof(ParameterIndex
),
869 // Save the input stream
870 boundParams
[ParameterIndex
- 1].setInputStream (x
, length
);
876 void OPreparedStatement::FreeParams()
879 delete [] boundParams
;
883 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
, std::exception
)
889 case PROPERTY_ID_RESULTSETCONCURRENCY
:
891 setResultSetConcurrency(comphelper::getINT32(rValue
));
893 case PROPERTY_ID_RESULTSETTYPE
:
895 setResultSetType(comphelper::getINT32(rValue
));
897 case PROPERTY_ID_FETCHDIRECTION
:
899 setFetchDirection(comphelper::getINT32(rValue
));
901 case PROPERTY_ID_USEBOOKMARKS
:
903 setUsingBookmarks(comphelper::getBOOL(rValue
));
906 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
909 catch(const SQLException
&)
911 // throw Exception(e.Message,*this);
915 void OPreparedStatement::prepareStatement()
919 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
920 OString
aSql(OUStringToOString(m_sSqlStatement
,getOwnConnection()->getTextEncoding()));
921 SQLRETURN nReturn
= N3SQLPrepare(m_aStatementHandle
,(SDB_ODBC_CHAR
*) aSql
.getStr(),aSql
.getLength());
922 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
928 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex
)
930 if( _parameterIndex
> numParams
||
931 _parameterIndex
< 1 ||
932 _parameterIndex
> std::numeric_limits
<SQLUSMALLINT
>::max() )
934 ::connectivity::SharedResources aResources
;
935 const OUString
sError( aResources
.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX
,
936 "$pos$", OUString::number(_parameterIndex
),
937 "$count$", OUString::number(numParams
)
939 SQLException
aNext(sError
,*this, OUString(),0,Any());
941 ::dbtools::throwInvalidIndexException(*this,makeAny(aNext
));
945 OResultSet
* OPreparedStatement::createResulSet()
947 OResultSet
* pReturn
= new OResultSet(m_aStatementHandle
,this);
948 pReturn
->setMetaData(getMetaData());
953 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */