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 .
22 #include <osl/diagnose.h>
23 #include <odbc/OPreparedStatement.hxx>
24 #include <odbc/OBoundParam.hxx>
25 #include <com/sun/star/io/IOException.hpp>
26 #include <com/sun/star/sdbc/DataType.hpp>
27 #include <odbc/OTools.hxx>
28 #include <odbc/OResultSet.hxx>
29 #include <odbc/OResultSetMetaData.hxx>
30 #include <comphelper/sequence.hxx>
31 #include <connectivity/dbtools.hxx>
32 #include <comphelper/types.hxx>
33 #include <connectivity/FValue.hxx>
34 #include <strings.hrc>
36 #include <type_traits>
38 using namespace ::comphelper
;
39 using namespace connectivity
;
40 using namespace connectivity::odbc
;
41 using namespace com::sun::star::uno
;
42 using namespace com::sun::star::lang
;
43 using namespace com::sun::star::beans
;
44 using namespace com::sun::star::sdbc
;
45 using namespace com::sun::star::sdbcx
;
46 using namespace com::sun::star::container
;
47 using namespace com::sun::star::io
;
48 using namespace com::sun::star::util
;
50 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
54 // for now, never use wchar,
55 // but most of code is prepared to handle it
56 // in case we make this configurable
57 const bool bUseWChar
= false;
60 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OUString
& sql
)
61 :OStatement_BASE2(_pConnection
)
65 m_sSqlStatement
= sql
;
68 OPreparedStatement::~OPreparedStatement()
72 void SAL_CALL
OPreparedStatement::acquire() noexcept
74 OStatement_BASE2::acquire();
77 void SAL_CALL
OPreparedStatement::release() noexcept
79 OStatement_BASE2::release();
82 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
)
84 Any aRet
= OStatement_BASE2::queryInterface(rType
);
85 return aRet
.hasValue() ? aRet
: OPreparedStatement_BASE::queryInterface(rType
);
88 css::uno::Sequence
< css::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( )
90 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
94 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( )
96 ::osl::MutexGuard
aGuard( m_aMutex
);
97 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
101 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
102 if(!m_xMetaData
.is())
103 m_xMetaData
= new OResultSetMetaData(getOwnConnection(),m_aStatementHandle
);
108 void SAL_CALL
OPreparedStatement::close( )
110 ::osl::MutexGuard
aGuard( m_aMutex
);
111 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
114 // Close/clear our result set
117 // Reset last warning message
121 OStatement_BASE2::close();
124 catch (SQLException
&) {
125 // If we get an error, ignore
128 // Remove this Statement object from the Connection object's
133 sal_Bool SAL_CALL
OPreparedStatement::execute( )
135 ::osl::MutexGuard
aGuard( m_aMutex
);
136 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
142 // Reset the statement handle, warning and saved Resultset
149 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
152 SQLRETURN nReturn
= N3SQLExecute(m_aStatementHandle
);
154 OTools::ThrowException(m_pConnection
.get(),nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
155 bool needData
= nReturn
== SQL_NEED_DATA
;
157 // Now loop while more data is needed (i.e. a data-at-
158 // execution parameter was given). For each parameter
159 // that needs data, put the data from the input stream.
163 // Get the parameter number that requires data
165 sal_Int32
* paramIndex
= nullptr;
166 N3SQLParamData(m_aStatementHandle
, reinterpret_cast<SQLPOINTER
*>(¶mIndex
));
168 // If the parameter index is -1, there is no
169 // more data required
171 if ( !paramIndex
|| ( *paramIndex
== -1 ) )
175 // Now we have the proper parameter
176 // index, get the data from the input
177 // stream and do a SQLPutData
178 putParamData (*paramIndex
);
183 catch (const SQLWarning
&)
187 // Now determine if there is a result set associated with
188 // the SQL statement that was executed. Get the column
189 // count, and if it is not zero, there is a result set.
192 return getColumnCount() > 0;
196 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( )
198 ::osl::MutexGuard
aGuard( m_aMutex
);
199 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
201 sal_Int32 numRows
= -1;
204 // Execute the statement. If execute returns sal_False, a
208 numRows
= getUpdateCount ();
211 // No update count was produced (a ResultSet was). Raise
213 m_pConnection
->throwGenericSQLException(STR_NO_ROWCOUNT
,*this);
219 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const OUString
& x
)
221 setParameter(parameterIndex
, DataType::CHAR
, invalid_scale
, x
);
225 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( )
227 ::osl::MutexGuard
aGuard( m_aMutex
);
228 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
230 return m_pConnection
;
234 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( )
236 ::osl::MutexGuard
aGuard( m_aMutex
);
237 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
239 Reference
< XResultSet
> rs
;
244 rs
= getResultSet(false);
247 // No ResultSet was produced. Raise an exception
248 m_pConnection
->throwGenericSQLException(STR_NO_RESULTSET
,*this);
254 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
)
256 // Set the parameter as if it were an integer
257 setInt (parameterIndex
, x
? 1 : 0 );
260 // The MutexGuard must _already_ be taken!
261 void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex
)
263 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
265 checkParameterIndex(parameterIndex
);
266 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
270 template <typename T
> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex
, const sal_Int32 i_nType
, const SQLULEN i_nColSize
, const T i_Value
)
272 setScalarParameter(parameterIndex
, i_nType
, i_nColSize
, invalid_scale
, i_Value
);
276 template <typename T
> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex
, const sal_Int32 i_nType
, const SQLULEN i_nColSize
, sal_Int32 i_nScale
, const T i_Value
)
278 ::osl::MutexGuard
aGuard( m_aMutex
);
279 setParameterPre(parameterIndex
);
281 typedef typename
std::remove_reference
<T
>::type TnoRef
;
283 TnoRef
*bindBuf
= static_cast< TnoRef
* >( allocBindBuf(parameterIndex
, sizeof(i_Value
)) );
286 setParameter(parameterIndex
, i_nType
, i_nColSize
, i_nScale
, bindBuf
, sizeof(i_Value
), sizeof(i_Value
));
290 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const sal_Int16 _nScale
, const OUString
&_sData
)
292 ::osl::MutexGuard
aGuard( m_aMutex
);
293 setParameterPre(parameterIndex
);
295 assert (_nType
== DataType::VARCHAR
|| _nType
== DataType::CHAR
|| _nType
== DataType::DECIMAL
|| _nType
== DataType::NUMERIC
);
303 * On Windows, wchar is 16 bits (UTF-16 encoding), the ODBC "W" variants functions take UTF-16 encoded strings
304 * and character lengths are number of UTF-16 codepoints.
305 * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms716246%28v=vs.85%29.aspx
306 * ODBC Programmer's reference > Developing Applications > Programming Considerations > Unicode > Unicode Function Arguments
307 * http://support.microsoft.com/kb/294169
309 * UnixODBC can be configured at compile-time so that the "W" variants expect
310 * UTF-16 or UTF-32 encoded strings, and character lengths are number of codepoints.
311 * However, UTF-16 is the default, what all/most distributions do
312 * and the established API that most drivers implement.
313 * As wchar is often 32 bits, this differs from C-style strings of wchar!
315 * On MacOS X, the "W" variants use wchar_t, which is UCS4
317 * Our internal OUString storage is always UTF-16, so no conversion to do here.
319 static_assert(sizeof (SQLWCHAR
) == 2 || sizeof (SQLWCHAR
) == 4, "must be 2 or 4");
320 if (sizeof (SQLWCHAR
) == 2)
322 nCharLen
= _sData
.getLength();
323 nByteLen
= 2 * nCharLen
;
324 pData
= allocBindBuf(parameterIndex
, nByteLen
);
325 memcpy(pData
, _sData
.getStr(), nByteLen
);
329 pData
= allocBindBuf(parameterIndex
, _sData
.getLength() * 4);
330 sal_uInt32
* pCursor
= static_cast<sal_uInt32
*>(pData
);
332 for (sal_Int32 i
= 0; i
!= _sData
.getLength();)
334 *pCursor
++ = _sData
.iterateCodePoints(&i
);
337 nByteLen
= 4 * nCharLen
;
342 assert(getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS2
&&
343 getOwnConnection()->getTextEncoding() != RTL_TEXTENCODING_UCS4
);
345 OUStringToOString(_sData
, getOwnConnection()->getTextEncoding()));
346 nCharLen
= nByteLen
= sOData
.getLength();
347 pData
= allocBindBuf(parameterIndex
, nByteLen
);
348 memcpy(pData
, sOData
.getStr(), nByteLen
);
351 setParameter( parameterIndex
, _nType
, nCharLen
, _nScale
, pData
, nByteLen
, nByteLen
);
354 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const Sequence
< sal_Int8
> &x
)
356 ::osl::MutexGuard
aGuard( m_aMutex
);
357 setParameterPre(parameterIndex
);
359 assert(_nType
== DataType::BINARY
|| _nType
== DataType::VARBINARY
);
361 // don't copy the sequence, just point the ODBC directly at the sequence's storage array
362 // Why BINARY/Sequence is treated differently than strings (which are copied), I'm not sure
363 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == nullptr);
364 boundParams
[parameterIndex
-1].setSequence(x
); // this ensures that the sequence stays alive
366 setParameter( parameterIndex
, _nType
, x
.getLength(), invalid_scale
, x
.getConstArray(), x
.getLength(), x
.getLength() );
369 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 SQLSMALLINT fCType
, fSqlType
;
372 OTools::getBindTypes(bUseWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
374 SQLLEN
& rDataLen
= boundParams
[parameterIndex
-1].getBindLengthBuffer();
375 rDataLen
= _nDataLen
;
378 nRetcode
= (*reinterpret_cast<T3SQLBindParameter
>(m_pConnection
->getOdbcFunction(ODBC3SQLFunctionId::BindParameter
)))(
380 // checkParameterIndex guarantees this is safe
381 static_cast<SQLUSMALLINT
>(parameterIndex
),
387 // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
388 const_cast<void*>(_pData
),
392 OTools::ThrowException(m_pConnection
.get(), nRetcode
, m_aStatementHandle
, SQL_HANDLE_STMT
, *this);
395 void SAL_CALL
OPreparedStatement::setByte( const sal_Int32 parameterIndex
, const sal_Int8 x
)
397 setScalarParameter(parameterIndex
, DataType::TINYINT
, 3, 0, x
);
400 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& aData
)
402 DATE_STRUCT
x(OTools::DateToOdbcDate(aData
));
403 setScalarParameter
<DATE_STRUCT
&>(parameterIndex
, DataType::DATE
, 10, x
);
406 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const css::util::Time
& aVal
)
409 if(aVal
.NanoSeconds
== 0)
411 else if(aVal
.NanoSeconds
% 100000000 == 0)
413 else if(aVal
.NanoSeconds
% 10000000 == 0)
415 else if(aVal
.NanoSeconds
% 1000000 == 0)
417 else if(aVal
.NanoSeconds
% 100000 == 0)
419 else if(aVal
.NanoSeconds
% 10000 == 0)
421 else if(aVal
.NanoSeconds
% 1000 == 0)
423 else if(aVal
.NanoSeconds
% 100 == 0)
425 else if(aVal
.NanoSeconds
% 10 == 0)
429 TIME_STRUCT
x(OTools::TimeToOdbcTime(aVal
));
430 setScalarParameter
<TIME_STRUCT
&>(parameterIndex
, DataType::TIME
, nColSize
, (nColSize
== 8)? 0 : nColSize
-9, x
);
434 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& aVal
)
437 if(aVal
.NanoSeconds
== 0)
439 if (aVal
.Seconds
== 0)
444 else if(aVal
.NanoSeconds
% 100000000 == 0)
446 else if(aVal
.NanoSeconds
% 10000000 == 0)
448 else if(aVal
.NanoSeconds
% 1000000 == 0)
450 else if(aVal
.NanoSeconds
% 100000 == 0)
452 else if(aVal
.NanoSeconds
% 10000 == 0)
454 else if(aVal
.NanoSeconds
% 1000 == 0)
456 else if(aVal
.NanoSeconds
% 100 == 0)
458 else if(aVal
.NanoSeconds
% 10 == 0)
463 TIMESTAMP_STRUCT
x(OTools::DateTimeToTimestamp(aVal
));
464 setScalarParameter
<TIMESTAMP_STRUCT
&>(parameterIndex
, DataType::TIMESTAMP
, nColSize
, (nColSize
<= 19)? 0 : nColSize
-20, x
);
468 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
)
470 setScalarParameter(parameterIndex
, DataType::DOUBLE
, 15, x
);
474 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
)
476 setScalarParameter(parameterIndex
, DataType::FLOAT
, 15, x
);
480 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
)
482 setScalarParameter(parameterIndex
, DataType::INTEGER
, 10, 0, x
);
486 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
)
490 setScalarParameter(parameterIndex
, DataType::BIGINT
, 19, 0, x
);
494 setString(parameterIndex
, ORowSetValue(x
));
499 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, const sal_Int32 _nType
)
501 ::osl::MutexGuard
aGuard( m_aMutex
);
502 setParameterPre(parameterIndex
);
504 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == nullptr);
505 SQLLEN
* const lenBuf
= getLengthBuf (parameterIndex
);
506 *lenBuf
= SQL_NULL_DATA
;
510 SQLSMALLINT fSqlType
;
512 OTools::getBindTypes( bUseWChar
,
513 m_pConnection
->useOldDateFormat(),
514 OTools::jdbcTypeToOdbc(_nType
),
518 SQLRETURN nReturn
= N3SQLBindParameter( m_aStatementHandle
,
519 static_cast<SQLUSMALLINT
>(parameterIndex
),
529 OTools::ThrowException(m_pConnection
.get(),nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
533 void SAL_CALL
OPreparedStatement::setClob( sal_Int32 parameterIndex
, const Reference
< XClob
>& x
)
536 setStream(parameterIndex
, x
->getCharacterStream(), x
->length(), DataType::LONGVARCHAR
);
540 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32 parameterIndex
, const Reference
< XBlob
>& x
)
543 setStream(parameterIndex
, x
->getBinaryStream(), x
->length(), DataType::LONGVARBINARY
);
547 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ )
549 ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setArray", *this );
553 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ )
555 ::dbtools::throwFunctionNotSupportedSQLException( "XParameters::setRef", *this );
558 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
)
560 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
561 ::osl::MutexGuard
aGuard( m_aMutex
);
564 // For each known SQL Type, call the appropriate
570 case DataType::VARCHAR
:
571 case DataType::LONGVARCHAR
:
576 setParameter(parameterIndex
, sqlType
, scale
, sStr
);
579 setNull(parameterIndex
,sqlType
);
581 case DataType::DECIMAL
:
582 case DataType::NUMERIC
:
587 // TODO: make sure that this calls the string overload
588 setParameter(parameterIndex
, sqlType
, scale
, aValue
);
591 setNull(parameterIndex
,sqlType
);
594 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
599 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ )
601 setNull(parameterIndex
,sqlType
);
605 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
)
607 if (!::dbtools::implSetObject(this, parameterIndex
, x
))
608 { // there is no other setXXX call which can handle the value in x
609 throw SQLException();
614 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
)
616 setScalarParameter(parameterIndex
, DataType::SMALLINT
, 5, 0, x
);
620 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
)
622 setParameter(parameterIndex
, DataType::BINARY
, x
);
626 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
628 // LEM: It is quite unclear to me what the interface here is.
629 // The XInputStream provides *bytes*, not characters.
630 setStream(parameterIndex
, x
, length
, DataType::LONGVARCHAR
);
634 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
636 setStream(parameterIndex
, x
, length
, DataType::LONGVARBINARY
);
640 void SAL_CALL
OPreparedStatement::clearParameters( )
642 ::osl::MutexGuard
aGuard( m_aMutex
);
644 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
645 N3SQLFreeStmt (m_aStatementHandle
, SQL_RESET_PARAMS
);
646 N3SQLFreeStmt (m_aStatementHandle
, SQL_UNBIND
);
649 void SAL_CALL
OPreparedStatement::clearBatch( )
651 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::clearBatch", *this );
652 // clearParameters( );
653 // m_aBatchVector.erase();
657 void SAL_CALL
OPreparedStatement::addBatch( )
659 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::addBatch", *this );
663 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( )
665 ::dbtools::throwFunctionNotSupportedSQLException( "XPreparedBatchExecution::executeBatch", *this );
666 // not reached, but keep -Werror happy
667 return Sequence
< sal_Int32
> ();
675 // Initialize the bound parameter objects
678 void OPreparedStatement::initBoundParam ()
680 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
681 // Get the number of parameters
683 N3SQLNumParams (m_aStatementHandle
,&numParams
);
685 // There are parameter markers, allocate the bound
690 boundParams
.reset(new OBoundParam
[numParams
]);
696 // Allocate storage for the permanent data buffer for the bound
700 void* OPreparedStatement::allocBindBuf( sal_Int32 index
,sal_Int32 bufLen
)
704 // Sanity check the parameter number
706 if ((index
>= 1) && (index
<= numParams
))
708 b
= boundParams
[index
- 1].allocBindDataBuffer(bufLen
);
716 // Gets the length buffer for the given parameter index
719 SQLLEN
* OPreparedStatement::getLengthBuf (sal_Int32 index
)
723 // Sanity check the parameter number
726 (index
<= numParams
))
728 b
= &boundParams
[index
- 1].getBindLengthBuffer ();
736 // Puts parameter data from a previously bound input stream. The
737 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
738 void OPreparedStatement::putParamData (sal_Int32 index
)
740 // Sanity check the parameter index
747 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
748 Sequence
< sal_Int8
> buf( MAX_PUT_DATA_LENGTH
);
750 // Get the information about the input stream
752 Reference
< XInputStream
> inputStream
= boundParams
[index
- 1].getInputStream ();
753 if ( !inputStream
.is() )
755 ::connectivity::SharedResources aResources
;
756 const OUString
sError( aResources
.getResourceString(STR_NO_INPUTSTREAM
));
757 throw SQLException (sError
, *this,OUString(),0,Any());
760 sal_Int32 maxBytesLeft
= boundParams
[index
- 1].getInputStreamLen ();
762 // Loop while more data from the input stream
763 sal_Int32 haveRead
= 0;
769 sal_Int32 toReadThisRound
= std::min( MAX_PUT_DATA_LENGTH
, maxBytesLeft
);
771 // Read some data from the input stream
772 haveRead
= inputStream
->readBytes( buf
, toReadThisRound
);
773 OSL_ENSURE( haveRead
== buf
.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
776 // no more data in the stream - the given stream length was a maximum which could not be
777 // fulfilled by the stream
781 OSL_ENSURE( m_aStatementHandle
, "OPreparedStatement::putParamData: StatementHandle is null!" );
782 N3SQLPutData ( m_aStatementHandle
, buf
.getArray(), buf
.getLength() );
784 // decrement the number of bytes still needed
785 maxBytesLeft
-= haveRead
;
787 while ( maxBytesLeft
> 0 );
789 catch (const IOException
& ex
)
792 // If an I/O exception was generated, turn
793 // it into a SQLException
795 throw SQLException(ex
.Message
,*this,OUString(),0,Any());
800 // Sets an input stream as a parameter, using the given SQL type
801 void OPreparedStatement::setStream(
802 sal_Int32 ParameterIndex
,
803 const Reference
< XInputStream
>& x
,
807 ::osl::MutexGuard
aGuard( m_aMutex
);
808 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
813 checkParameterIndex(ParameterIndex
);
814 // Get the buffer needed for the length
816 SQLLEN
* const lenBuf
= getLengthBuf(ParameterIndex
);
818 // Allocate a new buffer for the parameter data. This buffer
819 // will be returned by SQLParamData (it is set to the parameter
820 // number, a sal_Int32)
822 sal_Int32
* dataBuf
= static_cast<sal_Int32
*>( allocBindBuf(ParameterIndex
, sizeof(ParameterIndex
)) );
823 *dataBuf
= ParameterIndex
;
825 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
826 *lenBuf
= SQL_LEN_DATA_AT_EXEC (length
);
828 SQLSMALLINT fCType
, fSqlType
;
829 OTools::getBindTypes(bUseWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
832 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
833 N3SQLBindParameter(m_aStatementHandle
,
834 static_cast<SQLUSMALLINT
>(ParameterIndex
),
841 sizeof(ParameterIndex
),
844 // Save the input stream
845 boundParams
[ParameterIndex
- 1].setInputStream (x
, length
);
849 void OPreparedStatement::FreeParams()
855 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
)
861 case PROPERTY_ID_RESULTSETCONCURRENCY
:
863 setResultSetConcurrency(comphelper::getINT32(rValue
));
865 case PROPERTY_ID_RESULTSETTYPE
:
867 setResultSetType(comphelper::getINT32(rValue
));
869 case PROPERTY_ID_FETCHDIRECTION
:
871 setFetchDirection(comphelper::getINT32(rValue
));
873 case PROPERTY_ID_USEBOOKMARKS
:
875 setUsingBookmarks(comphelper::getBOOL(rValue
));
878 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
881 catch(const SQLException
&)
883 // throw Exception(e.Message,*this);
887 void OPreparedStatement::prepareStatement()
891 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
892 OString
aSql(OUStringToOString(m_sSqlStatement
,getOwnConnection()->getTextEncoding()));
893 SQLRETURN nReturn
= N3SQLPrepare(m_aStatementHandle
, reinterpret_cast<SDB_ODBC_CHAR
*>(const_cast<char *>(aSql
.getStr())), aSql
.getLength());
894 OTools::ThrowException(m_pConnection
.get(),nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
900 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex
)
902 if( _parameterIndex
> numParams
||
903 _parameterIndex
< 1 ||
904 _parameterIndex
> std::numeric_limits
<SQLUSMALLINT
>::max() )
906 ::connectivity::SharedResources aResources
;
907 const OUString
sError( aResources
.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX
,
908 "$pos$", OUString::number(_parameterIndex
),
909 "$count$", OUString::number(numParams
)
911 SQLException
aNext(sError
,*this, OUString(),0,Any());
913 ::dbtools::throwInvalidIndexException(*this,makeAny(aNext
));
917 rtl::Reference
<OResultSet
> OPreparedStatement::createResultSet()
919 rtl::Reference
<OResultSet
> pReturn
= new OResultSet(m_aStatementHandle
,this);
920 pReturn
->setMetaData(getMetaData());
925 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */