Update ooo320-m1
[ooovba.git] / connectivity / source / drivers / odbcbase / OPreparedStatement.cxx
blob187808bdbd867293fa40916b18d20837546e38f8
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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"
34 #include <stdio.h>
35 #include <string.h>
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)
70 ,numParams(0)
71 ,boundParams(NULL)
72 ,m_bPrepared(sal_False)
74 m_sSqlStatement = sql;
75 try
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) );
83 if ( pNode.get() )
84 { // special handling for parameters
85 OSQLParseNode::substituteParameterNames(pNode.get());
86 pNode->parseNodeToStr( sNewSql, _pConnection );
87 m_sSqlStatement = sNewSql;
91 catch(Exception&)
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);
124 prepareStatement();
125 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
126 if(!m_xMetaData.is())
127 m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
128 return m_xMetaData;
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
139 clearMyResultSet ();
141 // Reset last warning message
143 try {
144 clearWarnings ();
145 OStatement_BASE2::close();
146 FreeParams();
148 catch (SQLException &) {
149 // If we get an error, ignore
152 // Remove this Statement object from the Connection object's
153 // list
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;
165 // Reset warnings
167 clearWarnings ();
169 // Reset the statement handle, warning and saved Resultset
171 reset();
173 // Call SQLExecute
174 prepareStatement();
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.
188 while (needData) {
190 // Get the parameter number that requires data
192 sal_Int32* paramIndex = 0;
193 nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
195 // If the parameter index is -1, there is no
196 // more data required
198 if ( !paramIndex || ( *paramIndex == -1 ) )
199 needData = sal_False;
200 else
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.
218 while (needData) {
220 // Get the parameter number that requires data
222 sal_Int32* paramIndex = 0;
223 N3SQLParamData (m_aStatementHandle,(SQLPOINTER*)&paramIndex);
225 // If the parameter index is -1, there is no more
226 // data required
228 if (*paramIndex == -1) {
229 needData = sal_False;
231 else {
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;
255 prepareStatement();
256 // Execute the statement. If execute returns sal_False, a
257 // row count exists.
259 if (!execute())
260 numRows = getUpdateCount ();
261 else
263 // No update count was produced (a ResultSet was). Raise
264 // an exception
265 m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
267 return numRows;
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;
294 prepareStatement();
296 if (execute())
297 rs = getResultSet(sal_False);
298 else
300 // No ResultSet was produced. Raise an exception
301 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
303 return rs;
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);
313 sal_Int32 value = 0;
315 // If the parameter is sal_True, set the value to 1
316 if (x) {
317 value = 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, \
327 parameterIndex, \
328 bindBuf, \
329 getLengthBuf(parameterIndex), \
330 (SWORD)_jt, \
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);
339 prepareStatement();
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));
348 switch(fSqlType)
350 case SQL_CHAR:
351 case SQL_VARCHAR:
352 case SQL_DECIMAL:
353 case SQL_NUMERIC:
354 ++nRealSize;
355 break;
356 default:
357 break;
360 sal_Int8* bindBuf = allocBindBuf(parameterIndex, nRealSize);
362 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
363 OTools::bindParameter( m_pConnection,
364 m_aStatementHandle,
365 parameterIndex,
366 bindBuf,
367 getLengthBuf(parameterIndex),
368 fSqlType,
369 sal_False,
370 m_pConnection->useOldDateFormat(),
371 _pData,
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);
429 catch(SQLException&)
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);
442 prepareStatement();
443 // Get the buffer needed for the length
444 checkParameterIndex(parameterIndex);
446 sal_Int8* lenBuf = getLengthBuf (parameterIndex);
447 *(SQLLEN*)lenBuf = SQL_NULL_DATA;
450 SQLLEN prec = 0;
451 SQLULEN nColumnSize = 0;
452 if (sqlType == SQL_CHAR || sqlType == SQL_VARCHAR || sqlType == SQL_LONGVARCHAR)
454 prec = 1;
455 nColumnSize = 1;
458 SQLSMALLINT fCType = 0;
459 SQLSMALLINT fSqlType = 0;
461 SQLSMALLINT nDecimalDigits = 0;
462 OTools::getBindTypes( sal_False,
463 m_pConnection->useOldDateFormat(),
464 (SQLSMALLINT)sqlType,
465 fCType,
466 fSqlType);
468 SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
469 (SQLUSMALLINT)parameterIndex,
470 (SQLSMALLINT)SQL_PARAM_INPUT,
471 fCType,
472 fSqlType,
473 nColumnSize,
474 nDecimalDigits,
475 NULL,
476 prec,
477 (SQLLEN*)lenBuf
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 );
512 prepareStatement();
513 // For each known SQL Type, call the appropriate
514 // set routine
516 switch (sqlType)
518 case DataType::VARCHAR:
519 case DataType::LONGVARCHAR:
520 if(x.hasValue())
522 ::rtl::OUString sStr;
523 x >>= sStr;
524 ::rtl::OString aString(::rtl::OUStringToOString(sStr,getOwnConnection()->getTextEncoding()));
525 setParameter(parameterIndex,sqlType,aString.getLength(),&aString);
527 else
528 setNull(parameterIndex,sqlType);
529 break;
530 case DataType::DECIMAL:
531 case DataType::NUMERIC:
533 ORowSetValue aValue;
534 aValue.fill(x);
535 setString(parameterIndex,aValue);
537 break;
538 default:
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)
589 prepareStatement();
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 //====================================================================
614 // methods
615 //====================================================================
617 //--------------------------------------------------------------------
618 // initBoundParam
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
626 numParams = 0;
627 N3SQLNumParams (m_aStatementHandle,&numParams);
629 // There are parameter markers, allocate the bound
630 // parameter objects
632 if (numParams > 0)
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 //--------------------------------------------------------------------
650 // allocBindBuf
651 // Allocate storage for the permanent data buffer for the bound
652 // parameter.
653 //--------------------------------------------------------------------
655 sal_Int8* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
657 sal_Int8* b = NULL;
659 // Sanity check the parameter number
661 if ((index >= 1) &&
662 (index <= numParams) && bufLen > 0 )
664 b = boundParams[index - 1].allocBindDataBuffer(bufLen);
667 return b;
669 // -------------------------------------------------------------------------
671 //--------------------------------------------------------------------
672 // getDataBuf
673 // Gets the data buffer for the given parameter index
674 //--------------------------------------------------------------------
676 sal_Int8* OPreparedStatement::getDataBuf (sal_Int32 index)
678 sal_Int8* b = NULL;
680 // Sanity check the parameter number
682 if ((index >= 1) &&
683 (index <= numParams))
685 b = boundParams[index - 1].getBindDataBuffer ();
688 return b;
690 // -------------------------------------------------------------------------
692 //--------------------------------------------------------------------
693 // getLengthBuf
694 // Gets the length buffer for the given parameter index
695 //--------------------------------------------------------------------
697 sal_Int8* OPreparedStatement::getLengthBuf (sal_Int32 index)
699 sal_Int8* b = NULL;
701 // Sanity check the parameter number
703 if ((index >= 1) &&
704 (index <= numParams))
706 b = boundParams[index - 1].getBindLengthBuffer ();
709 return b;
711 // -------------------------------------------------------------------------
713 //--------------------------------------------------------------------
714 // getParamLength
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
728 if ((index >= 1) &&
729 (index <= numParams)) {
731 // Now get the length of the parameter from the
732 // bound param array. -1 is returned if it is NULL.
733 long n = 0;
734 memcpy (&n, boundParams[index -1].getBindLengthBuffer (), sizeof (n));
735 paramLen = n;
737 return paramLen;
739 // -------------------------------------------------------------------------
741 //--------------------------------------------------------------------
742 // putParamData
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
750 if ((index < 1) ||
751 (index > numParams))
753 return;
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!" );
784 if ( !haveRead )
785 // no more data in the stream - the given stream length was a maximum which could not be
786 // fulfilled by the stream
787 break;
789 // Put the data
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 //--------------------------------------------------------------------
809 // getPrecision
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);
819 sal_Int32 prec = -1;
820 const TTypeInfoVector& rTypeInfo = m_pConnection->getTypeInfo();
821 if ( !rTypeInfo.empty() )
823 m_pConnection->buildTypeInfo();
826 if ( !rTypeInfo.empty() )
828 OTypeInfo aInfo;
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;
834 return prec;
837 //--------------------------------------------------------------------
838 // setStream
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,
845 sal_Int32 length,
846 sal_Int32 SQLtype)
847 throw(SQLException)
849 ::osl::MutexGuard aGuard( m_aMutex );
850 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
853 prepareStatement();
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,
880 Ctype,
881 (SQLSMALLINT)SQLtype,
882 (SQLULEN)length,
884 dataBuf,
885 sizeof(ParameterIndex),
886 (SQLLEN*)lenBuf);
888 // Save the input stream
889 boundParams[ParameterIndex - 1].setInputStream (x, length);
891 // -------------------------------------------------------------------------
893 // -------------------------------------------------------------------------
895 void OPreparedStatement::FreeParams()
897 numParams = 0;
898 delete [] boundParams;
899 boundParams = NULL;
901 // -------------------------------------------------------------------------
902 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
906 switch(nHandle)
908 case PROPERTY_ID_RESULTSETCONCURRENCY:
909 if(!isPrepared())
910 setResultSetConcurrency(comphelper::getINT32(rValue));
911 break;
912 case PROPERTY_ID_RESULTSETTYPE:
913 if(!isPrepared())
914 setResultSetType(comphelper::getINT32(rValue));
915 break;
916 case PROPERTY_ID_FETCHDIRECTION:
917 if(!isPrepared())
918 setFetchDirection(comphelper::getINT32(rValue));
919 break;
920 case PROPERTY_ID_USEBOOKMARKS:
921 if(!isPrepared())
922 setUsingBookmarks(comphelper::getBOOL(rValue));
923 break;
924 default:
925 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
928 catch(const SQLException&)
930 // throw Exception(e.Message,*this);
933 // -----------------------------------------------------------------------------
934 void OPreparedStatement::prepareStatement()
936 if(!isPrepared())
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;
943 initBoundParam();
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());
966 return pReturn;
968 // -----------------------------------------------------------------------------