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/type_traits/remove_reference.hpp>
42 #include <boost/type_traits/is_same.hpp>
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
;
56 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
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;
66 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const OUString
& sql
)
67 :OStatement_BASE2(_pConnection
)
70 ,m_bPrepared(sal_False
)
72 m_sSqlStatement
= sql
;
75 if(_pConnection
->isParameterSubstitutionEnabled())
77 OSQLParser
aParser( comphelper::getComponentContext(_pConnection
->getDriver()->getORB()) );
78 OUString sErrorMessage
;
80 ::std::auto_ptr
<OSQLParseNode
> pNode( aParser
.parseTree(sErrorMessage
,sql
) );
82 { // special handling for parameters
83 OSQLParseNode::substituteParameterNames(pNode
.get());
84 pNode
->parseNodeToStr( sNewSql
, _pConnection
);
85 m_sSqlStatement
= sNewSql
;
93 // -----------------------------------------------------------------------------
94 void SAL_CALL
OPreparedStatement::acquire() throw()
96 OStatement_BASE2::acquire();
98 // -----------------------------------------------------------------------------
99 void SAL_CALL
OPreparedStatement::release() throw()
101 OStatement_BASE2::release();
103 // -----------------------------------------------------------------------------
104 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
106 Any aRet
= OStatement_BASE2::queryInterface(rType
);
107 return aRet
.hasValue() ? aRet
: OPreparedStatement_BASE::queryInterface(rType
);
109 // -------------------------------------------------------------------------
110 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
112 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
114 // -------------------------------------------------------------------------
116 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
118 ::osl::MutexGuard
aGuard( m_aMutex
);
119 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
123 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
124 if(!m_xMetaData
.is())
125 m_xMetaData
= new OResultSetMetaData(getOwnConnection(),m_aStatementHandle
);
128 // -------------------------------------------------------------------------
130 void SAL_CALL
OPreparedStatement::close( ) throw(SQLException
, RuntimeException
)
132 ::osl::MutexGuard
aGuard( m_aMutex
);
133 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
136 // Close/clear our result set
139 // Reset last warning message
143 OStatement_BASE2::close();
146 catch (SQLException
&) {
147 // If we get an error, ignore
150 // Remove this Statement object from the Connection object's
153 // -------------------------------------------------------------------------
155 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
157 ::osl::MutexGuard
aGuard( m_aMutex
);
158 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
161 sal_Bool needData
= sal_False
;
167 // Reset the statement handle, warning and saved Resultset
174 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
177 SQLRETURN nReturn
= N3SQLExecute(m_aStatementHandle
);
179 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
180 needData
= nReturn
== SQL_NEED_DATA
;
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.
188 // Get the parameter number that requires data
190 sal_Int32
* paramIndex
= 0;
191 nReturn
= N3SQLParamData(m_aStatementHandle
,(SQLPOINTER
*)¶mIndex
);
193 // If the parameter index is -1, there is no
194 // more data required
196 if ( !paramIndex
|| ( *paramIndex
== -1 ) )
197 needData
= sal_False
;
200 // Now we have the proper parameter
201 // index, get the data from the input
202 // stream and do a SQLPutData
203 putParamData (*paramIndex
);
208 catch (const SQLWarning
&)
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.
217 return getColumnCount() > 0;
219 // -------------------------------------------------------------------------
221 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
223 ::osl::MutexGuard
aGuard( m_aMutex
);
224 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
226 sal_Int32 numRows
= -1;
229 // Execute the statement. If execute returns sal_False, a
233 numRows
= getUpdateCount ();
236 // No update count was produced (a ResultSet was). Raise
238 m_pConnection
->throwGenericSQLException(STR_NO_ROWCOUNT
,*this);
242 // -------------------------------------------------------------------------
244 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const OUString
& x
) throw(SQLException
, RuntimeException
)
246 setParameter(parameterIndex
, DataType::CHAR
, invalid_scale
, x
);
248 // -------------------------------------------------------------------------
250 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
252 ::osl::MutexGuard
aGuard( m_aMutex
);
253 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
255 return (Reference
< XConnection
>)m_pConnection
;
257 // -------------------------------------------------------------------------
259 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
261 ::osl::MutexGuard
aGuard( m_aMutex
);
262 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
264 Reference
< XResultSet
> rs
= NULL
;
269 rs
= getResultSet(sal_False
);
272 // No ResultSet was produced. Raise an exception
273 m_pConnection
->throwGenericSQLException(STR_NO_RESULTSET
,*this);
277 // -------------------------------------------------------------------------
279 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
)
281 // Set the parameter as if it were an integer
282 setInt (parameterIndex
, x
? 1 : 0 );
284 // -------------------------------------------------------------------------
285 // The MutexGuard must _already_ be taken!
286 void OPreparedStatement::setParameterPre(sal_Int32 parameterIndex
)
288 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
290 checkParameterIndex(parameterIndex
);
291 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
293 // -------------------------------------------------------------------------
295 template <typename T
> void OPreparedStatement::setScalarParameter(const sal_Int32 parameterIndex
, const sal_Int32 i_nType
, const SQLULEN i_nColSize
, const T i_Value
)
297 ::osl::MutexGuard
aGuard( m_aMutex
);
298 setParameterPre(parameterIndex
);
300 typedef typename
boost::remove_reference
< T
>::type TnoRef
;
302 TnoRef
*bindBuf
= static_cast< TnoRef
* >( allocBindBuf(parameterIndex
, sizeof(i_Value
)) );
305 setParameter(parameterIndex
, i_nType
, i_nColSize
, invalid_scale
, bindBuf
, sizeof(i_Value
), sizeof(i_Value
));
307 // -------------------------------------------------------------------------
309 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const sal_Int16 _nScale
, const OUString
&_sData
)
311 ::osl::MutexGuard
aGuard( m_aMutex
);
312 setParameterPre(parameterIndex
);
314 assert (_nType
== DataType::VARCHAR
|| _nType
== DataType::CHAR
|| _nType
== DataType::DECIMAL
|| _nType
== DataType::NUMERIC
);
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
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!
334 * Our internal OUString storage is always UTF-16, so no conversion to do here.
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
);
345 OString
sOData( OUStringToOString(_sData
, getOwnConnection()->getTextEncoding()) );
346 nCharLen
= sOData
.getLength();
348 pData
= allocBindBuf(parameterIndex
, nByteLen
);
349 memcpy(pData
, sOData
.getStr(), nByteLen
);
352 setParameter( parameterIndex
, _nType
, nCharLen
, _nScale
, pData
, nByteLen
, nByteLen
);
354 // -------------------------------------------------------------------------
355 void OPreparedStatement::setParameter(const sal_Int32 parameterIndex
, const sal_Int32 _nType
, const Sequence
< sal_Int8
> &x
)
357 ::osl::MutexGuard
aGuard( m_aMutex
);
358 setParameterPre(parameterIndex
);
360 assert(_nType
== DataType::BINARY
|| _nType
== DataType::VARBINARY
);
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 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == NULL
);
365 boundParams
[parameterIndex
-1].setSequence(x
); // this ensures that the sequence stays alive
367 setParameter( parameterIndex
, _nType
, x
.getLength(), invalid_scale
, x
.getConstArray(), x
.getLength(), x
.getLength() );
369 // -------------------------------------------------------------------------
370 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
)
372 SQLSMALLINT fCType
, fSqlType
;
373 OTools::getBindTypes(useWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
375 SQLLEN
*pDataLen
=boundParams
[parameterIndex
-1].getBindLengthBuffer();
379 nRetcode
= (*(T3SQLBindParameter
)m_pConnection
->getOdbcFunction(ODBC3SQLBindParameter
))(
381 // checkParameterIndex guarantees this is safe
382 static_cast<SQLUSMALLINT
>(parameterIndex
),
388 // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
389 const_cast<void*>(_pData
),
393 OTools::ThrowException(m_pConnection
, nRetcode
, m_aStatementHandle
, SQL_HANDLE_STMT
, *this);
395 // -----------------------------------------------------------------------------
396 void SAL_CALL
OPreparedStatement::setByte( const sal_Int32 parameterIndex
, const sal_Int8 x
) throw(SQLException
, RuntimeException
)
398 setScalarParameter(parameterIndex
, DataType::TINYINT
, 3, x
);
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 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& aData
) throw(SQLException
, RuntimeException
)
407 DATE_STRUCT
x(OTools::DateToOdbcDate(aData
));
408 setScalarParameter
<DATE_STRUCT
&>(parameterIndex
, DataType::DATE
, 10, x
);
410 // -------------------------------------------------------------------------
412 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const Time
& aVal
) throw(SQLException
, RuntimeException
)
415 if(aVal
.NanoSeconds
== 0)
417 else if(aVal
.NanoSeconds
% 100000000 == 0)
419 else if(aVal
.NanoSeconds
% 10000000 == 0)
421 else if(aVal
.NanoSeconds
% 1000000 == 0)
423 else if(aVal
.NanoSeconds
% 100000 == 0)
425 else if(aVal
.NanoSeconds
% 10000 == 0)
427 else if(aVal
.NanoSeconds
% 1000 == 0)
429 else if(aVal
.NanoSeconds
% 100 == 0)
431 else if(aVal
.NanoSeconds
% 10 == 0)
435 TIME_STRUCT
x(OTools::TimeToOdbcTime(aVal
));
436 setScalarParameter
<TIME_STRUCT
&>(parameterIndex
, DataType::TIME
, nColSize
, x
);
438 // -------------------------------------------------------------------------
440 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& aVal
) throw(SQLException
, RuntimeException
)
443 if(aVal
.NanoSeconds
== 0)
445 if (aVal
.Seconds
== 0)
450 else if(aVal
.NanoSeconds
% 100000000 == 0)
452 else if(aVal
.NanoSeconds
% 10000000 == 0)
454 else if(aVal
.NanoSeconds
% 1000000 == 0)
456 else if(aVal
.NanoSeconds
% 100000 == 0)
458 else if(aVal
.NanoSeconds
% 10000 == 0)
460 else if(aVal
.NanoSeconds
% 1000 == 0)
462 else if(aVal
.NanoSeconds
% 100 == 0)
464 else if(aVal
.NanoSeconds
% 10 == 0)
469 TIMESTAMP_STRUCT
x(OTools::DateTimeToTimestamp(aVal
));
470 setScalarParameter
<TIMESTAMP_STRUCT
&>(parameterIndex
, DataType::TIMESTAMP
, nColSize
, x
);
472 // -------------------------------------------------------------------------
474 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
) throw(SQLException
, RuntimeException
)
476 setScalarParameter(parameterIndex
, DataType::DOUBLE
, 15, x
);
479 // -------------------------------------------------------------------------
481 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
) throw(SQLException
, RuntimeException
)
483 setScalarParameter(parameterIndex
, DataType::FLOAT
, 15, x
);
485 // -------------------------------------------------------------------------
487 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
)
489 setScalarParameter(parameterIndex
, DataType::INTEGER
, 10, x
);
491 // -------------------------------------------------------------------------
493 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
) throw(SQLException
, RuntimeException
)
497 setScalarParameter(parameterIndex
, DataType::BIGINT
, 19, x
);
501 setString(parameterIndex
, ORowSetValue(x
));
504 // -------------------------------------------------------------------------
506 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, const sal_Int32 _nType
) throw(SQLException
, RuntimeException
)
508 ::osl::MutexGuard
aGuard( m_aMutex
);
509 setParameterPre(parameterIndex
);
511 OSL_VERIFY(allocBindBuf(parameterIndex
, 0) == NULL
);
512 SQLLEN
* const lenBuf
= getLengthBuf (parameterIndex
);
513 *lenBuf
= SQL_NULL_DATA
;
517 SQLSMALLINT fSqlType
;
519 OTools::getBindTypes( useWChar
,
520 m_pConnection
->useOldDateFormat(),
521 OTools::jdbcTypeToOdbc(_nType
),
525 SQLRETURN nReturn
= N3SQLBindParameter( m_aStatementHandle
,
526 static_cast<SQLUSMALLINT
>(parameterIndex
),
536 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
538 // -------------------------------------------------------------------------
540 void SAL_CALL
OPreparedStatement::setClob( sal_Int32 parameterIndex
, const Reference
< XClob
>& x
) throw(SQLException
, RuntimeException
)
543 setStream(parameterIndex
, x
->getCharacterStream(), x
->length(), DataType::LONGVARCHAR
);
545 // -------------------------------------------------------------------------
547 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32 parameterIndex
, const Reference
< XBlob
>& x
) throw(SQLException
, RuntimeException
)
550 setStream(parameterIndex
, x
->getBinaryStream(), x
->length(), DataType::LONGVARBINARY
);
552 // -------------------------------------------------------------------------
554 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
556 ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
558 // -------------------------------------------------------------------------
560 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
562 ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
564 // -------------------------------------------------------------------------
565 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
) throw(SQLException
, RuntimeException
)
567 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
568 ::osl::MutexGuard
aGuard( m_aMutex
);
571 // For each known SQL Type, call the appropriate
577 case DataType::VARCHAR
:
578 case DataType::LONGVARCHAR
:
583 setParameter(parameterIndex
, sqlType
, scale
, sStr
);
586 setNull(parameterIndex
,sqlType
);
588 case DataType::DECIMAL
:
589 case DataType::NUMERIC
:
594 // TODO: make sure that this calls the string overload
595 setParameter(parameterIndex
, sqlType
, scale
, aValue
);
598 setNull(parameterIndex
,sqlType
);
601 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
604 // -------------------------------------------------------------------------
606 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
608 setNull(parameterIndex
,sqlType
);
610 // -------------------------------------------------------------------------
612 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
614 if (!::dbtools::implSetObject(this, parameterIndex
, x
))
615 { // there is no other setXXX call which can handle the value in x
616 throw SQLException();
619 // -------------------------------------------------------------------------
621 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
)
623 setScalarParameter(parameterIndex
, DataType::SMALLINT
, 5, x
);
625 // -------------------------------------------------------------------------
627 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
)
629 setParameter(parameterIndex
, DataType::BINARY
, x
);
631 // -------------------------------------------------------------------------
634 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
636 // LEM: It is quite unclear to me what the interface here is.
637 // The XInputStream provides *bytes*, not characters.
638 setStream(parameterIndex
, x
, length
, DataType::LONGVARCHAR
);
640 // -------------------------------------------------------------------------
642 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
644 setStream(parameterIndex
, x
, length
, DataType::LONGVARBINARY
);
646 // -------------------------------------------------------------------------
648 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
650 ::osl::MutexGuard
aGuard( m_aMutex
);
652 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
653 SQLRETURN nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_RESET_PARAMS
);
654 nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_UNBIND
);
657 // -------------------------------------------------------------------------
658 void SAL_CALL
OPreparedStatement::clearBatch( ) throw(SQLException
, RuntimeException
)
660 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::clearBatch", *this );
661 // clearParameters( );
662 // m_aBatchList.erase();
664 // -------------------------------------------------------------------------
666 void SAL_CALL
OPreparedStatement::addBatch( ) throw(SQLException
, RuntimeException
)
668 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::addBatch", *this );
670 // -------------------------------------------------------------------------
672 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( ) throw(SQLException
, RuntimeException
)
674 ::dbtools::throwFunctionNotSupportedException( "XPreparedBatchExecution::executeBatch", *this );
675 // not reached, but keep -Werror happy
676 return Sequence
< sal_Int32
> ();
678 // -------------------------------------------------------------------------
680 //====================================================================
682 //====================================================================
684 //--------------------------------------------------------------------
686 // Initialize the bound parameter objects
687 //--------------------------------------------------------------------
689 void OPreparedStatement::initBoundParam () throw(SQLException
)
691 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
692 // Get the number of parameters
694 N3SQLNumParams (m_aStatementHandle
,&numParams
);
696 // There are parameter markers, allocate the bound
701 // Allocate an array of bound parameter objects
703 boundParams
= new OBoundParam
[numParams
];
707 // -------------------------------------------------------------------------
709 //--------------------------------------------------------------------
711 // Allocate storage for the permanent data buffer for the bound
713 //--------------------------------------------------------------------
715 void* OPreparedStatement::allocBindBuf( sal_Int32 index
,sal_Int32 bufLen
)
719 // Sanity check the parameter number
721 if ((index
>= 1) && (index
<= numParams
))
723 b
= boundParams
[index
- 1].allocBindDataBuffer(bufLen
);
728 // -------------------------------------------------------------------------
730 //--------------------------------------------------------------------
732 // Gets the length buffer for the given parameter index
733 //--------------------------------------------------------------------
735 SQLLEN
* OPreparedStatement::getLengthBuf (sal_Int32 index
)
739 // Sanity check the parameter number
742 (index
<= numParams
))
744 b
= boundParams
[index
- 1].getBindLengthBuffer ();
749 // -------------------------------------------------------------------------
751 //--------------------------------------------------------------------
753 // Puts parameter data from a previously bound input stream. The
754 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
755 //--------------------------------------------------------------------
757 void OPreparedStatement::putParamData (sal_Int32 index
) throw(SQLException
)
759 // Sanity check the parameter index
766 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
767 Sequence
< sal_Int8
> buf( MAX_PUT_DATA_LENGTH
);
769 // Get the information about the input stream
771 Reference
< XInputStream
> inputStream
= boundParams
[index
- 1].getInputStream ();
772 if ( !inputStream
.is() )
774 ::connectivity::SharedResources aResources
;
775 const OUString
sError( aResources
.getResourceString(STR_NO_INPUTSTREAM
));
776 throw SQLException (sError
, *this,OUString(),0,Any());
779 sal_Int32 maxBytesLeft
= boundParams
[index
- 1].getInputStreamLen ();
781 // Loop while more data from the input stream
782 sal_Int32 haveRead
= 0;
788 sal_Int32 toReadThisRound
= ::std::min( MAX_PUT_DATA_LENGTH
, maxBytesLeft
);
790 // Read some data from the input stream
791 haveRead
= inputStream
->readBytes( buf
, toReadThisRound
);
792 OSL_ENSURE( haveRead
== buf
.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
795 // no more data in the stream - the given stream length was a maximum which could not be
796 // fulfilled by the stream
800 OSL_ENSURE( m_aStatementHandle
, "OPreparedStatement::putParamData: StatementHandle is null!" );
801 N3SQLPutData ( m_aStatementHandle
, buf
.getArray(), buf
.getLength() );
803 // decrement the number of bytes still needed
804 maxBytesLeft
-= haveRead
;
806 while ( maxBytesLeft
> 0 );
808 catch (const IOException
& ex
)
811 // If an I/O exception was generated, turn
812 // it into a SQLException
814 throw SQLException(ex
.Message
,*this,OUString(),0,Any());
817 // -------------------------------------------------------------------------
819 //--------------------------------------------------------------------
821 // Sets an input stream as a parameter, using the given SQL type
822 //--------------------------------------------------------------------
824 void OPreparedStatement::setStream(
825 sal_Int32 ParameterIndex
,
826 const Reference
< XInputStream
>& x
,
831 ::osl::MutexGuard
aGuard( m_aMutex
);
832 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
837 checkParameterIndex(ParameterIndex
);
838 // Get the buffer needed for the length
840 SQLLEN
* const lenBuf
= getLengthBuf(ParameterIndex
);
842 // Allocate a new buffer for the parameter data. This buffer
843 // will be returned by SQLParamData (it is set to the parameter
844 // number, a sal_Int32)
846 sal_Int32
* dataBuf
= static_cast<sal_Int32
*>( allocBindBuf(ParameterIndex
, sizeof(ParameterIndex
)) );
847 *dataBuf
= ParameterIndex
;
849 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
850 *lenBuf
= SQL_LEN_DATA_AT_EXEC (length
);
852 SQLSMALLINT fCType
, fSqlType
;
853 OTools::getBindTypes(useWChar
, m_pConnection
->useOldDateFormat(), OTools::jdbcTypeToOdbc(_nType
), fCType
, fSqlType
);
856 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
857 N3SQLBindParameter(m_aStatementHandle
,
858 static_cast<SQLUSMALLINT
>(ParameterIndex
),
865 sizeof(ParameterIndex
),
868 // Save the input stream
869 boundParams
[ParameterIndex
- 1].setInputStream (x
, length
);
871 // -------------------------------------------------------------------------
873 // -------------------------------------------------------------------------
875 void OPreparedStatement::FreeParams()
878 delete [] boundParams
;
881 // -------------------------------------------------------------------------
882 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
888 case PROPERTY_ID_RESULTSETCONCURRENCY
:
890 setResultSetConcurrency(comphelper::getINT32(rValue
));
892 case PROPERTY_ID_RESULTSETTYPE
:
894 setResultSetType(comphelper::getINT32(rValue
));
896 case PROPERTY_ID_FETCHDIRECTION
:
898 setFetchDirection(comphelper::getINT32(rValue
));
900 case PROPERTY_ID_USEBOOKMARKS
:
902 setUsingBookmarks(comphelper::getBOOL(rValue
));
905 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
908 catch(const SQLException
&)
910 // throw Exception(e.Message,*this);
913 // -----------------------------------------------------------------------------
914 void OPreparedStatement::prepareStatement()
918 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
919 OString
aSql(OUStringToOString(m_sSqlStatement
,getOwnConnection()->getTextEncoding()));
920 SQLRETURN nReturn
= N3SQLPrepare(m_aStatementHandle
,(SDB_ODBC_CHAR
*) aSql
.getStr(),aSql
.getLength());
921 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
922 m_bPrepared
= sal_True
;
926 // -----------------------------------------------------------------------------
927 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex
)
929 if( _parameterIndex
> numParams
||
930 _parameterIndex
< 1 ||
931 _parameterIndex
> std::numeric_limits
<SQLUSMALLINT
>::max() )
933 ::connectivity::SharedResources aResources
;
934 const OUString
sError( aResources
.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX
,
935 "$pos$", OUString::valueOf(_parameterIndex
),
936 "$count$", OUString::valueOf((sal_Int32
)numParams
)
938 SQLException
aNext(sError
,*this, OUString(),0,Any());
940 ::dbtools::throwInvalidIndexException(*this,makeAny(aNext
));
943 // -----------------------------------------------------------------------------
944 OResultSet
* OPreparedStatement::createResulSet()
946 OResultSet
* pReturn
= new OResultSet(m_aStatementHandle
,this);
947 pReturn
->setMetaData(getMetaData());
950 // -----------------------------------------------------------------------------
952 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */