Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / odbc / OStatement.cxx
blob40466b8301c8690ab1b574abcc917a9cf9129dd6
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 <osl/diagnose.h>
23 #include "odbc/OStatement.hxx"
24 #include "odbc/OConnection.hxx"
25 #include "odbc/OResultSet.hxx"
26 #include <comphelper/property.hxx>
27 #include "odbc/OTools.hxx"
28 #include <comphelper/uno3.hxx>
29 #include <osl/thread.h>
30 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
31 #include <com/sun/star/sdbc/ResultSetType.hpp>
32 #include <com/sun/star/sdbc/FetchDirection.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <comphelper/sequence.hxx>
35 #include <cppuhelper/typeprovider.hxx>
36 #include <comphelper/extract.hxx>
37 #include <comphelper/types.hxx>
38 #include "diagnose_ex.h"
39 #include <algorithm>
40 #include "resource/common_res.hrc"
41 #include "connectivity/dbexception.hxx"
43 using namespace ::comphelper;
45 #define THROW_SQL(x) \
46 OTools::ThrowException(m_pConnection,x,m_aStatementHandle,SQL_HANDLE_STMT,*this)
50 using namespace connectivity::odbc;
52 using namespace com::sun::star::uno;
53 using namespace com::sun::star::lang;
54 using namespace com::sun::star::beans;
55 using namespace com::sun::star::sdbc;
56 using namespace com::sun::star::sdbcx;
57 using namespace com::sun::star::container;
58 using namespace com::sun::star::io;
59 using namespace com::sun::star::util;
61 OStatement_Base::OStatement_Base(OConnection* _pConnection )
62 :OStatement_BASE(m_aMutex)
63 ,OPropertySetHelper(OStatement_BASE::rBHelper)
64 ,m_pConnection(_pConnection)
65 ,m_aStatementHandle(SQL_NULL_HANDLE)
66 ,m_pRowStatusArray(0)
67 ,rBHelper(OStatement_BASE::rBHelper)
69 osl_atomic_increment( &m_refCount );
70 m_pConnection->acquire();
71 m_aStatementHandle = m_pConnection->createStatementHandle();
73 //setMaxFieldSize(0);
74 // Don't do this. By ODBC spec, "0" is the default for the SQL_ATTR_MAX_LENGTH attribute. We once introduced
75 // this line since an PostgreSQL ODBC driver had a default other than 0. However, current drivers (at least 8.3
76 // and later) have a proper default of 0, so there should be no need anymore.
77 // On the other hand, the NotesSQL driver (IBM's ODBC driver for the Lotus Notes series) wrongly interprets
78 // "0" as "0", whereas the ODBC spec says it should in fact mean "unlimited".
79 // So, removing this line seems to be the best option for now.
80 // If we ever again encounter a ODBC driver which needs this option, then we should introduce a data source
81 // setting for it, instead of unconditionally doing it.
83 osl_atomic_decrement( &m_refCount );
86 OStatement_Base::~OStatement_Base()
88 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
91 void OStatement_Base::disposeResultSet()
93 // free the cursor if alive
94 Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY);
95 if (xComp.is())
96 xComp->dispose();
97 m_xResultSet.clear();
100 void SAL_CALL OStatement_Base::disposing(void)
102 ::osl::MutexGuard aGuard(m_aMutex);
104 disposeResultSet();
105 ::comphelper::disposeComponent(m_xGeneratedStatement);
107 OSL_ENSURE(m_aStatementHandle,"OStatement_BASE2::disposing: StatementHandle is null!");
108 if (m_pConnection)
110 m_pConnection->freeStatementHandle(m_aStatementHandle);
111 m_pConnection->release();
112 m_pConnection = NULL;
114 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
116 OStatement_BASE::disposing();
119 void OStatement_BASE2::disposing()
121 ::osl::MutexGuard aGuard(m_aMutex);
123 dispose_ChildImpl();
124 OStatement_Base::disposing();
127 void SAL_CALL OStatement_BASE2::release() throw()
129 relase_ChildImpl();
132 Any SAL_CALL OStatement_Base::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
134 if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() && rType == ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ) )
135 return Any();
136 Any aRet = OStatement_BASE::queryInterface(rType);
137 return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
140 Sequence< Type > SAL_CALL OStatement_Base::getTypes( ) throw(RuntimeException, std::exception)
142 ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ),
143 ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
144 ::getCppuType( (const Reference< XPropertySet > *)0 ));
145 Sequence< Type > aOldTypes = OStatement_BASE::getTypes();
146 if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() )
148 ::std::remove(aOldTypes.getArray(),aOldTypes.getArray() + aOldTypes.getLength(),
149 ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ));
150 aOldTypes.realloc(aOldTypes.getLength() - 1);
153 return ::comphelper::concatSequences(aTypes.getTypes(),aOldTypes);
156 Reference< XResultSet > SAL_CALL OStatement_Base::getGeneratedValues( ) throw (SQLException, RuntimeException, std::exception)
158 OSL_ENSURE( m_pConnection && m_pConnection->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!");
159 Reference< XResultSet > xRes;
160 if ( m_pConnection )
162 OUString sStmt = m_pConnection->getTransformedGeneratedStatement(m_sSqlStatement);
163 if ( !sStmt.isEmpty() )
165 ::comphelper::disposeComponent(m_xGeneratedStatement);
166 m_xGeneratedStatement = m_pConnection->createStatement();
167 xRes = m_xGeneratedStatement->executeQuery(sStmt);
170 return xRes;
173 void SAL_CALL OStatement_Base::cancel( ) throw(RuntimeException, std::exception)
175 ::osl::MutexGuard aGuard( m_aMutex );
176 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
178 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
179 OTools::ThrowException(m_pConnection,N3SQLCancel(m_aStatementHandle),m_aStatementHandle,SQL_HANDLE_STMT,*this);
183 void SAL_CALL OStatement_Base::close( ) throw(SQLException, RuntimeException, std::exception)
186 ::osl::MutexGuard aGuard( m_aMutex );
187 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
190 dispose();
194 void SAL_CALL OStatement::clearBatch( ) throw(SQLException, RuntimeException, std::exception)
200 void OStatement_Base::reset() throw (SQLException)
202 ::osl::MutexGuard aGuard( m_aMutex );
203 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
206 clearWarnings ();
208 if (m_xResultSet.get().is())
210 clearMyResultSet();
212 if(m_aStatementHandle)
214 THROW_SQL(N3SQLFreeStmt(m_aStatementHandle, SQL_CLOSE));
218 // clearMyResultSet
219 // If a ResultSet was created for this Statement, close it
222 void OStatement_Base::clearMyResultSet () throw (SQLException)
224 ::osl::MutexGuard aGuard( m_aMutex );
225 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
229 Reference<XCloseable> xCloseable;
230 if ( ::comphelper::query_interface( m_xResultSet.get(), xCloseable ) )
231 xCloseable->close();
233 catch( const DisposedException& ) { }
235 m_xResultSet.clear();
238 SQLLEN OStatement_Base::getRowCount () throw( SQLException)
240 ::osl::MutexGuard aGuard( m_aMutex );
241 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
244 SQLLEN numRows = 0;
246 try {
247 THROW_SQL(N3SQLRowCount(m_aStatementHandle,&numRows));
249 catch (const SQLException&)
252 return numRows;
255 // lockIfNecessary
256 // If the given SQL statement contains a 'FOR UPDATE' clause, change
257 // the concurrency to lock so that the row can then be updated. Returns
258 // true if the concurrency has been changed
261 bool OStatement_Base::lockIfNecessary (const OUString& sql) throw( SQLException)
263 bool rc = false;
265 // First, convert the statement to upper case
267 OUString sqlStatement = sql.toAsciiUpperCase ();
269 // Now, look for the FOR UPDATE keywords. If there is any extra white
270 // space between the FOR and UPDATE, this will fail.
272 sal_Int32 index = sqlStatement.indexOf(" FOR UPDATE");
274 // We found it. Change our concurrency level to ensure that the
275 // row can be updated.
277 if (index > 0)
279 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
282 THROW_SQL((setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, SQL_CONCUR_LOCK)));
284 catch (const SQLWarning& warn)
286 // Catch any warnings and place on the warning stack
287 setWarning (warn);
289 rc = true;
292 return rc;
295 // setWarning
296 // Sets the warning
299 void OStatement_Base::setWarning (const SQLWarning &ex) throw( SQLException)
301 ::osl::MutexGuard aGuard( m_aMutex );
302 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
305 m_aLastWarning = ex;
309 // getColumnCount
310 // Return the number of columns in the ResultSet
313 sal_Int32 OStatement_Base::getColumnCount () throw( SQLException)
315 ::osl::MutexGuard aGuard( m_aMutex );
316 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
319 sal_Int16 numCols = 0;
320 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
322 try {
323 THROW_SQL(N3SQLNumResultCols(m_aStatementHandle,&numCols));
325 catch (const SQLException&)
328 return numCols;
332 sal_Bool SAL_CALL OStatement_Base::execute( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
334 ::osl::MutexGuard aGuard( m_aMutex );
335 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
336 m_sSqlStatement = sql;
339 OString aSql(OUStringToOString(sql,getOwnConnection()->getTextEncoding()));
341 bool hasResultSet = false;
342 SQLWarning aWarning;
344 // Reset the statement handle and warning
346 reset();
348 // Check for a 'FOR UPDATE' statement. If present, change
349 // the concurrency to lock
351 lockIfNecessary (sql);
353 // Call SQLExecDirect
354 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
356 try {
357 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, (SDB_ODBC_CHAR*)aSql.getStr(),aSql.getLength()));
359 catch (const SQLWarning& ex) {
361 // Save pointer to warning and save with ResultSet
362 // object once it is created.
364 aWarning = ex;
367 // Now determine if there is a result set associated with
368 // the SQL statement that was executed. Get the column
369 // count, and if it is not zero, there is a result set.
371 if (getColumnCount () > 0)
373 hasResultSet = true;
376 return hasResultSet;
379 // getResultSet
380 // getResultSet returns the current result as a ResultSet. It
381 // returns NULL if the current result is not a ResultSet.
383 Reference< XResultSet > OStatement_Base::getResultSet (bool checkCount) throw( SQLException)
385 ::osl::MutexGuard aGuard( m_aMutex );
386 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
389 if (m_xResultSet.get().is()) // if resultset already retrieved,
391 // throw exception to avoid sequence error
392 ::dbtools::throwFunctionSequenceException(*this,Any());
395 OResultSet* pRs = NULL;
396 sal_Int32 numCols = 1;
398 // If we already know we have result columns, checkCount
399 // is false. This is an optimization to prevent unneeded
400 // calls to getColumnCount
402 if (checkCount)
403 numCols = getColumnCount ();
405 // Only return a result set if there are result columns
407 if (numCols > 0)
409 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
410 pRs = createResulSet();
411 pRs->construct();
413 // Save a copy of our last result set
414 // Changed to save copy at getResultSet.
415 //m_xResultSet = rs;
417 else
418 clearMyResultSet ();
420 return pRs;
423 // getStmtOption
424 // Invoke SQLGetStmtOption with the given option.
427 template < typename T, SQLINTEGER BufferLength > T OStatement_Base::getStmtOption (SQLINTEGER fOption, T dflt) const
429 T result (dflt);
430 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
431 N3SQLGetStmtAttr(m_aStatementHandle, fOption, &result, BufferLength, NULL);
432 return result;
434 template < typename T, SQLINTEGER BufferLength > SQLRETURN OStatement_Base::setStmtOption (SQLINTEGER fOption, T value) const
436 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
437 SQLPOINTER sv = reinterpret_cast<SQLPOINTER>(value);
438 return N3SQLSetStmtAttr(m_aStatementHandle, fOption, sv, BufferLength);
442 Reference< XResultSet > SAL_CALL OStatement_Base::executeQuery( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
444 ::osl::MutexGuard aGuard( m_aMutex );
445 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
448 Reference< XResultSet > xRS = NULL;
450 // Execute the statement. If execute returns true, a result
451 // set exists.
453 if (execute (sql))
455 xRS = getResultSet (false);
456 m_xResultSet = xRS;
458 else
460 // No ResultSet was produced. Raise an exception
461 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
463 return xRS;
467 Reference< XConnection > SAL_CALL OStatement_Base::getConnection( ) throw(SQLException, RuntimeException, std::exception)
469 ::osl::MutexGuard aGuard( m_aMutex );
470 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
472 return (Reference< XConnection >)m_pConnection;
476 Any SAL_CALL OStatement::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
478 Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this));
479 return aRet.hasValue() ? aRet : OStatement_Base::queryInterface(rType);
483 void SAL_CALL OStatement::addBatch( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
485 ::osl::MutexGuard aGuard( m_aMutex );
486 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
489 m_aBatchList.push_back(sql);
492 Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch( ) throw(SQLException, RuntimeException, std::exception)
494 ::osl::MutexGuard aGuard( m_aMutex );
495 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
498 OString aBatchSql;
499 sal_Int32 nLen = 0;
500 for(::std::list< OUString>::const_iterator i=m_aBatchList.begin();i != m_aBatchList.end();++i,++nLen)
502 aBatchSql += OUStringToOString(*i,getOwnConnection()->getTextEncoding());
503 aBatchSql += ";";
506 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
507 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, (SDB_ODBC_CHAR*)aBatchSql.getStr(),aBatchSql.getLength()));
509 Sequence< sal_Int32 > aRet(nLen);
510 sal_Int32* pArray = aRet.getArray();
511 for(sal_Int32 j=0;j<nLen;++j)
513 SQLRETURN nError = N3SQLMoreResults(m_aStatementHandle);
514 if(nError == SQL_SUCCESS)
516 SQLLEN nRowCount=0;
517 N3SQLRowCount(m_aStatementHandle,&nRowCount);
518 pArray[j] = nRowCount;
521 return aRet;
526 sal_Int32 SAL_CALL OStatement_Base::executeUpdate( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
528 ::osl::MutexGuard aGuard( m_aMutex );
529 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
532 sal_Int32 numRows = -1;
534 // Execute the statement. If execute returns false, a
535 // row count exists.
537 if (!execute (sql)) {
538 numRows = getUpdateCount();
540 else {
542 // No update count was produced (a ResultSet was). Raise
543 // an exception
545 ::connectivity::SharedResources aResources;
546 const OUString sError( aResources.getResourceString(STR_NO_ROWCOUNT));
547 throw SQLException (sError, *this,OUString(),0,Any());
549 return numRows;
554 Reference< XResultSet > SAL_CALL OStatement_Base::getResultSet( ) throw(SQLException, RuntimeException, std::exception)
556 ::osl::MutexGuard aGuard( m_aMutex );
557 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
560 m_xResultSet = getResultSet(true);
561 return m_xResultSet;
565 sal_Int32 SAL_CALL OStatement_Base::getUpdateCount( ) throw(SQLException, RuntimeException, std::exception)
567 ::osl::MutexGuard aGuard( m_aMutex );
568 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
571 sal_Int32 rowCount = -1;
573 // Only return a row count for SQL statements that did not
574 // return a result set.
576 if (getColumnCount () == 0)
577 rowCount = getRowCount ();
579 return rowCount;
583 sal_Bool SAL_CALL OStatement_Base::getMoreResults( ) throw(SQLException, RuntimeException, std::exception)
585 ::osl::MutexGuard aGuard( m_aMutex );
586 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
589 SQLWarning warning;
590 bool hasResultSet = false;
592 // clear previous warnings
594 clearWarnings ();
596 // Call SQLMoreResults
597 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
599 try {
600 hasResultSet = N3SQLMoreResults(m_aStatementHandle) == SQL_SUCCESS;
602 catch (const SQLWarning &ex) {
604 // Save pointer to warning and save with ResultSet
605 // object once it is created.
607 warning = ex;
610 // There are more results (it may not be a result set, though)
612 if (hasResultSet)
615 // Now determine if there is a result set associated
616 // with the SQL statement that was executed. Get the
617 // column count, and if it is zero, there is not a
618 // result set.
620 if (getColumnCount () == 0)
621 hasResultSet = false;
624 // Set the warning for the statement, if one was generated
626 setWarning (warning);
628 // Return the result set indicator
630 return hasResultSet;
635 Any SAL_CALL OStatement_Base::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
637 ::osl::MutexGuard aGuard( m_aMutex );
638 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
641 return makeAny(m_aLastWarning);
646 void SAL_CALL OStatement_Base::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
648 ::osl::MutexGuard aGuard( m_aMutex );
649 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
652 m_aLastWarning = SQLWarning();
656 sal_Int64 OStatement_Base::getQueryTimeOut() const
658 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT);
661 sal_Int64 OStatement_Base::getMaxRows() const
663 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS);
666 sal_Int32 OStatement_Base::getResultSetConcurrency() const
668 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
669 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY));
670 if(nValue == SQL_CONCUR_READ_ONLY)
671 nValue = ResultSetConcurrency::READ_ONLY;
672 else
673 nValue = ResultSetConcurrency::UPDATABLE;
674 return nValue;
677 sal_Int32 OStatement_Base::getResultSetType() const
679 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
680 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY));
681 switch(nValue)
683 case SQL_CURSOR_FORWARD_ONLY:
684 nValue = ResultSetType::FORWARD_ONLY;
685 break;
686 case SQL_CURSOR_KEYSET_DRIVEN:
687 case SQL_CURSOR_STATIC:
688 nValue = ResultSetType::SCROLL_INSENSITIVE;
689 break;
690 case SQL_CURSOR_DYNAMIC:
691 nValue = ResultSetType::SCROLL_SENSITIVE;
692 break;
693 default:
694 OSL_FAIL("Unknown ODBC Cursor Type");
697 return nValue;
700 sal_Int32 OStatement_Base::getFetchDirection() const
702 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
703 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE));
704 switch(nValue)
706 case SQL_SCROLLABLE:
707 nValue = FetchDirection::REVERSE;
708 break;
709 default:
710 nValue = FetchDirection::FORWARD;
711 break;
714 return nValue;
717 sal_Int32 OStatement_Base::getFetchSize() const
719 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
720 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE);
723 sal_Int64 OStatement_Base::getMaxFieldSize() const
725 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH);
728 OUString OStatement_Base::getCursorName() const
730 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
731 SQLCHAR pName[258];
732 SQLSMALLINT nRealLen = 0;
733 SQLRETURN nRetCode = N3SQLGetCursorName(m_aStatementHandle,(SQLCHAR*)pName,256,&nRealLen);
734 OSL_UNUSED( nRetCode );
735 return OUString::createFromAscii((const char*)pName);
738 void OStatement_Base::setQueryTimeOut(sal_Int64 seconds)
740 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
741 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT,seconds);
744 void OStatement_Base::setMaxRows(sal_Int64 _par0)
746 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
747 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS, _par0);
750 void OStatement_Base::setResultSetConcurrency(sal_Int32 _par0)
752 SQLULEN nSet;
753 if(_par0 == ResultSetConcurrency::READ_ONLY)
754 nSet = SQL_CONCUR_READ_ONLY;
755 else
756 nSet = SQL_CONCUR_VALUES;
758 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
759 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, nSet);
762 void OStatement_Base::setResultSetType(sal_Int32 _par0)
765 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
766 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN);
768 bool bUseBookmark = isUsingBookmarks();
769 SQLULEN nSet( SQL_UNSPECIFIED );
770 switch(_par0)
772 case ResultSetType::FORWARD_ONLY:
773 nSet = SQL_UNSPECIFIED;
774 break;
775 case ResultSetType::SCROLL_INSENSITIVE:
776 nSet = SQL_INSENSITIVE;
777 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
778 break;
779 case ResultSetType::SCROLL_SENSITIVE:
780 if(bUseBookmark)
782 SQLUINTEGER nCurProp = getCursorProperties(SQL_CURSOR_DYNAMIC,true);
783 if((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK) // check if bookmark for this type isn't supported
784 { // we have to test the next one
785 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,true);
786 bool bNotBookmarks = ((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK);
787 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,false);
788 nSet = SQL_CURSOR_KEYSET_DRIVEN;
789 if( bNotBookmarks ||
790 ((nCurProp & SQL_CA2_SENSITIVITY_DELETIONS) != SQL_CA2_SENSITIVITY_DELETIONS) ||
791 ((nCurProp & SQL_CA2_SENSITIVITY_ADDITIONS) != SQL_CA2_SENSITIVITY_ADDITIONS))
793 // bookmarks for keyset isn't supported so reset bookmark setting
794 setUsingBookmarks(sal_False);
795 nSet = SQL_CURSOR_DYNAMIC;
798 else
799 nSet = SQL_CURSOR_DYNAMIC;
801 else
802 nSet = SQL_CURSOR_DYNAMIC;
803 if( setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, nSet) != SQL_SUCCESS )
805 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
807 nSet = SQL_SENSITIVE;
808 break;
809 default:
810 OSL_FAIL( "OStatement_Base::setResultSetType: invalid result set type!" );
811 break;
815 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SENSITIVITY, nSet);
818 void OStatement_Base::setEscapeProcessing( const bool _bEscapeProc )
820 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
821 SQLULEN nEscapeProc( _bEscapeProc ? SQL_NOSCAN_OFF : SQL_NOSCAN_ON );
822 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_NOSCAN, nEscapeProc);
826 void OStatement_Base::setFetchDirection(sal_Int32 _par0)
828 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
829 if(_par0 == FetchDirection::FORWARD)
831 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_NONSCROLLABLE);
833 else if(_par0 == FetchDirection::REVERSE)
835 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_SCROLLABLE);
839 void OStatement_Base::setFetchSize(sal_Int32 _par0)
841 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
842 OSL_ENSURE(_par0>0,"Illegal fetch size!");
843 if ( _par0 > 0 )
845 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE, _par0);
847 if (m_pRowStatusArray)
848 delete[] m_pRowStatusArray;
849 m_pRowStatusArray = new SQLUSMALLINT[_par0];
850 setStmtOption<SQLUSMALLINT*, SQL_IS_POINTER>(SQL_ATTR_ROW_STATUS_PTR, m_pRowStatusArray);
854 void OStatement_Base::setMaxFieldSize(sal_Int64 _par0)
856 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
857 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH, _par0);
860 void OStatement_Base::setCursorName(const OUString &_par0)
862 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
863 OString aName(OUStringToOString(_par0,getOwnConnection()->getTextEncoding()));
864 N3SQLSetCursorName(m_aStatementHandle,(SDB_ODBC_CHAR*)aName.getStr(),(SQLSMALLINT)aName.getLength());
867 bool OStatement_Base::isUsingBookmarks() const
869 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
870 return SQL_UB_OFF != getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, SQL_UB_OFF);
873 bool OStatement_Base::getEscapeProcessing() const
875 OSL_ENSURE( m_aStatementHandle, "StatementHandle is null!" );
876 return SQL_NOSCAN_OFF == getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, SQL_NOSCAN_OFF);;
879 void OStatement_Base::setUsingBookmarks(sal_Bool _bUseBookmark)
881 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
882 SQLULEN nValue = _bUseBookmark ? SQL_UB_VARIABLE : SQL_UB_OFF;
883 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, nValue);
886 ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const
888 Sequence< Property > aProps(10);
889 Property* pProperties = aProps.getArray();
890 sal_Int32 nPos = 0;
891 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
892 PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
893 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
894 PROPERTY_ID_ESCAPEPROCESSING, ::getBooleanCppuType(), 0);
895 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
896 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
897 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
898 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
899 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
900 PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
901 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
902 PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
903 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
904 PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
905 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
906 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
907 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
908 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
909 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
910 PROPERTY_ID_USEBOOKMARKS, ::getBooleanCppuType(), 0);
912 return new ::cppu::OPropertyArrayHelper(aProps);
916 ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper()
918 return *const_cast<OStatement_Base*>(this)->getArrayHelper();
921 sal_Bool OStatement_Base::convertFastPropertyValue(
922 Any & rConvertedValue,
923 Any & rOldValue,
924 sal_Int32 nHandle,
925 const Any& rValue )
926 throw (::com::sun::star::lang::IllegalArgumentException)
928 bool bConverted = false;
931 switch(nHandle)
933 case PROPERTY_ID_QUERYTIMEOUT:
934 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getQueryTimeOut());
935 break;
937 case PROPERTY_ID_MAXFIELDSIZE:
938 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxFieldSize());
939 break;
941 case PROPERTY_ID_MAXROWS:
942 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxRows());
943 break;
945 case PROPERTY_ID_CURSORNAME:
946 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getCursorName());
947 break;
949 case PROPERTY_ID_RESULTSETCONCURRENCY:
950 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetConcurrency());
951 break;
953 case PROPERTY_ID_RESULTSETTYPE:
954 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetType());
955 break;
957 case PROPERTY_ID_FETCHDIRECTION:
958 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
959 break;
961 case PROPERTY_ID_FETCHSIZE:
962 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
963 break;
965 case PROPERTY_ID_USEBOOKMARKS:
966 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, isUsingBookmarks());
967 break;
969 case PROPERTY_ID_ESCAPEPROCESSING:
970 bConverted = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, getEscapeProcessing() );
971 break;
975 catch(const SQLException&)
977 // throw Exception(e.Message,*this);
979 return bConverted;
982 void OStatement_Base::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception, std::exception)
986 switch(nHandle)
988 case PROPERTY_ID_QUERYTIMEOUT:
989 setQueryTimeOut(comphelper::getINT64(rValue));
990 break;
991 case PROPERTY_ID_MAXFIELDSIZE:
992 setMaxFieldSize(comphelper::getINT64(rValue));
993 break;
994 case PROPERTY_ID_MAXROWS:
995 setMaxRows(comphelper::getINT64(rValue));
996 break;
997 case PROPERTY_ID_CURSORNAME:
998 setCursorName(comphelper::getString(rValue));
999 break;
1000 case PROPERTY_ID_RESULTSETCONCURRENCY:
1001 setResultSetConcurrency(comphelper::getINT32(rValue));
1002 break;
1003 case PROPERTY_ID_RESULTSETTYPE:
1004 setResultSetType(comphelper::getINT32(rValue));
1005 break;
1006 case PROPERTY_ID_FETCHDIRECTION:
1007 setFetchDirection(comphelper::getINT32(rValue));
1008 break;
1009 case PROPERTY_ID_FETCHSIZE:
1010 setFetchSize(comphelper::getINT32(rValue));
1011 break;
1012 case PROPERTY_ID_USEBOOKMARKS:
1013 setUsingBookmarks(comphelper::getBOOL(rValue));
1014 break;
1015 case PROPERTY_ID_ESCAPEPROCESSING:
1016 setEscapeProcessing( ::comphelper::getBOOL( rValue ) );
1017 break;
1018 default:
1019 OSL_FAIL( "OStatement_Base::setFastPropertyValue_NoBroadcast: what property?" );
1020 break;
1023 catch(const SQLException& )
1025 // throw Exception(e.Message,*this);
1029 void OStatement_Base::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
1031 switch(nHandle)
1033 case PROPERTY_ID_QUERYTIMEOUT:
1034 rValue <<= getQueryTimeOut();
1035 break;
1036 case PROPERTY_ID_MAXFIELDSIZE:
1037 rValue <<= getMaxFieldSize();
1038 break;
1039 case PROPERTY_ID_MAXROWS:
1040 rValue <<= getMaxRows();
1041 break;
1042 case PROPERTY_ID_CURSORNAME:
1043 rValue <<= getCursorName();
1044 break;
1045 case PROPERTY_ID_RESULTSETCONCURRENCY:
1046 rValue <<= getResultSetConcurrency();
1047 break;
1048 case PROPERTY_ID_RESULTSETTYPE:
1049 rValue <<= getResultSetType();
1050 break;
1051 case PROPERTY_ID_FETCHDIRECTION:
1052 rValue <<= getFetchDirection();
1053 break;
1054 case PROPERTY_ID_FETCHSIZE:
1055 rValue <<= getFetchSize();
1056 break;
1057 case PROPERTY_ID_USEBOOKMARKS:
1058 rValue <<= isUsingBookmarks();
1059 break;
1060 case PROPERTY_ID_ESCAPEPROCESSING:
1061 rValue <<= getEscapeProcessing();
1062 break;
1063 default:
1064 OSL_FAIL( "OStatement_Base::getFastPropertyValue: what property?" );
1065 break;
1069 IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
1071 void SAL_CALL OStatement_Base::acquire() throw()
1073 OStatement_BASE::acquire();
1076 void SAL_CALL OStatement_Base::release() throw()
1078 OStatement_BASE::release();
1081 void SAL_CALL OStatement::acquire() throw()
1083 OStatement_BASE2::acquire();
1086 void SAL_CALL OStatement::release() throw()
1088 OStatement_BASE2::release();
1091 OResultSet* OStatement_Base::createResulSet()
1093 return new OResultSet(m_aStatementHandle,this);
1096 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo( ) throw(RuntimeException, std::exception)
1098 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1101 SQLUINTEGER OStatement_Base::getCursorProperties(SQLINTEGER _nCursorType, bool bFirst)
1103 SQLUINTEGER nValueLen = 0;
1106 SQLUSMALLINT nAskFor = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1107 if(SQL_CURSOR_KEYSET_DRIVEN == _nCursorType)
1108 nAskFor = bFirst ? SQL_KEYSET_CURSOR_ATTRIBUTES1 : SQL_KEYSET_CURSOR_ATTRIBUTES2;
1109 else if(SQL_CURSOR_STATIC == _nCursorType)
1110 nAskFor = bFirst ? SQL_STATIC_CURSOR_ATTRIBUTES1 : SQL_STATIC_CURSOR_ATTRIBUTES2;
1111 else if(SQL_CURSOR_FORWARD_ONLY == _nCursorType)
1112 nAskFor = bFirst ? SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 : SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1113 else if(SQL_CURSOR_DYNAMIC == _nCursorType)
1114 nAskFor = bFirst ? SQL_DYNAMIC_CURSOR_ATTRIBUTES1 : SQL_DYNAMIC_CURSOR_ATTRIBUTES2;
1117 OTools::GetInfo(getOwnConnection(),getConnectionHandle(),nAskFor,nValueLen,NULL);
1119 catch(const Exception&)
1120 { // we don't want our result destroy here
1121 nValueLen = 0;
1123 return nValueLen;
1127 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */