bump product version to 6.3.0.0.beta1
[LibreOffice.git] / connectivity / source / drivers / odbc / OStatement.cxx
blob5797ec6e436af9cc954d3d991a1773e1228e536a
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 <osl/diagnose.h>
22 #include <odbc/OStatement.hxx>
23 #include <odbc/OConnection.hxx>
24 #include <odbc/OResultSet.hxx>
25 #include <comphelper/property.hxx>
26 #include <odbc/OTools.hxx>
27 #include <osl/thread.h>
28 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
29 #include <com/sun/star/sdbc/ResultSetType.hpp>
30 #include <com/sun/star/sdbc/FetchDirection.hpp>
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include <comphelper/sequence.hxx>
33 #include <cppuhelper/typeprovider.hxx>
34 #include <cppuhelper/queryinterface.hxx>
35 #include <comphelper/types.hxx>
36 #include <rtl/strbuf.hxx>
37 #include <algorithm>
38 #include <strings.hrc>
39 #include <connectivity/dbexception.hxx>
41 using namespace ::comphelper;
43 #define THROW_SQL(x) \
44 OTools::ThrowException(m_pConnection.get(),x,m_aStatementHandle,SQL_HANDLE_STMT,*this)
47 using namespace connectivity::odbc;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::lang;
51 using namespace com::sun::star::beans;
52 using namespace com::sun::star::sdbc;
53 using namespace com::sun::star::sdbcx;
54 using namespace com::sun::star::container;
55 using namespace com::sun::star::io;
56 using namespace com::sun::star::util;
58 OStatement_Base::OStatement_Base(OConnection* _pConnection )
59 :OStatement_BASE(m_aMutex)
60 ,OPropertySetHelper(OStatement_BASE::rBHelper)
61 ,m_pConnection(_pConnection)
62 ,m_aStatementHandle(SQL_NULL_HANDLE)
63 ,m_pRowStatusArray(nullptr)
65 osl_atomic_increment( &m_refCount );
66 m_aStatementHandle = m_pConnection->createStatementHandle();
68 //setMaxFieldSize(0);
69 // Don't do this. By ODBC spec, "0" is the default for the SQL_ATTR_MAX_LENGTH attribute. We once introduced
70 // this line since a PostgreSQL ODBC driver had a default other than 0. However, current drivers (at least 8.3
71 // and later) have a proper default of 0, so there should be no need anymore.
72 // On the other hand, the NotesSQL driver (IBM's ODBC driver for the Lotus Notes series) wrongly interprets
73 // "0" as "0", whereas the ODBC spec says it should in fact mean "unlimited".
74 // So, removing this line seems to be the best option for now.
75 // If we ever again encounter an ODBC driver which needs this option, then we should introduce a data source
76 // setting for it, instead of unconditionally doing it.
78 osl_atomic_decrement( &m_refCount );
81 OStatement_Base::~OStatement_Base()
83 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
86 void OStatement_Base::disposeResultSet()
88 // free the cursor if alive
89 Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY);
90 if (xComp.is())
91 xComp->dispose();
92 m_xResultSet.clear();
95 void SAL_CALL OStatement_Base::disposing()
97 ::osl::MutexGuard aGuard(m_aMutex);
99 disposeResultSet();
100 ::comphelper::disposeComponent(m_xGeneratedStatement);
102 OSL_ENSURE(m_aStatementHandle,"OStatement_BASE2::disposing: StatementHandle is null!");
103 if (m_pConnection.is())
105 m_pConnection->freeStatementHandle(m_aStatementHandle);
106 m_pConnection.clear();
108 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
110 OStatement_BASE::disposing();
113 void OStatement_BASE2::disposing()
115 ::osl::MutexGuard aGuard1(m_aMutex);
116 OStatement_Base::disposing();
119 Any SAL_CALL OStatement_Base::queryInterface( const Type & rType )
121 if ( m_pConnection.is() && !m_pConnection->isAutoRetrievingEnabled() && rType == cppu::UnoType<XGeneratedResultSet>::get())
122 return Any();
123 Any aRet = OStatement_BASE::queryInterface(rType);
124 return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
127 Sequence< Type > SAL_CALL OStatement_Base::getTypes( )
129 ::cppu::OTypeCollection aTypes( cppu::UnoType<XMultiPropertySet>::get(),
130 cppu::UnoType<XFastPropertySet>::get(),
131 cppu::UnoType<XPropertySet>::get());
132 Sequence< Type > aOldTypes = OStatement_BASE::getTypes();
133 if ( m_pConnection.is() && !m_pConnection->isAutoRetrievingEnabled() )
135 auto newEnd = std::remove(aOldTypes.begin(), aOldTypes.end(),
136 cppu::UnoType<XGeneratedResultSet>::get());
137 aOldTypes.realloc(std::distance(aOldTypes.begin(), newEnd));
140 return ::comphelper::concatSequences(aTypes.getTypes(),aOldTypes);
143 Reference< XResultSet > SAL_CALL OStatement_Base::getGeneratedValues( )
145 OSL_ENSURE( m_pConnection.is() && m_pConnection->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!");
146 Reference< XResultSet > xRes;
147 if ( m_pConnection.is() )
149 OUString sStmt = m_pConnection->getTransformedGeneratedStatement(m_sSqlStatement);
150 if ( !sStmt.isEmpty() )
152 ::comphelper::disposeComponent(m_xGeneratedStatement);
153 m_xGeneratedStatement = m_pConnection->createStatement();
154 xRes = m_xGeneratedStatement->executeQuery(sStmt);
157 return xRes;
160 void SAL_CALL OStatement_Base::cancel( )
162 ::osl::MutexGuard aGuard( m_aMutex );
163 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
165 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
166 N3SQLCancel(m_aStatementHandle);
170 void SAL_CALL OStatement_Base::close( )
173 ::osl::MutexGuard aGuard( m_aMutex );
174 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
177 dispose();
181 void SAL_CALL OStatement::clearBatch( )
186 void OStatement_Base::reset()
188 ::osl::MutexGuard aGuard( m_aMutex );
189 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
192 clearWarnings ();
194 if (m_xResultSet.get().is())
196 clearMyResultSet();
198 if(m_aStatementHandle)
200 THROW_SQL(N3SQLFreeStmt(m_aStatementHandle, SQL_CLOSE));
204 // clearMyResultSet
205 // If a ResultSet was created for this Statement, close it
206 void OStatement_Base::clearMyResultSet()
208 ::osl::MutexGuard aGuard( m_aMutex );
209 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
213 Reference<XCloseable> xCloseable(
214 m_xResultSet.get(), css::uno::UNO_QUERY);
215 if ( xCloseable.is() )
216 xCloseable->close();
218 catch( const DisposedException& ) { }
220 m_xResultSet.clear();
223 SQLLEN OStatement_Base::getRowCount()
225 ::osl::MutexGuard aGuard( m_aMutex );
226 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
229 SQLLEN numRows = 0;
231 try {
232 THROW_SQL(N3SQLRowCount(m_aStatementHandle,&numRows));
234 catch (const SQLException&)
237 return numRows;
240 // lockIfNecessary
241 // If the given SQL statement contains a 'FOR UPDATE' clause, change
242 // the concurrency to lock so that the row can then be updated. Returns
243 // true if the concurrency has been changed
244 bool OStatement_Base::lockIfNecessary (const OUString& sql)
246 bool rc = false;
248 // First, convert the statement to upper case
250 OUString sqlStatement = sql.toAsciiUpperCase ();
252 // Now, look for the FOR UPDATE keywords. If there is any extra white
253 // space between the FOR and UPDATE, this will fail.
255 sal_Int32 index = sqlStatement.indexOf(" FOR UPDATE");
257 // We found it. Change our concurrency level to ensure that the
258 // row can be updated.
260 if (index > 0)
262 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
265 THROW_SQL((setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, SQL_CONCUR_LOCK)));
267 catch (const SQLWarning& warn)
269 // Catch any warnings and place on the warning stack
270 setWarning (warn);
272 rc = true;
275 return rc;
278 // setWarning
279 // Sets the warning
282 void OStatement_Base::setWarning (const SQLWarning &ex)
284 ::osl::MutexGuard aGuard( m_aMutex );
285 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
288 m_aLastWarning = ex;
292 // getColumnCount
293 // Return the number of columns in the ResultSet
294 sal_Int32 OStatement_Base::getColumnCount()
296 ::osl::MutexGuard aGuard( m_aMutex );
297 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
300 sal_Int16 numCols = 0;
301 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
303 try {
304 THROW_SQL(N3SQLNumResultCols(m_aStatementHandle,&numCols));
306 catch (const SQLException&)
309 return numCols;
313 sal_Bool SAL_CALL OStatement_Base::execute( const OUString& sql )
315 ::osl::MutexGuard aGuard( m_aMutex );
316 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
317 m_sSqlStatement = sql;
320 OString aSql(OUStringToOString(sql,getOwnConnection()->getTextEncoding()));
322 bool hasResultSet = false;
323 SQLWarning aWarning;
325 // Reset the statement handle and warning
327 reset();
329 // Check for a 'FOR UPDATE' statement. If present, change
330 // the concurrency to lock
332 lockIfNecessary (sql);
334 // Call SQLExecDirect
335 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
337 try {
338 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength()));
340 catch (const SQLWarning& ex) {
342 // Save pointer to warning and save with ResultSet
343 // object once it is created.
345 aWarning = ex;
348 // Now determine if there is a result set associated with
349 // the SQL statement that was executed. Get the column
350 // count, and if it is not zero, there is a result set.
352 if (getColumnCount () > 0)
354 hasResultSet = true;
357 return hasResultSet;
360 // getResultSet
361 // getResultSet returns the current result as a ResultSet. It
362 // returns NULL if the current result is not a ResultSet.
364 Reference< XResultSet > OStatement_Base::getResultSet(bool checkCount)
366 ::osl::MutexGuard aGuard( m_aMutex );
367 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
370 if (m_xResultSet.get().is()) // if resultset already retrieved,
372 // throw exception to avoid sequence error
373 ::dbtools::throwFunctionSequenceException(*this);
376 OResultSet* pRs = nullptr;
377 sal_Int32 numCols = 1;
379 // If we already know we have result columns, checkCount
380 // is false. This is an optimization to prevent unneeded
381 // calls to getColumnCount
383 if (checkCount)
384 numCols = getColumnCount ();
386 // Only return a result set if there are result columns
388 if (numCols > 0)
390 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
391 pRs = createResulSet();
392 pRs->construct();
394 // Save a copy of our last result set
395 // Changed to save copy at getResultSet.
396 //m_xResultSet = rs;
398 else
399 clearMyResultSet ();
401 return pRs;
404 // getStmtOption
405 // Invoke SQLGetStmtOption with the given option.
408 template < typename T, SQLINTEGER BufferLength > T OStatement_Base::getStmtOption (SQLINTEGER fOption) const
410 T result (0);
411 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
412 N3SQLGetStmtAttr(m_aStatementHandle, fOption, &result, BufferLength, nullptr);
413 return result;
415 template < typename T, SQLINTEGER BufferLength > SQLRETURN OStatement_Base::setStmtOption (SQLINTEGER fOption, T value) const
417 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
418 SQLPOINTER sv = reinterpret_cast<SQLPOINTER>(value);
419 return N3SQLSetStmtAttr(m_aStatementHandle, fOption, sv, BufferLength);
423 Reference< XResultSet > SAL_CALL OStatement_Base::executeQuery( const OUString& sql )
425 ::osl::MutexGuard aGuard( m_aMutex );
426 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
429 Reference< XResultSet > xRS;
431 // Execute the statement. If execute returns true, a result
432 // set exists.
434 if (execute (sql))
436 xRS = getResultSet (false);
437 m_xResultSet = xRS;
439 else
441 // No ResultSet was produced. Raise an exception
442 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
444 return xRS;
448 Reference< XConnection > SAL_CALL OStatement_Base::getConnection( )
450 ::osl::MutexGuard aGuard( m_aMutex );
451 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
453 return Reference< XConnection >(m_pConnection.get());
457 Any SAL_CALL OStatement::queryInterface( const Type & rType )
459 Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this));
460 return aRet.hasValue() ? aRet : OStatement_Base::queryInterface(rType);
464 void SAL_CALL OStatement::addBatch( const OUString& sql )
466 ::osl::MutexGuard aGuard( m_aMutex );
467 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
470 m_aBatchVector.push_back(sql);
473 Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch( )
475 ::osl::MutexGuard aGuard( m_aMutex );
476 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
478 OStringBuffer aBatchSql;
479 sal_Int32 nLen = m_aBatchVector.size();
481 for (auto const& elem : m_aBatchVector)
483 aBatchSql.append(OUStringToOString(elem,getOwnConnection()->getTextEncoding()));
484 aBatchSql.append(";");
487 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
488 auto s = aBatchSql.makeStringAndClear();
489 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(s.getStr())), s.getLength()));
491 Sequence< sal_Int32 > aRet(nLen);
492 sal_Int32* pArray = aRet.getArray();
493 for(sal_Int32 j=0;j<nLen;++j)
495 SQLRETURN nError = N3SQLMoreResults(m_aStatementHandle);
496 if(nError == SQL_SUCCESS)
498 SQLLEN nRowCount=0;
499 N3SQLRowCount(m_aStatementHandle,&nRowCount);
500 pArray[j] = nRowCount;
503 return aRet;
507 sal_Int32 SAL_CALL OStatement_Base::executeUpdate( const OUString& sql )
509 ::osl::MutexGuard aGuard( m_aMutex );
510 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
513 sal_Int32 numRows = -1;
515 // Execute the statement. If execute returns false, a
516 // row count exists.
518 if (!execute (sql)) {
519 numRows = getUpdateCount();
521 else {
523 // No update count was produced (a ResultSet was). Raise
524 // an exception
526 ::connectivity::SharedResources aResources;
527 const OUString sError( aResources.getResourceString(STR_NO_ROWCOUNT));
528 throw SQLException (sError, *this,OUString(),0,Any());
530 return numRows;
535 Reference< XResultSet > SAL_CALL OStatement_Base::getResultSet( )
537 ::osl::MutexGuard aGuard( m_aMutex );
538 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
541 m_xResultSet = getResultSet(true);
542 return m_xResultSet;
546 sal_Int32 SAL_CALL OStatement_Base::getUpdateCount( )
548 ::osl::MutexGuard aGuard( m_aMutex );
549 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
552 sal_Int32 rowCount = -1;
554 // Only return a row count for SQL statements that did not
555 // return a result set.
557 if (getColumnCount () == 0)
558 rowCount = getRowCount ();
560 return rowCount;
564 sal_Bool SAL_CALL OStatement_Base::getMoreResults( )
566 ::osl::MutexGuard aGuard( m_aMutex );
567 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
570 SQLWarning warning;
571 bool hasResultSet = false;
573 // clear previous warnings
575 clearWarnings ();
577 // Call SQLMoreResults
578 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
580 try {
581 hasResultSet = N3SQLMoreResults(m_aStatementHandle) == SQL_SUCCESS;
583 catch (const SQLWarning &ex) {
585 // Save pointer to warning and save with ResultSet
586 // object once it is created.
588 warning = ex;
591 // There are more results (it may not be a result set, though)
593 if (hasResultSet)
596 // Now determine if there is a result set associated
597 // with the SQL statement that was executed. Get the
598 // column count, and if it is zero, there is not a
599 // result set.
601 if (getColumnCount () == 0)
602 hasResultSet = false;
605 // Set the warning for the statement, if one was generated
607 setWarning (warning);
609 // Return the result set indicator
611 return hasResultSet;
615 Any SAL_CALL OStatement_Base::getWarnings( )
617 ::osl::MutexGuard aGuard( m_aMutex );
618 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
621 return makeAny(m_aLastWarning);
625 void SAL_CALL OStatement_Base::clearWarnings( )
627 ::osl::MutexGuard aGuard( m_aMutex );
628 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
631 m_aLastWarning = SQLWarning();
635 sal_Int64 OStatement_Base::getQueryTimeOut() const
637 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT);
640 sal_Int64 OStatement_Base::getMaxRows() const
642 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS);
645 sal_Int32 OStatement_Base::getResultSetConcurrency() const
647 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
648 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY));
649 if(nValue == SQL_CONCUR_READ_ONLY)
650 nValue = ResultSetConcurrency::READ_ONLY;
651 else
652 nValue = ResultSetConcurrency::UPDATABLE;
653 return nValue;
656 sal_Int32 OStatement_Base::getResultSetType() const
658 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
659 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE));
660 switch(nValue)
662 case SQL_CURSOR_FORWARD_ONLY:
663 nValue = ResultSetType::FORWARD_ONLY;
664 break;
665 case SQL_CURSOR_KEYSET_DRIVEN:
666 case SQL_CURSOR_STATIC:
667 nValue = ResultSetType::SCROLL_INSENSITIVE;
668 break;
669 case SQL_CURSOR_DYNAMIC:
670 nValue = ResultSetType::SCROLL_SENSITIVE;
671 break;
672 default:
673 OSL_FAIL("Unknown ODBC Cursor Type");
676 return nValue;
679 sal_Int32 OStatement_Base::getFetchDirection() const
681 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
682 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE));
683 switch(nValue)
685 case SQL_SCROLLABLE:
686 nValue = FetchDirection::REVERSE;
687 break;
688 default:
689 nValue = FetchDirection::FORWARD;
690 break;
693 return nValue;
696 sal_Int32 OStatement_Base::getFetchSize() const
698 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
699 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE);
702 sal_Int64 OStatement_Base::getMaxFieldSize() const
704 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH);
707 OUString OStatement_Base::getCursorName() const
709 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
710 SQLCHAR pName[258];
711 SQLSMALLINT nRealLen = 0;
712 N3SQLGetCursorName(m_aStatementHandle,pName,256,&nRealLen);
713 return OUString::createFromAscii(reinterpret_cast<char*>(pName));
716 void OStatement_Base::setQueryTimeOut(sal_Int64 seconds)
718 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
719 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT,seconds);
722 void OStatement_Base::setMaxRows(sal_Int64 _par0)
724 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
725 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS, _par0);
728 void OStatement_Base::setResultSetConcurrency(sal_Int32 _par0)
730 SQLULEN nSet;
731 if(_par0 == ResultSetConcurrency::READ_ONLY)
732 nSet = SQL_CONCUR_READ_ONLY;
733 else
734 nSet = SQL_CONCUR_VALUES;
736 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
737 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, nSet);
740 void OStatement_Base::setResultSetType(sal_Int32 _par0)
743 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
744 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN);
746 bool bUseBookmark = isUsingBookmarks();
747 SQLULEN nSet( SQL_UNSPECIFIED );
748 switch(_par0)
750 case ResultSetType::FORWARD_ONLY:
751 nSet = SQL_UNSPECIFIED;
752 break;
753 case ResultSetType::SCROLL_INSENSITIVE:
754 nSet = SQL_INSENSITIVE;
755 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
756 break;
757 case ResultSetType::SCROLL_SENSITIVE:
758 if(bUseBookmark)
760 SQLUINTEGER nCurProp = getCursorProperties(SQL_CURSOR_DYNAMIC,true);
761 if((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK) // check if bookmark for this type isn't supported
762 { // we have to test the next one
763 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,true);
764 bool bNotBookmarks = ((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK);
765 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,false);
766 nSet = SQL_CURSOR_KEYSET_DRIVEN;
767 if( bNotBookmarks ||
768 ((nCurProp & SQL_CA2_SENSITIVITY_DELETIONS) != SQL_CA2_SENSITIVITY_DELETIONS) ||
769 ((nCurProp & SQL_CA2_SENSITIVITY_ADDITIONS) != SQL_CA2_SENSITIVITY_ADDITIONS))
771 // bookmarks for keyset isn't supported so reset bookmark setting
772 setUsingBookmarks(false);
773 nSet = SQL_CURSOR_DYNAMIC;
776 else
777 nSet = SQL_CURSOR_DYNAMIC;
779 else
780 nSet = SQL_CURSOR_DYNAMIC;
781 if( setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, nSet) != SQL_SUCCESS )
783 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
785 nSet = SQL_SENSITIVE;
786 break;
787 default:
788 OSL_FAIL( "OStatement_Base::setResultSetType: invalid result set type!" );
789 break;
793 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SENSITIVITY, nSet);
796 void OStatement_Base::setEscapeProcessing( const bool _bEscapeProc )
798 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
799 SQLULEN nEscapeProc( _bEscapeProc ? SQL_NOSCAN_OFF : SQL_NOSCAN_ON );
800 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_NOSCAN, nEscapeProc);
804 void OStatement_Base::setFetchDirection(sal_Int32 _par0)
806 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
807 if(_par0 == FetchDirection::FORWARD)
809 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_NONSCROLLABLE);
811 else if(_par0 == FetchDirection::REVERSE)
813 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_SCROLLABLE);
817 void OStatement_Base::setFetchSize(sal_Int32 _par0)
819 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
820 OSL_ENSURE(_par0>0,"Illegal fetch size!");
821 if ( _par0 > 0 )
823 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE, _par0);
825 delete[] m_pRowStatusArray;
826 m_pRowStatusArray = new SQLUSMALLINT[_par0];
827 setStmtOption<SQLUSMALLINT*, SQL_IS_POINTER>(SQL_ATTR_ROW_STATUS_PTR, m_pRowStatusArray);
831 void OStatement_Base::setMaxFieldSize(sal_Int64 _par0)
833 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
834 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH, _par0);
837 void OStatement_Base::setCursorName(const OUString &_par0)
839 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
840 OString aName(OUStringToOString(_par0,getOwnConnection()->getTextEncoding()));
841 N3SQLSetCursorName(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aName.getStr())), static_cast<SQLSMALLINT>(aName.getLength()));
844 bool OStatement_Base::isUsingBookmarks() const
846 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
847 return SQL_UB_OFF != getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS);
850 bool OStatement_Base::getEscapeProcessing() const
852 OSL_ENSURE( m_aStatementHandle, "StatementHandle is null!" );
853 return SQL_NOSCAN_OFF == getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS);
856 void OStatement_Base::setUsingBookmarks(bool _bUseBookmark)
858 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
859 SQLULEN nValue = _bUseBookmark ? SQL_UB_VARIABLE : SQL_UB_OFF;
860 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, nValue);
863 ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const
865 Sequence< Property > aProps(10);
866 Property* pProperties = aProps.getArray();
867 sal_Int32 nPos = 0;
868 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
869 PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
870 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
871 PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
872 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
873 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
874 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
875 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
876 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
877 PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
878 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
879 PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
880 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
881 PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
882 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
883 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
884 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
885 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
886 pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
887 PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
889 return new ::cppu::OPropertyArrayHelper(aProps);
893 ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper()
895 return *getArrayHelper();
898 sal_Bool OStatement_Base::convertFastPropertyValue(
899 Any & rConvertedValue,
900 Any & rOldValue,
901 sal_Int32 nHandle,
902 const Any& rValue )
904 bool bConverted = false;
907 switch(nHandle)
909 case PROPERTY_ID_QUERYTIMEOUT:
910 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getQueryTimeOut());
911 break;
913 case PROPERTY_ID_MAXFIELDSIZE:
914 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxFieldSize());
915 break;
917 case PROPERTY_ID_MAXROWS:
918 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxRows());
919 break;
921 case PROPERTY_ID_CURSORNAME:
922 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getCursorName());
923 break;
925 case PROPERTY_ID_RESULTSETCONCURRENCY:
926 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetConcurrency());
927 break;
929 case PROPERTY_ID_RESULTSETTYPE:
930 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetType());
931 break;
933 case PROPERTY_ID_FETCHDIRECTION:
934 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
935 break;
937 case PROPERTY_ID_FETCHSIZE:
938 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
939 break;
941 case PROPERTY_ID_USEBOOKMARKS:
942 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, isUsingBookmarks());
943 break;
945 case PROPERTY_ID_ESCAPEPROCESSING:
946 bConverted = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, getEscapeProcessing() );
947 break;
951 catch(const SQLException&)
953 // throw Exception(e.Message,*this);
955 return bConverted;
958 void OStatement_Base::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue)
962 switch(nHandle)
964 case PROPERTY_ID_QUERYTIMEOUT:
965 setQueryTimeOut(comphelper::getINT64(rValue));
966 break;
967 case PROPERTY_ID_MAXFIELDSIZE:
968 setMaxFieldSize(comphelper::getINT64(rValue));
969 break;
970 case PROPERTY_ID_MAXROWS:
971 setMaxRows(comphelper::getINT64(rValue));
972 break;
973 case PROPERTY_ID_CURSORNAME:
974 setCursorName(comphelper::getString(rValue));
975 break;
976 case PROPERTY_ID_RESULTSETCONCURRENCY:
977 setResultSetConcurrency(comphelper::getINT32(rValue));
978 break;
979 case PROPERTY_ID_RESULTSETTYPE:
980 setResultSetType(comphelper::getINT32(rValue));
981 break;
982 case PROPERTY_ID_FETCHDIRECTION:
983 setFetchDirection(comphelper::getINT32(rValue));
984 break;
985 case PROPERTY_ID_FETCHSIZE:
986 setFetchSize(comphelper::getINT32(rValue));
987 break;
988 case PROPERTY_ID_USEBOOKMARKS:
989 setUsingBookmarks(comphelper::getBOOL(rValue));
990 break;
991 case PROPERTY_ID_ESCAPEPROCESSING:
992 setEscapeProcessing( ::comphelper::getBOOL( rValue ) );
993 break;
994 default:
995 OSL_FAIL( "OStatement_Base::setFastPropertyValue_NoBroadcast: what property?" );
996 break;
999 catch(const SQLException& )
1001 // throw Exception(e.Message,*this);
1005 void OStatement_Base::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
1007 switch(nHandle)
1009 case PROPERTY_ID_QUERYTIMEOUT:
1010 rValue <<= getQueryTimeOut();
1011 break;
1012 case PROPERTY_ID_MAXFIELDSIZE:
1013 rValue <<= getMaxFieldSize();
1014 break;
1015 case PROPERTY_ID_MAXROWS:
1016 rValue <<= getMaxRows();
1017 break;
1018 case PROPERTY_ID_CURSORNAME:
1019 rValue <<= getCursorName();
1020 break;
1021 case PROPERTY_ID_RESULTSETCONCURRENCY:
1022 rValue <<= getResultSetConcurrency();
1023 break;
1024 case PROPERTY_ID_RESULTSETTYPE:
1025 rValue <<= getResultSetType();
1026 break;
1027 case PROPERTY_ID_FETCHDIRECTION:
1028 rValue <<= getFetchDirection();
1029 break;
1030 case PROPERTY_ID_FETCHSIZE:
1031 rValue <<= getFetchSize();
1032 break;
1033 case PROPERTY_ID_USEBOOKMARKS:
1034 rValue <<= isUsingBookmarks();
1035 break;
1036 case PROPERTY_ID_ESCAPEPROCESSING:
1037 rValue <<= getEscapeProcessing();
1038 break;
1039 default:
1040 OSL_FAIL( "OStatement_Base::getFastPropertyValue: what property?" );
1041 break;
1045 IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
1047 void SAL_CALL OStatement_Base::acquire() throw()
1049 OStatement_BASE::acquire();
1052 void SAL_CALL OStatement_Base::release() throw()
1054 OStatement_BASE::release();
1057 void SAL_CALL OStatement::acquire() throw()
1059 OStatement_BASE2::acquire();
1062 void SAL_CALL OStatement::release() throw()
1064 OStatement_BASE2::release();
1067 OResultSet* OStatement_Base::createResulSet()
1069 return new OResultSet(m_aStatementHandle,this);
1072 Reference< css::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo( )
1074 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1077 SQLUINTEGER OStatement_Base::getCursorProperties(SQLINTEGER _nCursorType, bool bFirst)
1079 SQLUINTEGER nValueLen = 0;
1082 SQLUSMALLINT nAskFor = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1083 if(SQL_CURSOR_KEYSET_DRIVEN == _nCursorType)
1084 nAskFor = bFirst ? SQL_KEYSET_CURSOR_ATTRIBUTES1 : SQL_KEYSET_CURSOR_ATTRIBUTES2;
1085 else if(SQL_CURSOR_STATIC == _nCursorType)
1086 nAskFor = bFirst ? SQL_STATIC_CURSOR_ATTRIBUTES1 : SQL_STATIC_CURSOR_ATTRIBUTES2;
1087 else if(SQL_CURSOR_FORWARD_ONLY == _nCursorType)
1088 nAskFor = bFirst ? SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 : SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1089 else if(SQL_CURSOR_DYNAMIC == _nCursorType)
1090 nAskFor = bFirst ? SQL_DYNAMIC_CURSOR_ATTRIBUTES1 : SQL_DYNAMIC_CURSOR_ATTRIBUTES2;
1093 OTools::GetInfo(getOwnConnection(),getConnectionHandle(),nAskFor,nValueLen,nullptr);
1095 catch(const Exception&)
1096 { // we don't want our result destroy here
1097 nValueLen = 0;
1099 return nValueLen;
1103 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */