1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: OPreparedStatement.cxx,v $
10 * $Revision: 1.49.56.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
36 #include <osl/diagnose.h>
37 #include "odbc/OPreparedStatement.hxx"
38 #include "odbc/OBoundParam.hxx"
39 #include <com/sun/star/sdbc/DataType.hpp>
40 #include "odbc/OTools.hxx"
41 #include "odbc/ODriver.hxx"
42 #include "odbc/OResultSet.hxx"
43 #include "odbc/OResultSetMetaData.hxx"
44 #include <cppuhelper/typeprovider.hxx>
45 #include <comphelper/sequence.hxx>
46 #include <com/sun/star/lang/DisposedException.hpp>
47 #include "connectivity/dbtools.hxx"
48 #include <comphelper/types.hxx>
49 #include "connectivity/FValue.hxx"
50 #include "resource/common_res.hrc"
51 #include "connectivity/sqlparse.hxx"
53 using namespace ::comphelper
;
54 using namespace connectivity
;
55 using namespace connectivity::odbc
;
56 using namespace com::sun::star::uno
;
57 using namespace com::sun::star::lang
;
58 using namespace com::sun::star::beans
;
59 using namespace com::sun::star::sdbc
;
60 using namespace com::sun::star::sdbcx
;
61 using namespace com::sun::star::container
;
62 using namespace com::sun::star::io
;
63 using namespace com::sun::star::util
;
65 IMPLEMENT_SERVICE_INFO(OPreparedStatement
,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
68 OPreparedStatement::OPreparedStatement( OConnection
* _pConnection
,const ::rtl::OUString
& sql
)
69 :OStatement_BASE2(_pConnection
)
72 ,m_bPrepared(sal_False
)
74 m_sSqlStatement
= sql
;
77 if(_pConnection
->isParameterSubstitutionEnabled())
79 OSQLParser
aParser(_pConnection
->getDriver()->getORB());
80 ::rtl::OUString sErrorMessage
;
81 ::rtl::OUString sNewSql
;
82 ::std::auto_ptr
<OSQLParseNode
> pNode( aParser
.parseTree(sErrorMessage
,sql
) );
84 { // special handling for parameters
85 OSQLParseNode::substituteParameterNames(pNode
.get());
86 pNode
->parseNodeToStr( sNewSql
, _pConnection
);
87 m_sSqlStatement
= sNewSql
;
95 // -----------------------------------------------------------------------------
96 void SAL_CALL
OPreparedStatement::acquire() throw()
98 OStatement_BASE2::acquire();
100 // -----------------------------------------------------------------------------
101 void SAL_CALL
OPreparedStatement::release() throw()
103 OStatement_BASE2::release();
105 // -----------------------------------------------------------------------------
106 Any SAL_CALL
OPreparedStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
108 Any aRet
= OStatement_BASE2::queryInterface(rType
);
109 return aRet
.hasValue() ? aRet
: OPreparedStatement_BASE::queryInterface(rType
);
111 // -------------------------------------------------------------------------
112 ::com::sun::star::uno::Sequence
< ::com::sun::star::uno::Type
> SAL_CALL
OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException
)
114 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
116 // -------------------------------------------------------------------------
118 Reference
< XResultSetMetaData
> SAL_CALL
OPreparedStatement::getMetaData( ) throw(SQLException
, RuntimeException
)
120 ::osl::MutexGuard
aGuard( m_aMutex
);
121 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
125 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
126 if(!m_xMetaData
.is())
127 m_xMetaData
= new OResultSetMetaData(getOwnConnection(),m_aStatementHandle
);
130 // -------------------------------------------------------------------------
132 void SAL_CALL
OPreparedStatement::close( ) throw(SQLException
, RuntimeException
)
134 ::osl::MutexGuard
aGuard( m_aMutex
);
135 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
138 // Close/clear our result set
141 // Reset last warning message
145 OStatement_BASE2::close();
148 catch (SQLException
&) {
149 // If we get an error, ignore
152 // Remove this Statement object from the Connection object's
155 // -------------------------------------------------------------------------
157 sal_Bool SAL_CALL
OPreparedStatement::execute( ) throw(SQLException
, RuntimeException
)
159 ::osl::MutexGuard
aGuard( m_aMutex
);
160 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
163 sal_Bool needData
= sal_False
;
169 // Reset the statement handle, warning and saved Resultset
176 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
179 SQLRETURN nReturn
= N3SQLExecute(m_aStatementHandle
);
181 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
182 needData
= nReturn
== SQL_NEED_DATA
;
184 // Now loop while more data is needed (i.e. a data-at-
185 // execution parameter was given). For each parameter
186 // that needs data, put the data from the input stream.
190 // Get the parameter number that requires data
192 sal_Int32
* paramIndex
= 0;
193 nReturn
= N3SQLParamData(m_aStatementHandle
,(SQLPOINTER
*)¶mIndex
);
195 // If the parameter index is -1, there is no
196 // more data required
198 if ( !paramIndex
|| ( *paramIndex
== -1 ) )
199 needData
= sal_False
;
202 // Now we have the proper parameter
203 // index, get the data from the input
204 // stream and do a SQLPutData
205 putParamData (*paramIndex
);
210 catch (const SQLWarning
&)
214 // Now loop while more data is needed (i.e. a data-at-
215 // execution parameter was given). For each parameter
216 // that needs data, put the data from the input stream.
220 // Get the parameter number that requires data
222 sal_Int32
* paramIndex
= 0;
223 N3SQLParamData (m_aStatementHandle
,(SQLPOINTER
*)¶mIndex
);
225 // If the parameter index is -1, there is no more
228 if (*paramIndex
== -1) {
229 needData
= sal_False
;
232 // Now we have the proper parameter index,
233 // get the data from the input stream
234 // and do a SQLPutData
235 putParamData(*paramIndex
);
239 // Now determine if there is a result set associated with
240 // the SQL statement that was executed. Get the column
241 // count, and if it is not zero, there is a result set.
244 return getColumnCount() > 0;
246 // -------------------------------------------------------------------------
248 sal_Int32 SAL_CALL
OPreparedStatement::executeUpdate( ) throw(SQLException
, RuntimeException
)
250 ::osl::MutexGuard
aGuard( m_aMutex
);
251 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
253 sal_Int32 numRows
= -1;
256 // Execute the statement. If execute returns sal_False, a
260 numRows
= getUpdateCount ();
263 // No update count was produced (a ResultSet was). Raise
265 m_pConnection
->throwGenericSQLException(STR_NO_ROWCOUNT
,*this);
269 // -------------------------------------------------------------------------
271 void SAL_CALL
OPreparedStatement::setString( sal_Int32 parameterIndex
, const ::rtl::OUString
& x
) throw(SQLException
, RuntimeException
)
273 ::rtl::OString
aString(::rtl::OUStringToOString(x
,getOwnConnection()->getTextEncoding()));
274 setParameter(parameterIndex
,DataType::CHAR
,aString
.getLength(),(void*)&x
);
276 // -------------------------------------------------------------------------
278 Reference
< XConnection
> SAL_CALL
OPreparedStatement::getConnection( ) throw(SQLException
, RuntimeException
)
280 ::osl::MutexGuard
aGuard( m_aMutex
);
281 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
283 return (Reference
< XConnection
>)m_pConnection
;
285 // -------------------------------------------------------------------------
287 Reference
< XResultSet
> SAL_CALL
OPreparedStatement::executeQuery( ) throw(SQLException
, RuntimeException
)
289 ::osl::MutexGuard
aGuard( m_aMutex
);
290 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
292 Reference
< XResultSet
> rs
= NULL
;
297 rs
= getResultSet(sal_False
);
300 // No ResultSet was produced. Raise an exception
301 m_pConnection
->throwGenericSQLException(STR_NO_RESULTSET
,*this);
305 // -------------------------------------------------------------------------
307 void SAL_CALL
OPreparedStatement::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
) throw(SQLException
, RuntimeException
)
309 ::osl::MutexGuard
aGuard( m_aMutex
);
310 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
315 // If the parameter is sal_True, set the value to 1
320 // Set the parameter as if it were an integer
321 setInt (parameterIndex
, value
);
323 // -------------------------------------------------------------------------
324 #define PREP_BIND_PARAM(_ty,_jt) \
325 OTools::bindParameter(m_pConnection, \
326 m_aStatementHandle, \
329 getLengthBuf(parameterIndex), \
331 sal_False,m_pConnection->useOldDateFormat(),_pData,(Reference <XInterface>)*this,getOwnConnection()->getTextEncoding())
334 void OPreparedStatement::setParameter(sal_Int32 parameterIndex
,sal_Int32 _nType
,sal_Int32 _nSize
,void* _pData
)
336 ::osl::MutexGuard
aGuard( m_aMutex
);
337 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
340 // Allocate a buffer to be used in binding. This will be
341 // a 'permanent' buffer that the bridge will fill in with
342 // the bound data in native format.
345 checkParameterIndex(parameterIndex
);
346 sal_Int32 nRealSize
= _nSize
;
347 SQLSMALLINT fSqlType
= static_cast<SQLSMALLINT
>(OTools::jdbcTypeToOdbc(_nType
));
360 sal_Int8
* bindBuf
= allocBindBuf(parameterIndex
, nRealSize
);
362 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
363 OTools::bindParameter( m_pConnection
,
367 getLengthBuf(parameterIndex
),
370 m_pConnection
->useOldDateFormat(),
372 (Reference
<XInterface
>)*this,
373 getOwnConnection()->getTextEncoding());
375 // -----------------------------------------------------------------------------
376 void SAL_CALL
OPreparedStatement::setByte( sal_Int32 parameterIndex
, sal_Int8 x
) throw(SQLException
, RuntimeException
)
378 setParameter(parameterIndex
,DataType::TINYINT
,sizeof(sal_Int8
),&x
);
380 // -------------------------------------------------------------------------
382 void SAL_CALL
OPreparedStatement::setDate( sal_Int32 parameterIndex
, const Date
& aData
) throw(SQLException
, RuntimeException
)
384 DATE_STRUCT x
= OTools::DateToOdbcDate(aData
);
385 setParameter(parameterIndex
,DataType::DATE
,sizeof(DATE_STRUCT
),&x
);
387 // -------------------------------------------------------------------------
390 void SAL_CALL
OPreparedStatement::setTime( sal_Int32 parameterIndex
, const Time
& aVal
) throw(SQLException
, RuntimeException
)
392 TIME_STRUCT x
= OTools::TimeToOdbcTime(aVal
);
393 setParameter(parameterIndex
,DataType::TIME
,sizeof(TIME_STRUCT
),&x
);
395 // -------------------------------------------------------------------------
397 void SAL_CALL
OPreparedStatement::setTimestamp( sal_Int32 parameterIndex
, const DateTime
& aVal
) throw(SQLException
, RuntimeException
)
399 TIMESTAMP_STRUCT x
= OTools::DateTimeToTimestamp(aVal
);
400 setParameter(parameterIndex
,DataType::TIMESTAMP
,sizeof(TIMESTAMP_STRUCT
),&x
);
402 // -------------------------------------------------------------------------
404 void SAL_CALL
OPreparedStatement::setDouble( sal_Int32 parameterIndex
, double x
) throw(SQLException
, RuntimeException
)
406 setParameter(parameterIndex
,DataType::DOUBLE
,sizeof(double),&x
);
409 // -------------------------------------------------------------------------
411 void SAL_CALL
OPreparedStatement::setFloat( sal_Int32 parameterIndex
, float x
) throw(SQLException
, RuntimeException
)
413 setParameter(parameterIndex
,DataType::FLOAT
,sizeof(float),&x
);
415 // -------------------------------------------------------------------------
417 void SAL_CALL
OPreparedStatement::setInt( sal_Int32 parameterIndex
, sal_Int32 x
) throw(SQLException
, RuntimeException
)
419 setParameter(parameterIndex
,DataType::INTEGER
,sizeof(sal_Int32
),&x
);
421 // -------------------------------------------------------------------------
423 void SAL_CALL
OPreparedStatement::setLong( sal_Int32 parameterIndex
, sal_Int64 x
) throw(SQLException
, RuntimeException
)
427 setParameter(parameterIndex
,DataType::BIGINT
,sizeof(sal_Int64
),&x
);
431 setString(parameterIndex
,ORowSetValue(x
));
434 // -------------------------------------------------------------------------
436 void SAL_CALL
OPreparedStatement::setNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
) throw(SQLException
, RuntimeException
)
438 ::osl::MutexGuard
aGuard( m_aMutex
);
439 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
443 // Get the buffer needed for the length
444 checkParameterIndex(parameterIndex
);
446 sal_Int8
* lenBuf
= getLengthBuf (parameterIndex
);
447 *(SQLLEN
*)lenBuf
= SQL_NULL_DATA
;
451 SQLULEN nColumnSize
= 0;
452 if (sqlType
== SQL_CHAR
|| sqlType
== SQL_VARCHAR
|| sqlType
== SQL_LONGVARCHAR
)
458 SQLSMALLINT fCType
= 0;
459 SQLSMALLINT fSqlType
= 0;
461 SQLSMALLINT nDecimalDigits
= 0;
462 OTools::getBindTypes( sal_False
,
463 m_pConnection
->useOldDateFormat(),
464 (SQLSMALLINT
)sqlType
,
468 SQLRETURN nReturn
= N3SQLBindParameter( m_aStatementHandle
,
469 (SQLUSMALLINT
)parameterIndex
,
470 (SQLSMALLINT
)SQL_PARAM_INPUT
,
479 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
481 // -------------------------------------------------------------------------
483 void SAL_CALL
OPreparedStatement::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
485 ::dbtools::throwFunctionNotSupportedException( "XParameters::setClob", *this );
487 // -------------------------------------------------------------------------
489 void SAL_CALL
OPreparedStatement::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ ) throw(SQLException
, RuntimeException
)
491 ::dbtools::throwFunctionNotSupportedException( "XParameters::setBlob", *this );
493 // -------------------------------------------------------------------------
495 void SAL_CALL
OPreparedStatement::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ ) throw(SQLException
, RuntimeException
)
497 ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
499 // -------------------------------------------------------------------------
501 void SAL_CALL
OPreparedStatement::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ ) throw(SQLException
, RuntimeException
)
503 ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
505 // -------------------------------------------------------------------------
507 void SAL_CALL
OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 sqlType
, sal_Int32 scale
) throw(SQLException
, RuntimeException
)
509 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
510 ::osl::MutexGuard
aGuard( m_aMutex
);
513 // For each known SQL Type, call the appropriate
518 case DataType::VARCHAR
:
519 case DataType::LONGVARCHAR
:
522 ::rtl::OUString sStr
;
524 ::rtl::OString
aString(::rtl::OUStringToOString(sStr
,getOwnConnection()->getTextEncoding()));
525 setParameter(parameterIndex
,sqlType
,aString
.getLength(),&aString
);
528 setNull(parameterIndex
,sqlType
);
530 case DataType::DECIMAL
:
531 case DataType::NUMERIC
:
535 setString(parameterIndex
,aValue
);
539 ::dbtools::setObjectWithInfo(this,parameterIndex
,x
,sqlType
,scale
);
542 // -------------------------------------------------------------------------
544 void SAL_CALL
OPreparedStatement::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const ::rtl::OUString
& /*typeName*/ ) throw(SQLException
, RuntimeException
)
546 ::osl::MutexGuard
aGuard( m_aMutex
);
547 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
549 setNull(parameterIndex
,sqlType
);
551 // -------------------------------------------------------------------------
553 void SAL_CALL
OPreparedStatement::setObject( sal_Int32 parameterIndex
, const Any
& x
) throw(SQLException
, RuntimeException
)
555 if (!::dbtools::implSetObject(this, parameterIndex
, x
))
556 { // there is no other setXXX call which can handle the value in x
557 throw SQLException();
560 // -------------------------------------------------------------------------
562 void SAL_CALL
OPreparedStatement::setShort( sal_Int32 parameterIndex
, sal_Int16 x
) throw(SQLException
, RuntimeException
)
564 setParameter(parameterIndex
,DataType::SMALLINT
,sizeof(sal_Int16
),&x
);
566 // -------------------------------------------------------------------------
568 void SAL_CALL
OPreparedStatement::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
) throw(SQLException
, RuntimeException
)
570 setParameter(parameterIndex
,DataType::BINARY
,x
.getLength(),(void*)&x
);
572 // -------------------------------------------------------------------------
575 void SAL_CALL
OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
577 setStream (parameterIndex
, x
, length
, DataType::LONGVARCHAR
);
579 // -------------------------------------------------------------------------
581 void SAL_CALL
OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< ::com::sun::star::io::XInputStream
>& x
, sal_Int32 length
) throw(SQLException
, RuntimeException
)
583 setStream (parameterIndex
, x
, length
, DataType::LONGVARBINARY
);
585 // -------------------------------------------------------------------------
587 void SAL_CALL
OPreparedStatement::clearParameters( ) throw(SQLException
, RuntimeException
)
590 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
591 SQLRETURN nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_RESET_PARAMS
);
592 nRet
= N3SQLFreeStmt (m_aStatementHandle
, SQL_UNBIND
);
594 // -------------------------------------------------------------------------
595 void SAL_CALL
OPreparedStatement::clearBatch( ) throw(SQLException
, RuntimeException
)
597 // clearParameters( );
598 // m_aBatchList.erase();
600 // -------------------------------------------------------------------------
602 void SAL_CALL
OPreparedStatement::addBatch( ) throw(SQLException
, RuntimeException
)
605 // -------------------------------------------------------------------------
607 Sequence
< sal_Int32
> SAL_CALL
OPreparedStatement::executeBatch( ) throw(SQLException
, RuntimeException
)
609 return Sequence
< sal_Int32
> ();
611 // -------------------------------------------------------------------------
613 //====================================================================
615 //====================================================================
617 //--------------------------------------------------------------------
619 // Initialize the bound parameter objects
620 //--------------------------------------------------------------------
622 void OPreparedStatement::initBoundParam () throw(SQLException
)
624 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
625 // Get the number of parameters
627 N3SQLNumParams (m_aStatementHandle
,&numParams
);
629 // There are parameter markers, allocate the bound
634 // Allocate an array of bound parameter objects
636 boundParams
= new OBoundParam
[numParams
];
638 // Allocate and initialize each bound parameter
640 for (sal_Int32 i
= 0; i
< numParams
; i
++)
642 boundParams
[i
] = OBoundParam();
643 boundParams
[i
].initialize ();
647 // -------------------------------------------------------------------------
649 //--------------------------------------------------------------------
651 // Allocate storage for the permanent data buffer for the bound
653 //--------------------------------------------------------------------
655 sal_Int8
* OPreparedStatement::allocBindBuf( sal_Int32 index
,sal_Int32 bufLen
)
659 // Sanity check the parameter number
662 (index
<= numParams
) && bufLen
> 0 )
664 b
= boundParams
[index
- 1].allocBindDataBuffer(bufLen
);
669 // -------------------------------------------------------------------------
671 //--------------------------------------------------------------------
673 // Gets the data buffer for the given parameter index
674 //--------------------------------------------------------------------
676 sal_Int8
* OPreparedStatement::getDataBuf (sal_Int32 index
)
680 // Sanity check the parameter number
683 (index
<= numParams
))
685 b
= boundParams
[index
- 1].getBindDataBuffer ();
690 // -------------------------------------------------------------------------
692 //--------------------------------------------------------------------
694 // Gets the length buffer for the given parameter index
695 //--------------------------------------------------------------------
697 sal_Int8
* OPreparedStatement::getLengthBuf (sal_Int32 index
)
701 // Sanity check the parameter number
704 (index
<= numParams
))
706 b
= boundParams
[index
- 1].getBindLengthBuffer ();
711 // -------------------------------------------------------------------------
713 //--------------------------------------------------------------------
715 // Returns the length of the given parameter number. When each
716 // parameter was bound, a 4-sal_Int8 buffer was given to hold the
717 // length (stored in native format). Get the buffer, convert the
718 // buffer from native format, and return it. If the length is -1,
719 // the column is considered to be NULL.
720 //--------------------------------------------------------------------
722 sal_Int32
OPreparedStatement::getParamLength ( sal_Int32 index
)
724 sal_Int32 paramLen
= SQL_NULL_DATA
;
726 // Sanity check the parameter number
729 (index
<= numParams
)) {
731 // Now get the length of the parameter from the
732 // bound param array. -1 is returned if it is NULL.
734 memcpy (&n
, boundParams
[index
-1].getBindLengthBuffer (), sizeof (n
));
739 // -------------------------------------------------------------------------
741 //--------------------------------------------------------------------
743 // Puts parameter data from a previously bound input stream. The
744 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
745 //--------------------------------------------------------------------
747 void OPreparedStatement::putParamData (sal_Int32 index
) throw(SQLException
)
749 // Sanity check the parameter index
756 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
757 Sequence
< sal_Int8
> buf( MAX_PUT_DATA_LENGTH
);
759 // Get the information about the input stream
761 Reference
< XInputStream
> inputStream
= boundParams
[index
- 1].getInputStream ();
762 if ( !inputStream
.is() )
764 ::connectivity::SharedResources aResources
;
765 const ::rtl::OUString
sError( aResources
.getResourceString(STR_NO_INPUTSTREAM
));
766 throw SQLException (sError
, *this,::rtl::OUString(),0,Any());
769 sal_Int32 maxBytesLeft
= boundParams
[index
- 1].getInputStreamLen ();
771 // Loop while more data from the input stream
772 sal_Int32 haveRead
= 0;
778 sal_Int32 toReadThisRound
= ::std::min( MAX_PUT_DATA_LENGTH
, maxBytesLeft
);
780 // Read some data from the input stream
781 haveRead
= inputStream
->readBytes( buf
, toReadThisRound
);
782 OSL_ENSURE( haveRead
== buf
.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
785 // no more data in the stream - the given stream length was a maximum which could not be
786 // fulfilled by the stream
790 OSL_ENSURE( m_aStatementHandle
, "OPreparedStatement::putParamData: StatementHandle is null!" );
791 N3SQLPutData ( m_aStatementHandle
, buf
.getArray(), buf
.getLength() );
793 // decrement the number of bytes still needed
794 maxBytesLeft
-= haveRead
;
796 while ( maxBytesLeft
> 0 );
798 catch (const IOException
& ex
)
801 // If an I/O exception was generated, turn
802 // it into a SQLException
804 throw SQLException(ex
.Message
,*this,::rtl::OUString(),0,Any());
807 // -------------------------------------------------------------------------
808 //--------------------------------------------------------------------
810 // Given a SQL type, return the maximum precision for the column.
811 // Returns -1 if not known
812 //--------------------------------------------------------------------
814 sal_Int32
OPreparedStatement::getPrecision ( sal_Int32 sqlType
)
816 ::osl::MutexGuard
aGuard( m_aMutex
);
817 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
820 const TTypeInfoVector
& rTypeInfo
= m_pConnection
->getTypeInfo();
821 if ( !rTypeInfo
.empty() )
823 m_pConnection
->buildTypeInfo();
826 if ( !rTypeInfo
.empty() )
829 aInfo
.nType
= (sal_Int16
)sqlType
;
830 TTypeInfoVector::const_iterator aIter
= ::std::find(rTypeInfo
.begin(),rTypeInfo
.end(),aInfo
);
831 if(aIter
!= rTypeInfo
.end())
832 prec
= (*aIter
).nPrecision
;
837 //--------------------------------------------------------------------
839 // Sets an input stream as a parameter, using the given SQL type
840 //--------------------------------------------------------------------
842 void OPreparedStatement::setStream (
843 sal_Int32 ParameterIndex
,
844 const Reference
< XInputStream
>& x
,
849 ::osl::MutexGuard
aGuard( m_aMutex
);
850 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
855 checkParameterIndex(ParameterIndex
);
856 // Get the buffer needed for the length
858 sal_Int8
* lenBuf
= getLengthBuf(ParameterIndex
);
860 // Allocate a new buffer for the parameter data. This buffer
861 // will be returned by SQLParamData (it is set to the parameter
862 // number, a 4-sal_Int8 integer)
864 sal_Int8
* dataBuf
= allocBindBuf (ParameterIndex
, 4);
866 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
867 SQLSMALLINT Ctype
= SQL_C_CHAR
;
868 SQLLEN atExec
= SQL_LEN_DATA_AT_EXEC (length
);
869 memcpy (dataBuf
, &ParameterIndex
, sizeof(ParameterIndex
));
870 memcpy (lenBuf
, &atExec
, sizeof (atExec
));
872 if ((SQLtype
== SQL_BINARY
) || (SQLtype
== SQL_VARBINARY
) || (SQLtype
== SQL_LONGVARBINARY
))
873 Ctype
= SQL_C_BINARY
;
876 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
877 N3SQLBindParameter(m_aStatementHandle
,
878 (SQLUSMALLINT
)ParameterIndex
,
879 (SQLUSMALLINT
)SQL_PARAM_INPUT
,
881 (SQLSMALLINT
)SQLtype
,
885 sizeof(ParameterIndex
),
888 // Save the input stream
889 boundParams
[ParameterIndex
- 1].setInputStream (x
, length
);
891 // -------------------------------------------------------------------------
893 // -------------------------------------------------------------------------
895 void OPreparedStatement::FreeParams()
898 delete [] boundParams
;
901 // -------------------------------------------------------------------------
902 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
908 case PROPERTY_ID_RESULTSETCONCURRENCY
:
910 setResultSetConcurrency(comphelper::getINT32(rValue
));
912 case PROPERTY_ID_RESULTSETTYPE
:
914 setResultSetType(comphelper::getINT32(rValue
));
916 case PROPERTY_ID_FETCHDIRECTION
:
918 setFetchDirection(comphelper::getINT32(rValue
));
920 case PROPERTY_ID_USEBOOKMARKS
:
922 setUsingBookmarks(comphelper::getBOOL(rValue
));
925 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
928 catch(const SQLException
&)
930 // throw Exception(e.Message,*this);
933 // -----------------------------------------------------------------------------
934 void OPreparedStatement::prepareStatement()
938 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
939 ::rtl::OString
aSql(::rtl::OUStringToOString(m_sSqlStatement
,getOwnConnection()->getTextEncoding()));
940 SQLRETURN nReturn
= N3SQLPrepare(m_aStatementHandle
,(SDB_ODBC_CHAR
*) aSql
.getStr(),aSql
.getLength());
941 OTools::ThrowException(m_pConnection
,nReturn
,m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
942 m_bPrepared
= sal_True
;
946 // -----------------------------------------------------------------------------
947 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex
)
949 if( !_parameterIndex
|| _parameterIndex
> numParams
)
951 ::connectivity::SharedResources aResources
;
952 const ::rtl::OUString
sError( aResources
.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX
,
953 "$pos$", ::rtl::OUString::valueOf(_parameterIndex
),
954 "$count$", ::rtl::OUString::valueOf((sal_Int32
)numParams
)
956 SQLException
aNext(sError
,*this, ::rtl::OUString(),0,Any());
958 ::dbtools::throwInvalidIndexException(*this,makeAny(aNext
));
961 // -----------------------------------------------------------------------------
962 OResultSet
* OPreparedStatement::createResulSet()
964 OResultSet
* pReturn
= new OResultSet(m_aStatementHandle
,this);
965 pReturn
->setMetaData(getMetaData());
968 // -----------------------------------------------------------------------------