Bump for 3.6-28
[LibreOffice.git] / connectivity / source / drivers / odbcbase / OPreparedStatement.cxx
blobd1288f99736663a5839cce3b6d99f582eb9acd83
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <stdio.h>
31 #include <string.h>
32 #include <osl/diagnose.h>
33 #include "diagnose_ex.h"
34 #include "odbc/OPreparedStatement.hxx"
35 #include "odbc/OBoundParam.hxx"
36 #include <com/sun/star/sdbc/DataType.hpp>
37 #include "odbc/OTools.hxx"
38 #include "odbc/ODriver.hxx"
39 #include "odbc/OResultSet.hxx"
40 #include "odbc/OResultSetMetaData.hxx"
41 #include <cppuhelper/typeprovider.hxx>
42 #include <comphelper/sequence.hxx>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include "connectivity/dbtools.hxx"
45 #include <comphelper/types.hxx>
46 #include "connectivity/FValue.hxx"
47 #include "resource/common_res.hrc"
48 #include "connectivity/sqlparse.hxx"
50 using namespace ::comphelper;
51 using namespace connectivity;
52 using namespace connectivity::odbc;
53 using namespace com::sun::star::uno;
54 using namespace com::sun::star::lang;
55 using namespace com::sun::star::beans;
56 using namespace com::sun::star::sdbc;
57 using namespace com::sun::star::sdbcx;
58 using namespace com::sun::star::container;
59 using namespace com::sun::star::io;
60 using namespace com::sun::star::util;
62 IMPLEMENT_SERVICE_INFO(OPreparedStatement,"com.sun.star.sdbcx.OPreparedStatement","com.sun.star.sdbc.PreparedStatement");
65 OPreparedStatement::OPreparedStatement( OConnection* _pConnection,const ::rtl::OUString& sql)
66 :OStatement_BASE2(_pConnection)
67 ,numParams(0)
68 ,boundParams(NULL)
69 ,m_bPrepared(sal_False)
71 m_sSqlStatement = sql;
72 try
74 if(_pConnection->isParameterSubstitutionEnabled())
76 OSQLParser aParser(_pConnection->getDriver()->getORB());
77 ::rtl::OUString sErrorMessage;
78 ::rtl::OUString sNewSql;
79 ::std::auto_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
80 if ( pNode.get() )
81 { // special handling for parameters
82 OSQLParseNode::substituteParameterNames(pNode.get());
83 pNode->parseNodeToStr( sNewSql, _pConnection );
84 m_sSqlStatement = sNewSql;
88 catch(Exception&)
92 // -----------------------------------------------------------------------------
93 void SAL_CALL OPreparedStatement::acquire() throw()
95 OStatement_BASE2::acquire();
97 // -----------------------------------------------------------------------------
98 void SAL_CALL OPreparedStatement::release() throw()
100 OStatement_BASE2::release();
102 // -----------------------------------------------------------------------------
103 Any SAL_CALL OPreparedStatement::queryInterface( const Type & rType ) throw(RuntimeException)
105 Any aRet = OStatement_BASE2::queryInterface(rType);
106 return aRet.hasValue() ? aRet : OPreparedStatement_BASE::queryInterface(rType);
108 // -------------------------------------------------------------------------
109 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL OPreparedStatement::getTypes( ) throw(::com::sun::star::uno::RuntimeException)
111 return ::comphelper::concatSequences(OPreparedStatement_BASE::getTypes(),OStatement_BASE2::getTypes());
113 // -------------------------------------------------------------------------
115 Reference< XResultSetMetaData > SAL_CALL OPreparedStatement::getMetaData( ) throw(SQLException, RuntimeException)
117 ::osl::MutexGuard aGuard( m_aMutex );
118 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
121 prepareStatement();
122 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
123 if(!m_xMetaData.is())
124 m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
125 return m_xMetaData;
127 // -------------------------------------------------------------------------
129 void SAL_CALL OPreparedStatement::close( ) throw(SQLException, RuntimeException)
131 ::osl::MutexGuard aGuard( m_aMutex );
132 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
135 // Close/clear our result set
136 clearMyResultSet ();
138 // Reset last warning message
140 try {
141 clearWarnings ();
142 OStatement_BASE2::close();
143 FreeParams();
145 catch (SQLException &) {
146 // If we get an error, ignore
149 // Remove this Statement object from the Connection object's
150 // list
152 // -------------------------------------------------------------------------
154 sal_Bool SAL_CALL OPreparedStatement::execute( ) throw(SQLException, RuntimeException)
156 ::osl::MutexGuard aGuard( m_aMutex );
157 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
160 sal_Bool needData = sal_False;
162 // Reset warnings
164 clearWarnings ();
166 // Reset the statement handle, warning and saved Resultset
168 reset();
170 // Call SQLExecute
171 prepareStatement();
173 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
176 SQLRETURN nReturn = N3SQLExecute(m_aStatementHandle);
178 OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
179 needData = nReturn == SQL_NEED_DATA;
181 // Now loop while more data is needed (i.e. a data-at-
182 // execution parameter was given). For each parameter
183 // that needs data, put the data from the input stream.
185 while (needData) {
187 // Get the parameter number that requires data
189 sal_Int32* paramIndex = 0;
190 nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
192 // If the parameter index is -1, there is no
193 // more data required
195 if ( !paramIndex || ( *paramIndex == -1 ) )
196 needData = sal_False;
197 else
199 // Now we have the proper parameter
200 // index, get the data from the input
201 // stream and do a SQLPutData
202 putParamData (*paramIndex);
207 catch (const SQLWarning&)
211 // Now loop while more data is needed (i.e. a data-at-
212 // execution parameter was given). For each parameter
213 // that needs data, put the data from the input stream.
215 while (needData) {
217 // Get the parameter number that requires data
219 sal_Int32* paramIndex = 0;
220 N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)&paramIndex);
222 // If the parameter index is -1, there is no more
223 // data required
225 if (*paramIndex == -1) {
226 needData = sal_False;
228 else {
229 // Now we have the proper parameter index,
230 // get the data from the input stream
231 // and do a SQLPutData
232 putParamData(*paramIndex);
236 // Now determine if there is a result set associated with
237 // the SQL statement that was executed. Get the column
238 // count, and if it is not zero, there is a result set.
241 return getColumnCount() > 0;
243 // -------------------------------------------------------------------------
245 sal_Int32 SAL_CALL OPreparedStatement::executeUpdate( ) throw(SQLException, RuntimeException)
247 ::osl::MutexGuard aGuard( m_aMutex );
248 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
250 sal_Int32 numRows = -1;
252 prepareStatement();
253 // Execute the statement. If execute returns sal_False, a
254 // row count exists.
256 if (!execute())
257 numRows = getUpdateCount ();
258 else
260 // No update count was produced (a ResultSet was). Raise
261 // an exception
262 m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
264 return numRows;
266 // -------------------------------------------------------------------------
268 void SAL_CALL OPreparedStatement::setString( sal_Int32 parameterIndex, const ::rtl::OUString& x ) throw(SQLException, RuntimeException)
270 ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
271 setParameter(parameterIndex,DataType::CHAR,aString.getLength(),(void*)&x);
273 // -------------------------------------------------------------------------
275 Reference< XConnection > SAL_CALL OPreparedStatement::getConnection( ) throw(SQLException, RuntimeException)
277 ::osl::MutexGuard aGuard( m_aMutex );
278 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
280 return (Reference< XConnection >)m_pConnection;
282 // -------------------------------------------------------------------------
284 Reference< XResultSet > SAL_CALL OPreparedStatement::executeQuery( ) throw(SQLException, RuntimeException)
286 ::osl::MutexGuard aGuard( m_aMutex );
287 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
289 Reference< XResultSet > rs = NULL;
291 prepareStatement();
293 if (execute())
294 rs = getResultSet(sal_False);
295 else
297 // No ResultSet was produced. Raise an exception
298 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
300 return rs;
302 // -------------------------------------------------------------------------
304 void SAL_CALL OPreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) throw(SQLException, RuntimeException)
306 ::osl::MutexGuard aGuard( m_aMutex );
307 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
310 sal_Int32 value = 0;
312 // If the parameter is sal_True, set the value to 1
313 if (x) {
314 value = 1;
317 // Set the parameter as if it were an integer
318 setInt (parameterIndex, value);
320 // -------------------------------------------------------------------------
321 void OPreparedStatement::setParameter(sal_Int32 parameterIndex,sal_Int32 _nType,sal_Int32 _nSize,void* _pData)
323 ::osl::MutexGuard aGuard( m_aMutex );
324 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
326 prepareStatement();
327 // Allocate a buffer to be used in binding. This will be
328 // a 'permanent' buffer that the bridge will fill in with
329 // the bound data in native format.
332 checkParameterIndex(parameterIndex);
333 sal_Int32 nRealSize = _nSize;
334 SQLSMALLINT fSqlType = static_cast<SQLSMALLINT>(OTools::jdbcTypeToOdbc(_nType));
335 switch(fSqlType)
337 case SQL_CHAR:
338 case SQL_VARCHAR:
339 case SQL_DECIMAL:
340 case SQL_NUMERIC:
341 ++nRealSize;
342 break;
343 case SQL_BINARY:
344 case SQL_VARBINARY:
345 nRealSize=1; //dummy buffer, binary data isn't copied
346 break;
347 default:
348 break;
351 sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
353 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
354 OTools::bindParameter( m_pConnection,
355 m_aStatementHandle,
356 parameterIndex,
357 bindBuf,
358 getLengthBuf(parameterIndex),
359 fSqlType,
360 sal_False,
361 m_pConnection->useOldDateFormat(),
362 _pData,
363 (Reference <XInterface>)*this,
364 getOwnConnection()->getTextEncoding());
366 // -----------------------------------------------------------------------------
367 void SAL_CALL OPreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) throw(SQLException, RuntimeException)
369 setParameter(parameterIndex,DataType::TINYINT,sizeof(sal_Int8),&x);
371 // -------------------------------------------------------------------------
373 void SAL_CALL OPreparedStatement::setDate( sal_Int32 parameterIndex, const Date& aData ) throw(SQLException, RuntimeException)
375 DATE_STRUCT x = OTools::DateToOdbcDate(aData);
376 setParameter(parameterIndex,DataType::DATE,sizeof(DATE_STRUCT),&x);
378 // -------------------------------------------------------------------------
381 void SAL_CALL OPreparedStatement::setTime( sal_Int32 parameterIndex, const Time& aVal ) throw(SQLException, RuntimeException)
383 TIME_STRUCT x = OTools::TimeToOdbcTime(aVal);
384 setParameter(parameterIndex,DataType::TIME,sizeof(TIME_STRUCT),&x);
386 // -------------------------------------------------------------------------
388 void SAL_CALL OPreparedStatement::setTimestamp( sal_Int32 parameterIndex, const DateTime& aVal ) throw(SQLException, RuntimeException)
390 TIMESTAMP_STRUCT x = OTools::DateTimeToTimestamp(aVal);
391 setParameter(parameterIndex,DataType::TIMESTAMP,sizeof(TIMESTAMP_STRUCT),&x);
393 // -------------------------------------------------------------------------
395 void SAL_CALL OPreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) throw(SQLException, RuntimeException)
397 setParameter(parameterIndex,DataType::DOUBLE,sizeof(double),&x);
400 // -------------------------------------------------------------------------
402 void SAL_CALL OPreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) throw(SQLException, RuntimeException)
404 setParameter(parameterIndex,DataType::FLOAT,sizeof(float),&x);
406 // -------------------------------------------------------------------------
408 void SAL_CALL OPreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) throw(SQLException, RuntimeException)
410 setParameter(parameterIndex,DataType::INTEGER,sizeof(sal_Int32),&x);
412 // -------------------------------------------------------------------------
414 void SAL_CALL OPreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) throw(SQLException, RuntimeException)
418 setParameter(parameterIndex,DataType::BIGINT,sizeof(sal_Int64),&x);
420 catch(SQLException&)
422 setString(parameterIndex,ORowSetValue(x));
425 // -------------------------------------------------------------------------
427 void SAL_CALL OPreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) throw(SQLException, RuntimeException)
429 ::osl::MutexGuard aGuard( m_aMutex );
430 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
433 prepareStatement();
434 // Get the buffer needed for the length
435 checkParameterIndex(parameterIndex);
437 sal_Int8* lenBuf = getLengthBuf (parameterIndex);
438 *(SQLLEN*)lenBuf = SQL_NULL_DATA;
441 SQLLEN prec = 0;
442 SQLULEN nColumnSize = 0;
443 if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
445 prec = 1;
446 nColumnSize = 1;
449 SQLSMALLINT fCType = 0;
450 SQLSMALLINT fSqlType = 0;
452 SQLSMALLINT nDecimalDigits = 0;
453 OTools::getBindTypes( sal_False,
454 m_pConnection->useOldDateFormat(),
455 (SQLSMALLINT)sqlType,
456 fCType,
457 fSqlType);
459 SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
460 (SQLUSMALLINT)parameterIndex,
461 (SQLSMALLINT)SQL_PARAM_INPUT,
462 fCType,
463 fSqlType,
464 nColumnSize,
465 nDecimalDigits,
466 NULL,
467 prec,
468 (SQLLEN*)lenBuf
470 OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
472 // -------------------------------------------------------------------------
474 void SAL_CALL OPreparedStatement::setClob( sal_Int32 parameterIndex, const Reference< XClob >& x ) throw(SQLException, RuntimeException)
476 if ( x.is() )
477 setStream(parameterIndex, x->getCharacterStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
479 // -------------------------------------------------------------------------
481 void SAL_CALL OPreparedStatement::setBlob( sal_Int32 parameterIndex, const Reference< XBlob >& x ) throw(SQLException, RuntimeException)
483 if ( x.is() )
484 setStream(parameterIndex, x->getBinaryStream(), (SQLLEN)x->length(), DataType::LONGVARCHAR);
486 // -------------------------------------------------------------------------
488 void SAL_CALL OPreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) throw(SQLException, RuntimeException)
490 ::dbtools::throwFunctionNotSupportedException( "XParameters::setArray", *this );
492 // -------------------------------------------------------------------------
494 void SAL_CALL OPreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) throw(SQLException, RuntimeException)
496 ::dbtools::throwFunctionNotSupportedException( "XParameters::setRef", *this );
498 // -------------------------------------------------------------------------
499 void OPreparedStatement::setDecimal( sal_Int32 parameterIndex, const ::rtl::OUString& x )
501 ::rtl::OString aString(::rtl::OUStringToOString(x,getOwnConnection()->getTextEncoding()));
502 setParameter(parameterIndex,DataType::DECIMAL,aString.getLength(),(void*)&x);
504 // -------------------------------------------------------------------------
505 void SAL_CALL OPreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 sqlType, sal_Int32 scale ) throw(SQLException, RuntimeException)
507 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
508 ::osl::MutexGuard aGuard( m_aMutex );
510 prepareStatement();
511 // For each known SQL Type, call the appropriate
512 // set routine
514 switch (sqlType)
516 case DataType::VARCHAR:
517 case DataType::LONGVARCHAR:
518 if(x.hasValue())
520 ::rtl::OUString sStr;
521 x >>= sStr;
522 ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
523 setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
525 else
526 setNull(parameterIndex,sqlType);
527 break;
528 case DataType::DECIMAL:
530 ORowSetValue aValue;
531 aValue.fill(x);
532 setDecimal(parameterIndex,aValue);
534 break;
535 case DataType::NUMERIC:
537 ORowSetValue aValue;
538 aValue.fill(x);
539 setString(parameterIndex,aValue);
541 break;
542 default:
543 ::dbtools::setObjectWithInfo(this,parameterIndex,x,sqlType,scale);
546 // -------------------------------------------------------------------------
548 void SAL_CALL OPreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& /*typeName*/ ) throw(SQLException, RuntimeException)
550 ::osl::MutexGuard aGuard( m_aMutex );
551 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
553 setNull(parameterIndex,sqlType);
555 // -------------------------------------------------------------------------
557 void SAL_CALL OPreparedStatement::setObject( sal_Int32 parameterIndex, const Any& x ) throw(SQLException, RuntimeException)
559 if (!::dbtools::implSetObject(this, parameterIndex, x))
560 { // there is no other setXXX call which can handle the value in x
561 throw SQLException();
564 // -------------------------------------------------------------------------
566 void SAL_CALL OPreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) throw(SQLException, RuntimeException)
568 setParameter(parameterIndex,DataType::SMALLINT,sizeof(sal_Int16),&x);
570 // -------------------------------------------------------------------------
572 void SAL_CALL OPreparedStatement::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) throw(SQLException, RuntimeException)
574 setParameter(parameterIndex,DataType::BINARY,x.getLength(),(void*)&x);
575 boundParams[parameterIndex-1].setSequence(x); // this assures that the sequence stays alive
577 // -------------------------------------------------------------------------
580 void SAL_CALL OPreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
582 setStream(parameterIndex, x, length, DataType::LONGVARCHAR);
584 // -------------------------------------------------------------------------
586 void SAL_CALL OPreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const Reference< ::com::sun::star::io::XInputStream >& x, sal_Int32 length ) throw(SQLException, RuntimeException)
588 setStream(parameterIndex, x, length, DataType::LONGVARBINARY);
590 // -------------------------------------------------------------------------
592 void SAL_CALL OPreparedStatement::clearParameters( ) throw(SQLException, RuntimeException)
594 prepareStatement();
595 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
596 SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
597 nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
598 OSL_UNUSED(nRet);
600 // -------------------------------------------------------------------------
601 void SAL_CALL OPreparedStatement::clearBatch( ) throw(SQLException, RuntimeException)
603 // clearParameters( );
604 // m_aBatchList.erase();
606 // -------------------------------------------------------------------------
608 void SAL_CALL OPreparedStatement::addBatch( ) throw(SQLException, RuntimeException)
611 // -------------------------------------------------------------------------
613 Sequence< sal_Int32 > SAL_CALL OPreparedStatement::executeBatch( ) throw(SQLException, RuntimeException)
615 return Sequence< sal_Int32 > ();
617 // -------------------------------------------------------------------------
619 //====================================================================
620 // methods
621 //====================================================================
623 //--------------------------------------------------------------------
624 // initBoundParam
625 // Initialize the bound parameter objects
626 //--------------------------------------------------------------------
628 void OPreparedStatement::initBoundParam () throw(SQLException)
630 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
631 // Get the number of parameters
632 numParams = 0;
633 N3SQLNumParams (m_aStatementHandle,&numParams);
635 // There are parameter markers, allocate the bound
636 // parameter objects
638 if (numParams > 0)
640 // Allocate an array of bound parameter objects
642 boundParams = new OBoundParam[numParams];
644 // initialize each bound parameter
646 for (sal_Int32 i = 0; i < numParams; i++)
648 boundParams[i].initialize ();
652 // -------------------------------------------------------------------------
654 //--------------------------------------------------------------------
655 // allocBindBuf
656 // Allocate storage for the permanent data buffer for the bound
657 // parameter.
658 //--------------------------------------------------------------------
660 sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
662 sal_Int8* b = NULL;
664 // Sanity check the parameter number
666 if ((index >= 1) &&
667 (index <= numParams) && bufLen > 0 )
669 b = boundParams[index - 1].allocBindDataBuffer(bufLen);
672 return b;
674 // -------------------------------------------------------------------------
676 //--------------------------------------------------------------------
677 // getLengthBuf
678 // Gets the length buffer for the given parameter index
679 //--------------------------------------------------------------------
681 sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
683 sal_Int8* b = NULL;
685 // Sanity check the parameter number
687 if ((index >= 1) &&
688 (index <= numParams))
690 b = boundParams[index - 1].getBindLengthBuffer ();
693 return b;
695 // -------------------------------------------------------------------------
697 //--------------------------------------------------------------------
698 // putParamData
699 // Puts parameter data from a previously bound input stream. The
700 // input stream was bound using SQL_LEN_DATA_AT_EXEC.
701 //--------------------------------------------------------------------
703 void OPreparedStatement::putParamData (sal_Int32 index) throw(SQLException)
705 // Sanity check the parameter index
706 if ((index < 1) ||
707 (index > numParams))
709 return;
712 // We'll transfer up to MAX_PUT_DATA_LENGTH at a time
713 Sequence< sal_Int8 > buf( MAX_PUT_DATA_LENGTH );
715 // Get the information about the input stream
717 Reference< XInputStream> inputStream = boundParams[index - 1].getInputStream ();
718 if ( !inputStream.is() )
720 ::connectivity::SharedResources aResources;
721 const ::rtl::OUString sError( aResources.getResourceString(STR_NO_INPUTSTREAM));
722 throw SQLException (sError, *this,::rtl::OUString(),0,Any());
725 sal_Int32 maxBytesLeft = boundParams[index - 1].getInputStreamLen ();
727 // Loop while more data from the input stream
728 sal_Int32 haveRead = 0;
734 sal_Int32 toReadThisRound = ::std::min( MAX_PUT_DATA_LENGTH, maxBytesLeft );
736 // Read some data from the input stream
737 haveRead = inputStream->readBytes( buf, toReadThisRound );
738 OSL_ENSURE( haveRead == buf.getLength(), "OPreparedStatement::putParamData: inconsistency!" );
740 if ( !haveRead )
741 // no more data in the stream - the given stream length was a maximum which could not be
742 // fulfilled by the stream
743 break;
745 // Put the data
746 OSL_ENSURE( m_aStatementHandle, "OPreparedStatement::putParamData: StatementHandle is null!" );
747 N3SQLPutData ( m_aStatementHandle, buf.getArray(), buf.getLength() );
749 // decrement the number of bytes still needed
750 maxBytesLeft -= haveRead;
752 while ( maxBytesLeft > 0 );
754 catch (const IOException& ex)
757 // If an I/O exception was generated, turn
758 // it into a SQLException
760 throw SQLException(ex.Message,*this,::rtl::OUString(),0,Any());
763 // -------------------------------------------------------------------------
765 //--------------------------------------------------------------------
766 // setStream
767 // Sets an input stream as a parameter, using the given SQL type
768 //--------------------------------------------------------------------
770 void OPreparedStatement::setStream(
771 sal_Int32 ParameterIndex,
772 const Reference< XInputStream>& x,
773 SQLLEN length,
774 sal_Int32 SQLtype)
775 throw(SQLException)
777 ::osl::MutexGuard aGuard( m_aMutex );
778 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
781 prepareStatement();
783 checkParameterIndex(ParameterIndex);
784 // Get the buffer needed for the length
786 sal_Int8* lenBuf = getLengthBuf(ParameterIndex);
788 // Allocate a new buffer for the parameter data. This buffer
789 // will be returned by SQLParamData (it is set to the parameter
790 // number, a 4-sal_Int8 integer)
792 sal_Int8* dataBuf = allocBindBuf (ParameterIndex, 4);
794 // Bind the parameter with SQL_LEN_DATA_AT_EXEC
795 SQLSMALLINT Ctype = SQL_C_CHAR;
796 SQLLEN atExec = SQL_LEN_DATA_AT_EXEC (length);
797 memcpy (dataBuf, &ParameterIndex, sizeof(ParameterIndex));
798 memcpy (lenBuf, &atExec, sizeof (atExec));
800 if ((SQLtype == SQL_BINARY) || (SQLtype == SQL_VARBINARY) || (SQLtype == SQL_LONGVARBINARY))
801 Ctype = SQL_C_BINARY;
804 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
805 N3SQLBindParameter(m_aStatementHandle,
806 (SQLUSMALLINT)ParameterIndex,
807 (SQLUSMALLINT)SQL_PARAM_INPUT,
808 Ctype,
809 (SQLSMALLINT)SQLtype,
810 (SQLULEN)length,
812 dataBuf,
813 sizeof(ParameterIndex),
814 (SQLLEN*)lenBuf);
816 // Save the input stream
817 boundParams[ParameterIndex - 1].setInputStream (x, length);
819 // -------------------------------------------------------------------------
821 // -------------------------------------------------------------------------
823 void OPreparedStatement::FreeParams()
825 numParams = 0;
826 delete [] boundParams;
827 boundParams = NULL;
829 // -------------------------------------------------------------------------
830 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
834 switch(nHandle)
836 case PROPERTY_ID_RESULTSETCONCURRENCY:
837 if(!isPrepared())
838 setResultSetConcurrency(comphelper::getINT32(rValue));
839 break;
840 case PROPERTY_ID_RESULTSETTYPE:
841 if(!isPrepared())
842 setResultSetType(comphelper::getINT32(rValue));
843 break;
844 case PROPERTY_ID_FETCHDIRECTION:
845 if(!isPrepared())
846 setFetchDirection(comphelper::getINT32(rValue));
847 break;
848 case PROPERTY_ID_USEBOOKMARKS:
849 if(!isPrepared())
850 setUsingBookmarks(comphelper::getBOOL(rValue));
851 break;
852 default:
853 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
856 catch(const SQLException&)
858 // throw Exception(e.Message,*this);
861 // -----------------------------------------------------------------------------
862 void OPreparedStatement::prepareStatement()
864 if(!isPrepared())
866 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
867 ::rtl::OString aSql(::rtl::OUStringToOString(m_sSqlStatement,getOwnConnection()->getTextEncoding()));
868 SQLRETURN nReturn = N3SQLPrepare(m_aStatementHandle,(SDB_ODBC_CHAR *) aSql.getStr(),aSql.getLength());
869 OTools::ThrowException(m_pConnection,nReturn,m_aStatementHandle,SQL_HANDLE_STMT,*this);
870 m_bPrepared = sal_True;
871 initBoundParam();
874 // -----------------------------------------------------------------------------
875 void OPreparedStatement::checkParameterIndex(sal_Int32 _parameterIndex)
877 if( !_parameterIndex || _parameterIndex > numParams)
879 ::connectivity::SharedResources aResources;
880 const ::rtl::OUString sError( aResources.getResourceStringWithSubstitution(STR_WRONG_PARAM_INDEX,
881 "$pos$", ::rtl::OUString::valueOf(_parameterIndex),
882 "$count$", ::rtl::OUString::valueOf((sal_Int32)numParams)
884 SQLException aNext(sError,*this, ::rtl::OUString(),0,Any());
886 ::dbtools::throwInvalidIndexException(*this,makeAny(aNext));
889 // -----------------------------------------------------------------------------
890 OResultSet* OPreparedStatement::createResulSet()
892 OResultSet* pReturn = new OResultSet(m_aStatementHandle,this);
893 pReturn->setMetaData(getMetaData());
894 return pReturn;
896 // -----------------------------------------------------------------------------
898 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */