bump product version to 4.1.6.2
[LibreOffice.git] / connectivity / source / drivers / odbcbase / OPreparedStatement.cxx
blob5d234c445ea4e009d90d9863ebc2ec15a3e848df
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 #include <stdio.h>
22 #include <string.h>
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");
58 namespace
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)
68 ,numParams(0)
69 ,boundParams(NULL)
70 ,m_bPrepared(sal_False)
72 m_sSqlStatement = sql;
73 try
75 if(_pConnection->isParameterSubstitutionEnabled())
77 OSQLParser aParser( comphelper::getComponentContext(_pConnection->getDriver()->getORB()) );
78 OUString sErrorMessage;
79 OUString sNewSql;
80 ::std::auto_ptr<OSQLParseNode> pNode( aParser.parseTree(sErrorMessage,sql) );
81 if ( pNode.get() )
82 { // special handling for parameters
83 OSQLParseNode::substituteParameterNames(pNode.get());
84 pNode->parseNodeToStr( sNewSql, _pConnection );
85 m_sSqlStatement = sNewSql;
89 catch(Exception&)
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);
122 prepareStatement();
123 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
124 if(!m_xMetaData.is())
125 m_xMetaData = new OResultSetMetaData(getOwnConnection(),m_aStatementHandle);
126 return m_xMetaData;
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
137 clearMyResultSet ();
139 // Reset last warning message
141 try {
142 clearWarnings ();
143 OStatement_BASE2::close();
144 FreeParams();
146 catch (SQLException &) {
147 // If we get an error, ignore
150 // Remove this Statement object from the Connection object's
151 // list
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;
163 // Reset warnings
165 clearWarnings ();
167 // Reset the statement handle, warning and saved Resultset
169 reset();
171 // Call SQLExecute
172 prepareStatement();
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.
186 while (needData) {
188 // Get the parameter number that requires data
190 sal_Int32* paramIndex = 0;
191 nReturn = N3SQLParamData(m_aStatementHandle,(SQLPOINTER*)&paramIndex);
193 // If the parameter index is -1, there is no
194 // more data required
196 if ( !paramIndex || ( *paramIndex == -1 ) )
197 needData = sal_False;
198 else
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;
228 prepareStatement();
229 // Execute the statement. If execute returns sal_False, a
230 // row count exists.
232 if (!execute())
233 numRows = getUpdateCount ();
234 else
236 // No update count was produced (a ResultSet was). Raise
237 // an exception
238 m_pConnection->throwGenericSQLException(STR_NO_ROWCOUNT,*this);
240 return numRows;
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;
266 prepareStatement();
268 if (execute())
269 rs = getResultSet(sal_False);
270 else
272 // No ResultSet was produced. Raise an exception
273 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
275 return rs;
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);
289 prepareStatement();
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)) );
303 *bindBuf = 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);
316 sal_Int32 nCharLen;
317 sal_Int32 nByteLen;
318 void *pData;
319 if (useWChar)
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);
343 else
345 OString sOData( OUStringToOString(_sData, getOwnConnection()->getTextEncoding()) );
346 nCharLen = sOData.getLength();
347 nByteLen = nCharLen;
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();
376 *pDataLen=_nDataLen;
378 SQLRETURN nRetcode;
379 nRetcode = (*(T3SQLBindParameter)m_pConnection->getOdbcFunction(ODBC3SQLBindParameter))(
380 m_aStatementHandle,
381 // checkParameterIndex guarantees this is safe
382 static_cast<SQLUSMALLINT>(parameterIndex),
383 SQL_PARAM_INPUT,
384 fCType,
385 fSqlType,
386 _nColumnSize,
387 _nScale,
388 // we trust the ODBC driver not to touch it because SQL_PARAM_INPUT
389 const_cast<void*>(_pData),
390 _nDataAllocLen,
391 pDataLen);
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)
414 SQLULEN nColSize;
415 if(aVal.NanoSeconds == 0)
416 nColSize = 8;
417 else if(aVal.NanoSeconds % 100000000 == 0)
418 nColSize = 10;
419 else if(aVal.NanoSeconds % 10000000 == 0)
420 nColSize = 11;
421 else if(aVal.NanoSeconds % 1000000 == 0)
422 nColSize = 12;
423 else if(aVal.NanoSeconds % 100000 == 0)
424 nColSize = 13;
425 else if(aVal.NanoSeconds % 10000 == 0)
426 nColSize = 14;
427 else if(aVal.NanoSeconds % 1000 == 0)
428 nColSize = 15;
429 else if(aVal.NanoSeconds % 100 == 0)
430 nColSize = 16;
431 else if(aVal.NanoSeconds % 10 == 0)
432 nColSize = 17;
433 else
434 nColSize = 18;
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)
442 SQLULEN nColSize;
443 if(aVal.NanoSeconds == 0)
445 if (aVal.Seconds == 0)
446 nColSize=16;
447 else
448 nColSize=19;
450 else if(aVal.NanoSeconds % 100000000 == 0)
451 nColSize = 21;
452 else if(aVal.NanoSeconds % 10000000 == 0)
453 nColSize = 22;
454 else if(aVal.NanoSeconds % 1000000 == 0)
455 nColSize = 23;
456 else if(aVal.NanoSeconds % 100000 == 0)
457 nColSize = 24;
458 else if(aVal.NanoSeconds % 10000 == 0)
459 nColSize = 25;
460 else if(aVal.NanoSeconds % 1000 == 0)
461 nColSize = 26;
462 else if(aVal.NanoSeconds % 100 == 0)
463 nColSize = 27;
464 else if(aVal.NanoSeconds % 10 == 0)
465 nColSize = 28;
466 else
467 nColSize = 29;
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);
499 catch(SQLException&)
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;
516 SQLSMALLINT fCType;
517 SQLSMALLINT fSqlType;
519 OTools::getBindTypes( useWChar,
520 m_pConnection->useOldDateFormat(),
521 OTools::jdbcTypeToOdbc(_nType),
522 fCType,
523 fSqlType);
525 SQLRETURN nReturn = N3SQLBindParameter( m_aStatementHandle,
526 static_cast<SQLUSMALLINT>(parameterIndex),
527 SQL_PARAM_INPUT,
528 fCType,
529 fSqlType,
532 NULL,
534 lenBuf
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)
542 if ( x.is() )
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)
549 if ( x.is() )
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 );
570 prepareStatement();
571 // For each known SQL Type, call the appropriate
572 // set routine
574 switch (sqlType)
576 case DataType::CHAR:
577 case DataType::VARCHAR:
578 case DataType::LONGVARCHAR:
579 if(x.hasValue())
581 OUString sStr;
582 x >>= sStr;
583 setParameter(parameterIndex, sqlType, scale, sStr);
585 else
586 setNull(parameterIndex,sqlType);
587 break;
588 case DataType::DECIMAL:
589 case DataType::NUMERIC:
590 if(x.hasValue())
592 ORowSetValue aValue;
593 aValue.fill(x);
594 // TODO: make sure that this calls the string overload
595 setParameter(parameterIndex, sqlType, scale, aValue);
597 else
598 setNull(parameterIndex,sqlType);
599 break;
600 default:
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 );
651 prepareStatement();
652 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
653 SQLRETURN nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_RESET_PARAMS);
654 nRet = N3SQLFreeStmt (m_aStatementHandle, SQL_UNBIND);
655 OSL_UNUSED(nRet);
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 //====================================================================
681 // methods
682 //====================================================================
684 //--------------------------------------------------------------------
685 // initBoundParam
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
693 numParams = 0;
694 N3SQLNumParams (m_aStatementHandle,&numParams);
696 // There are parameter markers, allocate the bound
697 // parameter objects
699 if (numParams > 0)
701 // Allocate an array of bound parameter objects
703 boundParams = new OBoundParam[numParams];
707 // -------------------------------------------------------------------------
709 //--------------------------------------------------------------------
710 // allocBindBuf
711 // Allocate storage for the permanent data buffer for the bound
712 // parameter.
713 //--------------------------------------------------------------------
715 void* OPreparedStatement::allocBindBuf( sal_Int32 index,sal_Int32 bufLen)
717 void* b = NULL;
719 // Sanity check the parameter number
721 if ((index >= 1) && (index <= numParams))
723 b = boundParams[index - 1].allocBindDataBuffer(bufLen);
726 return b;
728 // -------------------------------------------------------------------------
730 //--------------------------------------------------------------------
731 // getLengthBuf
732 // Gets the length buffer for the given parameter index
733 //--------------------------------------------------------------------
735 SQLLEN* OPreparedStatement::getLengthBuf (sal_Int32 index)
737 SQLLEN* b = NULL;
739 // Sanity check the parameter number
741 if ((index >= 1) &&
742 (index <= numParams))
744 b = boundParams[index - 1].getBindLengthBuffer ();
747 return b;
749 // -------------------------------------------------------------------------
751 //--------------------------------------------------------------------
752 // putParamData
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
760 if ((index < 1) ||
761 (index > numParams))
763 return;
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!" );
794 if ( !haveRead )
795 // no more data in the stream - the given stream length was a maximum which could not be
796 // fulfilled by the stream
797 break;
799 // Put the data
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 //--------------------------------------------------------------------
820 // setStream
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,
827 SQLLEN length,
828 sal_Int32 _nType)
829 throw(SQLException)
831 ::osl::MutexGuard aGuard( m_aMutex );
832 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
835 prepareStatement();
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),
859 SQL_PARAM_INPUT,
860 fCType,
861 fSqlType,
862 length,
863 invalid_scale,
864 dataBuf,
865 sizeof(ParameterIndex),
866 lenBuf);
868 // Save the input stream
869 boundParams[ParameterIndex - 1].setInputStream (x, length);
871 // -------------------------------------------------------------------------
873 // -------------------------------------------------------------------------
875 void OPreparedStatement::FreeParams()
877 numParams = 0;
878 delete [] boundParams;
879 boundParams = NULL;
881 // -------------------------------------------------------------------------
882 void OPreparedStatement::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
886 switch(nHandle)
888 case PROPERTY_ID_RESULTSETCONCURRENCY:
889 if(!isPrepared())
890 setResultSetConcurrency(comphelper::getINT32(rValue));
891 break;
892 case PROPERTY_ID_RESULTSETTYPE:
893 if(!isPrepared())
894 setResultSetType(comphelper::getINT32(rValue));
895 break;
896 case PROPERTY_ID_FETCHDIRECTION:
897 if(!isPrepared())
898 setFetchDirection(comphelper::getINT32(rValue));
899 break;
900 case PROPERTY_ID_USEBOOKMARKS:
901 if(!isPrepared())
902 setUsingBookmarks(comphelper::getBOOL(rValue));
903 break;
904 default:
905 OStatement_Base::setFastPropertyValue_NoBroadcast(nHandle,rValue);
908 catch(const SQLException&)
910 // throw Exception(e.Message,*this);
913 // -----------------------------------------------------------------------------
914 void OPreparedStatement::prepareStatement()
916 if(!isPrepared())
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;
923 initBoundParam();
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());
948 return pReturn;
950 // -----------------------------------------------------------------------------
952 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */