update emoji autocorrect entries from po-files
[LibreOffice.git] / connectivity / source / drivers / odbc / OStatement.cxx
blob8f3f8b6b5805f65a7f070f747cd82515e8439c9f
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/extract.hxx>
36 #include <comphelper/types.hxx>
37 #include "diagnose_ex.h"
38 #include <algorithm>
39 #include "resource/common_res.hrc"
40 #include <connectivity/dbexception.hxx>
42 using namespace ::comphelper;
44 #define THROW_SQL(x) \
45 OTools::ThrowException(m_pConnection,x,m_aStatementHandle,SQL_HANDLE_STMT,*this)
49 using namespace connectivity::odbc;
51 using namespace com::sun::star::uno;
52 using namespace com::sun::star::lang;
53 using namespace com::sun::star::beans;
54 using namespace com::sun::star::sdbc;
55 using namespace com::sun::star::sdbcx;
56 using namespace com::sun::star::container;
57 using namespace com::sun::star::io;
58 using namespace com::sun::star::util;
60 OStatement_Base::OStatement_Base(OConnection* _pConnection )
61 :OStatement_BASE(m_aMutex)
62 ,OPropertySetHelper(OStatement_BASE::rBHelper)
63 ,m_pConnection(_pConnection)
64 ,m_aStatementHandle(SQL_NULL_HANDLE)
65 ,m_pRowStatusArray(0)
66 ,rBHelper(OStatement_BASE::rBHelper)
68 osl_atomic_increment( &m_refCount );
69 m_pConnection->acquire();
70 m_aStatementHandle = m_pConnection->createStatementHandle();
72 //setMaxFieldSize(0);
73 // Don't do this. By ODBC spec, "0" is the default for the SQL_ATTR_MAX_LENGTH attribute. We once introduced
74 // this line since an PostgreSQL ODBC driver had a default other than 0. However, current drivers (at least 8.3
75 // and later) have a proper default of 0, so there should be no need anymore.
76 // On the other hand, the NotesSQL driver (IBM's ODBC driver for the Lotus Notes series) wrongly interprets
77 // "0" as "0", whereas the ODBC spec says it should in fact mean "unlimited".
78 // So, removing this line seems to be the best option for now.
79 // If we ever again encounter a ODBC driver which needs this option, then we should introduce a data source
80 // setting for it, instead of unconditionally doing it.
82 osl_atomic_decrement( &m_refCount );
85 OStatement_Base::~OStatement_Base()
87 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
90 void OStatement_Base::disposeResultSet()
92 // free the cursor if alive
93 Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY);
94 if (xComp.is())
95 xComp->dispose();
96 m_xResultSet.clear();
99 void SAL_CALL OStatement_Base::disposing()
101 ::osl::MutexGuard aGuard(m_aMutex);
103 disposeResultSet();
104 ::comphelper::disposeComponent(m_xGeneratedStatement);
106 OSL_ENSURE(m_aStatementHandle,"OStatement_BASE2::disposing: StatementHandle is null!");
107 if (m_pConnection)
109 m_pConnection->freeStatementHandle(m_aStatementHandle);
110 m_pConnection->release();
111 m_pConnection = NULL;
113 OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
115 OStatement_BASE::disposing();
118 void OStatement_BASE2::disposing()
120 ::osl::MutexGuard aGuard(m_aMutex);
122 dispose_ChildImpl();
123 OStatement_Base::disposing();
126 void SAL_CALL OStatement_BASE2::release() throw()
128 relase_ChildImpl();
131 Any SAL_CALL OStatement_Base::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
133 if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() && rType == cppu::UnoType<XGeneratedResultSet>::get())
134 return Any();
135 Any aRet = OStatement_BASE::queryInterface(rType);
136 return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
139 Sequence< Type > SAL_CALL OStatement_Base::getTypes( ) throw(RuntimeException, std::exception)
141 ::cppu::OTypeCollection aTypes( cppu::UnoType<XMultiPropertySet>::get(),
142 cppu::UnoType<XFastPropertySet>::get(),
143 cppu::UnoType<XPropertySet>::get());
144 Sequence< Type > aOldTypes = OStatement_BASE::getTypes();
145 if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() )
147 ::std::remove(aOldTypes.getArray(),aOldTypes.getArray() + aOldTypes.getLength(),
148 cppu::UnoType<XGeneratedResultSet>::get());
149 aOldTypes.realloc(aOldTypes.getLength() - 1);
152 return ::comphelper::concatSequences(aTypes.getTypes(),aOldTypes);
155 Reference< XResultSet > SAL_CALL OStatement_Base::getGeneratedValues( ) throw (SQLException, RuntimeException, std::exception)
157 OSL_ENSURE( m_pConnection && m_pConnection->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!");
158 Reference< XResultSet > xRes;
159 if ( m_pConnection )
161 OUString sStmt = m_pConnection->getTransformedGeneratedStatement(m_sSqlStatement);
162 if ( !sStmt.isEmpty() )
164 ::comphelper::disposeComponent(m_xGeneratedStatement);
165 m_xGeneratedStatement = m_pConnection->createStatement();
166 xRes = m_xGeneratedStatement->executeQuery(sStmt);
169 return xRes;
172 void SAL_CALL OStatement_Base::cancel( ) throw(RuntimeException, std::exception)
174 ::osl::MutexGuard aGuard( m_aMutex );
175 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
177 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
178 N3SQLCancel(m_aStatementHandle);
182 void SAL_CALL OStatement_Base::close( ) throw(SQLException, RuntimeException, std::exception)
185 ::osl::MutexGuard aGuard( m_aMutex );
186 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
189 dispose();
193 void SAL_CALL OStatement::clearBatch( ) throw(SQLException, RuntimeException, std::exception)
198 void OStatement_Base::reset()
199 throw (SQLException, RuntimeException)
201 ::osl::MutexGuard aGuard( m_aMutex );
202 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
205 clearWarnings ();
207 if (m_xResultSet.get().is())
209 clearMyResultSet();
211 if(m_aStatementHandle)
213 THROW_SQL(N3SQLFreeStmt(m_aStatementHandle, SQL_CLOSE));
217 // clearMyResultSet
218 // If a ResultSet was created for this Statement, close it
219 void OStatement_Base::clearMyResultSet()
220 throw (SQLException, RuntimeException)
222 ::osl::MutexGuard aGuard( m_aMutex );
223 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
227 Reference<XCloseable> xCloseable(
228 m_xResultSet.get(), css::uno::UNO_QUERY);
229 if ( xCloseable.is() )
230 xCloseable->close();
232 catch( const DisposedException& ) { }
234 m_xResultSet.clear();
237 SQLLEN OStatement_Base::getRowCount()
238 throw (SQLException, RuntimeException)
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
259 bool OStatement_Base::lockIfNecessary (const OUString& sql) throw (SQLException, RuntimeException)
261 bool rc = false;
263 // First, convert the statement to upper case
265 OUString sqlStatement = sql.toAsciiUpperCase ();
267 // Now, look for the FOR UPDATE keywords. If there is any extra white
268 // space between the FOR and UPDATE, this will fail.
270 sal_Int32 index = sqlStatement.indexOf(" FOR UPDATE");
272 // We found it. Change our concurrency level to ensure that the
273 // row can be updated.
275 if (index > 0)
277 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
280 THROW_SQL((setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, SQL_CONCUR_LOCK)));
282 catch (const SQLWarning& warn)
284 // Catch any warnings and place on the warning stack
285 setWarning (warn);
287 rc = true;
290 return rc;
293 // setWarning
294 // Sets the warning
297 void OStatement_Base::setWarning (const SQLWarning &ex)
298 throw (SQLException, RuntimeException)
300 ::osl::MutexGuard aGuard( m_aMutex );
301 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
304 m_aLastWarning = ex;
308 // getColumnCount
309 // Return the number of columns in the ResultSet
310 sal_Int32 OStatement_Base::getColumnCount()
311 throw (SQLException, RuntimeException)
313 ::osl::MutexGuard aGuard( m_aMutex );
314 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
317 sal_Int16 numCols = 0;
318 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
320 try {
321 THROW_SQL(N3SQLNumResultCols(m_aStatementHandle,&numCols));
323 catch (const SQLException&)
326 return numCols;
330 sal_Bool SAL_CALL OStatement_Base::execute( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
332 ::osl::MutexGuard aGuard( m_aMutex );
333 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
334 m_sSqlStatement = sql;
337 OString aSql(OUStringToOString(sql,getOwnConnection()->getTextEncoding()));
339 bool hasResultSet = false;
340 SQLWarning aWarning;
342 // Reset the statement handle and warning
344 reset();
346 // Check for a 'FOR UPDATE' statement. If present, change
347 // the concurrency to lock
349 lockIfNecessary (sql);
351 // Call SQLExecDirect
352 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
354 try {
355 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aSql.getStr())), aSql.getLength()));
357 catch (const SQLWarning& ex) {
359 // Save pointer to warning and save with ResultSet
360 // object once it is created.
362 aWarning = ex;
365 // Now determine if there is a result set associated with
366 // the SQL statement that was executed. Get the column
367 // count, and if it is not zero, there is a result set.
369 if (getColumnCount () > 0)
371 hasResultSet = true;
374 return hasResultSet;
377 // getResultSet
378 // getResultSet returns the current result as a ResultSet. It
379 // returns NULL if the current result is not a ResultSet.
381 Reference< XResultSet > OStatement_Base::getResultSet(bool checkCount)
382 throw (SQLException, css::uno::RuntimeException)
384 ::osl::MutexGuard aGuard( m_aMutex );
385 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
388 if (m_xResultSet.get().is()) // if resultset already retrieved,
390 // throw exception to avoid sequence error
391 ::dbtools::throwFunctionSequenceException(*this,Any());
394 OResultSet* pRs = NULL;
395 sal_Int32 numCols = 1;
397 // If we already know we have result columns, checkCount
398 // is false. This is an optimization to prevent unneeded
399 // calls to getColumnCount
401 if (checkCount)
402 numCols = getColumnCount ();
404 // Only return a result set if there are result columns
406 if (numCols > 0)
408 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
409 pRs = createResulSet();
410 pRs->construct();
412 // Save a copy of our last result set
413 // Changed to save copy at getResultSet.
414 //m_xResultSet = rs;
416 else
417 clearMyResultSet ();
419 return pRs;
422 // getStmtOption
423 // Invoke SQLGetStmtOption with the given option.
426 template < typename T, SQLINTEGER BufferLength > T OStatement_Base::getStmtOption (SQLINTEGER fOption, T dflt) const
428 T result (dflt);
429 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
430 N3SQLGetStmtAttr(m_aStatementHandle, fOption, &result, BufferLength, NULL);
431 return result;
433 template < typename T, SQLINTEGER BufferLength > SQLRETURN OStatement_Base::setStmtOption (SQLINTEGER fOption, T value) const
435 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
436 SQLPOINTER sv = reinterpret_cast<SQLPOINTER>(value);
437 return N3SQLSetStmtAttr(m_aStatementHandle, fOption, sv, BufferLength);
441 Reference< XResultSet > SAL_CALL OStatement_Base::executeQuery( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
443 ::osl::MutexGuard aGuard( m_aMutex );
444 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
447 Reference< XResultSet > xRS = NULL;
449 // Execute the statement. If execute returns true, a result
450 // set exists.
452 if (execute (sql))
454 xRS = getResultSet (false);
455 m_xResultSet = xRS;
457 else
459 // No ResultSet was produced. Raise an exception
460 m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
462 return xRS;
466 Reference< XConnection > SAL_CALL OStatement_Base::getConnection( ) throw(SQLException, RuntimeException, std::exception)
468 ::osl::MutexGuard aGuard( m_aMutex );
469 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
471 return Reference< XConnection >(m_pConnection);
475 Any SAL_CALL OStatement::queryInterface( const Type & rType ) throw(RuntimeException, std::exception)
477 Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this));
478 return aRet.hasValue() ? aRet : OStatement_Base::queryInterface(rType);
482 void SAL_CALL OStatement::addBatch( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
484 ::osl::MutexGuard aGuard( m_aMutex );
485 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
488 m_aBatchList.push_back(sql);
491 Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch( ) throw(SQLException, RuntimeException, std::exception)
493 ::osl::MutexGuard aGuard( m_aMutex );
494 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
497 OString aBatchSql;
498 sal_Int32 nLen = 0;
499 for(::std::list< OUString>::const_iterator i=m_aBatchList.begin();i != m_aBatchList.end();++i,++nLen)
501 aBatchSql += OUStringToOString(*i,getOwnConnection()->getTextEncoding());
502 aBatchSql += ";";
505 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
506 THROW_SQL(N3SQLExecDirect(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aBatchSql.getStr())), aBatchSql.getLength()));
508 Sequence< sal_Int32 > aRet(nLen);
509 sal_Int32* pArray = aRet.getArray();
510 for(sal_Int32 j=0;j<nLen;++j)
512 SQLRETURN nError = N3SQLMoreResults(m_aStatementHandle);
513 if(nError == SQL_SUCCESS)
515 SQLLEN nRowCount=0;
516 N3SQLRowCount(m_aStatementHandle,&nRowCount);
517 pArray[j] = nRowCount;
520 return aRet;
525 sal_Int32 SAL_CALL OStatement_Base::executeUpdate( const OUString& sql ) throw(SQLException, RuntimeException, std::exception)
527 ::osl::MutexGuard aGuard( m_aMutex );
528 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
531 sal_Int32 numRows = -1;
533 // Execute the statement. If execute returns false, a
534 // row count exists.
536 if (!execute (sql)) {
537 numRows = getUpdateCount();
539 else {
541 // No update count was produced (a ResultSet was). Raise
542 // an exception
544 ::connectivity::SharedResources aResources;
545 const OUString sError( aResources.getResourceString(STR_NO_ROWCOUNT));
546 throw SQLException (sError, *this,OUString(),0,Any());
548 return numRows;
553 Reference< XResultSet > SAL_CALL OStatement_Base::getResultSet( ) throw(SQLException, RuntimeException, std::exception)
555 ::osl::MutexGuard aGuard( m_aMutex );
556 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
559 m_xResultSet = getResultSet(true);
560 return m_xResultSet;
564 sal_Int32 SAL_CALL OStatement_Base::getUpdateCount( ) throw(SQLException, RuntimeException, std::exception)
566 ::osl::MutexGuard aGuard( m_aMutex );
567 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
570 sal_Int32 rowCount = -1;
572 // Only return a row count for SQL statements that did not
573 // return a result set.
575 if (getColumnCount () == 0)
576 rowCount = getRowCount ();
578 return rowCount;
582 sal_Bool SAL_CALL OStatement_Base::getMoreResults( ) throw(SQLException, RuntimeException, std::exception)
584 ::osl::MutexGuard aGuard( m_aMutex );
585 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
588 SQLWarning warning;
589 bool hasResultSet = false;
591 // clear previous warnings
593 clearWarnings ();
595 // Call SQLMoreResults
596 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
598 try {
599 hasResultSet = N3SQLMoreResults(m_aStatementHandle) == SQL_SUCCESS;
601 catch (const SQLWarning &ex) {
603 // Save pointer to warning and save with ResultSet
604 // object once it is created.
606 warning = ex;
609 // There are more results (it may not be a result set, though)
611 if (hasResultSet)
614 // Now determine if there is a result set associated
615 // with the SQL statement that was executed. Get the
616 // column count, and if it is zero, there is not a
617 // result set.
619 if (getColumnCount () == 0)
620 hasResultSet = false;
623 // Set the warning for the statement, if one was generated
625 setWarning (warning);
627 // Return the result set indicator
629 return hasResultSet;
634 Any SAL_CALL OStatement_Base::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
636 ::osl::MutexGuard aGuard( m_aMutex );
637 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
640 return makeAny(m_aLastWarning);
645 void SAL_CALL OStatement_Base::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
647 ::osl::MutexGuard aGuard( m_aMutex );
648 checkDisposed(OStatement_BASE::rBHelper.bDisposed);
651 m_aLastWarning = SQLWarning();
655 sal_Int64 OStatement_Base::getQueryTimeOut() const
657 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT);
660 sal_Int64 OStatement_Base::getMaxRows() const
662 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS);
665 sal_Int32 OStatement_Base::getResultSetConcurrency() const
667 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
668 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY));
669 if(nValue == SQL_CONCUR_READ_ONLY)
670 nValue = ResultSetConcurrency::READ_ONLY;
671 else
672 nValue = ResultSetConcurrency::UPDATABLE;
673 return nValue;
676 sal_Int32 OStatement_Base::getResultSetType() const
678 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
679 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_FORWARD_ONLY));
680 switch(nValue)
682 case SQL_CURSOR_FORWARD_ONLY:
683 nValue = ResultSetType::FORWARD_ONLY;
684 break;
685 case SQL_CURSOR_KEYSET_DRIVEN:
686 case SQL_CURSOR_STATIC:
687 nValue = ResultSetType::SCROLL_INSENSITIVE;
688 break;
689 case SQL_CURSOR_DYNAMIC:
690 nValue = ResultSetType::SCROLL_SENSITIVE;
691 break;
692 default:
693 OSL_FAIL("Unknown ODBC Cursor Type");
696 return nValue;
699 sal_Int32 OStatement_Base::getFetchDirection() const
701 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
702 SQLULEN nValue (getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE));
703 switch(nValue)
705 case SQL_SCROLLABLE:
706 nValue = FetchDirection::REVERSE;
707 break;
708 default:
709 nValue = FetchDirection::FORWARD;
710 break;
713 return nValue;
716 sal_Int32 OStatement_Base::getFetchSize() const
718 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
719 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE);
722 sal_Int64 OStatement_Base::getMaxFieldSize() const
724 return getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH);
727 OUString OStatement_Base::getCursorName() const
729 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
730 SQLCHAR pName[258];
731 SQLSMALLINT nRealLen = 0;
732 SQLRETURN nRetCode = N3SQLGetCursorName(m_aStatementHandle,(SQLCHAR*)pName,256,&nRealLen);
733 OSL_UNUSED( nRetCode );
734 return OUString::createFromAscii(reinterpret_cast<char*>(pName));
737 void OStatement_Base::setQueryTimeOut(sal_Int64 seconds)
739 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
740 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_QUERY_TIMEOUT,seconds);
743 void OStatement_Base::setMaxRows(sal_Int64 _par0)
745 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
746 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_ROWS, _par0);
749 void OStatement_Base::setResultSetConcurrency(sal_Int32 _par0)
751 SQLULEN nSet;
752 if(_par0 == ResultSetConcurrency::READ_ONLY)
753 nSet = SQL_CONCUR_READ_ONLY;
754 else
755 nSet = SQL_CONCUR_VALUES;
757 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
758 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CONCURRENCY, nSet);
761 void OStatement_Base::setResultSetType(sal_Int32 _par0)
764 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
765 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN);
767 bool bUseBookmark = isUsingBookmarks();
768 SQLULEN nSet( SQL_UNSPECIFIED );
769 switch(_par0)
771 case ResultSetType::FORWARD_ONLY:
772 nSet = SQL_UNSPECIFIED;
773 break;
774 case ResultSetType::SCROLL_INSENSITIVE:
775 nSet = SQL_INSENSITIVE;
776 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
777 break;
778 case ResultSetType::SCROLL_SENSITIVE:
779 if(bUseBookmark)
781 SQLUINTEGER nCurProp = getCursorProperties(SQL_CURSOR_DYNAMIC,true);
782 if((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK) // check if bookmark for this type isn't supported
783 { // we have to test the next one
784 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,true);
785 bool bNotBookmarks = ((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK);
786 nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,false);
787 nSet = SQL_CURSOR_KEYSET_DRIVEN;
788 if( bNotBookmarks ||
789 ((nCurProp & SQL_CA2_SENSITIVITY_DELETIONS) != SQL_CA2_SENSITIVITY_DELETIONS) ||
790 ((nCurProp & SQL_CA2_SENSITIVITY_ADDITIONS) != SQL_CA2_SENSITIVITY_ADDITIONS))
792 // bookmarks for keyset isn't supported so reset bookmark setting
793 setUsingBookmarks(false);
794 nSet = SQL_CURSOR_DYNAMIC;
797 else
798 nSet = SQL_CURSOR_DYNAMIC;
800 else
801 nSet = SQL_CURSOR_DYNAMIC;
802 if( setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, nSet) != SQL_SUCCESS )
804 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_TYPE, SQL_CURSOR_KEYSET_DRIVEN);
806 nSet = SQL_SENSITIVE;
807 break;
808 default:
809 OSL_FAIL( "OStatement_Base::setResultSetType: invalid result set type!" );
810 break;
814 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SENSITIVITY, nSet);
817 void OStatement_Base::setEscapeProcessing( const bool _bEscapeProc )
819 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
820 SQLULEN nEscapeProc( _bEscapeProc ? SQL_NOSCAN_OFF : SQL_NOSCAN_ON );
821 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_NOSCAN, nEscapeProc);
825 void OStatement_Base::setFetchDirection(sal_Int32 _par0)
827 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
828 if(_par0 == FetchDirection::FORWARD)
830 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_NONSCROLLABLE);
832 else if(_par0 == FetchDirection::REVERSE)
834 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_CURSOR_SCROLLABLE, SQL_SCROLLABLE);
838 void OStatement_Base::setFetchSize(sal_Int32 _par0)
840 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
841 OSL_ENSURE(_par0>0,"Illegal fetch size!");
842 if ( _par0 > 0 )
844 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_ROW_ARRAY_SIZE, _par0);
846 if (m_pRowStatusArray)
847 delete[] m_pRowStatusArray;
848 m_pRowStatusArray = new SQLUSMALLINT[_par0];
849 setStmtOption<SQLUSMALLINT*, SQL_IS_POINTER>(SQL_ATTR_ROW_STATUS_PTR, m_pRowStatusArray);
853 void OStatement_Base::setMaxFieldSize(sal_Int64 _par0)
855 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
856 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_MAX_LENGTH, _par0);
859 void OStatement_Base::setCursorName(const OUString &_par0)
861 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
862 OString aName(OUStringToOString(_par0,getOwnConnection()->getTextEncoding()));
863 N3SQLSetCursorName(m_aStatementHandle, reinterpret_cast<SDB_ODBC_CHAR *>(const_cast<char *>(aName.getStr())), (SQLSMALLINT)aName.getLength());
866 bool OStatement_Base::isUsingBookmarks() const
868 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
869 return SQL_UB_OFF != getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, SQL_UB_OFF);
872 bool OStatement_Base::getEscapeProcessing() const
874 OSL_ENSURE( m_aStatementHandle, "StatementHandle is null!" );
875 return SQL_NOSCAN_OFF == getStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, SQL_NOSCAN_OFF);;
878 void OStatement_Base::setUsingBookmarks(bool _bUseBookmark)
880 OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
881 SQLULEN nValue = _bUseBookmark ? SQL_UB_VARIABLE : SQL_UB_OFF;
882 setStmtOption<SQLULEN, SQL_IS_UINTEGER>(SQL_ATTR_USE_BOOKMARKS, nValue);
885 ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const
887 Sequence< Property > aProps(10);
888 Property* pProperties = aProps.getArray();
889 sal_Int32 nPos = 0;
890 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME),
891 PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0);
892 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING),
893 PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0);
894 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION),
895 PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0);
896 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE),
897 PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0);
898 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE),
899 PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0);
900 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS),
901 PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0);
902 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT),
903 PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0);
904 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY),
905 PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0);
906 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE),
907 PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0);
908 pProperties[nPos++] = ::com::sun::star::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS),
909 PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0);
911 return new ::cppu::OPropertyArrayHelper(aProps);
915 ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper()
917 return *getArrayHelper();
920 sal_Bool OStatement_Base::convertFastPropertyValue(
921 Any & rConvertedValue,
922 Any & rOldValue,
923 sal_Int32 nHandle,
924 const Any& rValue )
925 throw (::com::sun::star::lang::IllegalArgumentException)
927 bool bConverted = false;
930 switch(nHandle)
932 case PROPERTY_ID_QUERYTIMEOUT:
933 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getQueryTimeOut());
934 break;
936 case PROPERTY_ID_MAXFIELDSIZE:
937 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxFieldSize());
938 break;
940 case PROPERTY_ID_MAXROWS:
941 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxRows());
942 break;
944 case PROPERTY_ID_CURSORNAME:
945 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getCursorName());
946 break;
948 case PROPERTY_ID_RESULTSETCONCURRENCY:
949 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetConcurrency());
950 break;
952 case PROPERTY_ID_RESULTSETTYPE:
953 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetType());
954 break;
956 case PROPERTY_ID_FETCHDIRECTION:
957 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
958 break;
960 case PROPERTY_ID_FETCHSIZE:
961 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
962 break;
964 case PROPERTY_ID_USEBOOKMARKS:
965 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, isUsingBookmarks());
966 break;
968 case PROPERTY_ID_ESCAPEPROCESSING:
969 bConverted = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, getEscapeProcessing() );
970 break;
974 catch(const SQLException&)
976 // throw Exception(e.Message,*this);
978 return bConverted;
981 void OStatement_Base::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception, std::exception)
985 switch(nHandle)
987 case PROPERTY_ID_QUERYTIMEOUT:
988 setQueryTimeOut(comphelper::getINT64(rValue));
989 break;
990 case PROPERTY_ID_MAXFIELDSIZE:
991 setMaxFieldSize(comphelper::getINT64(rValue));
992 break;
993 case PROPERTY_ID_MAXROWS:
994 setMaxRows(comphelper::getINT64(rValue));
995 break;
996 case PROPERTY_ID_CURSORNAME:
997 setCursorName(comphelper::getString(rValue));
998 break;
999 case PROPERTY_ID_RESULTSETCONCURRENCY:
1000 setResultSetConcurrency(comphelper::getINT32(rValue));
1001 break;
1002 case PROPERTY_ID_RESULTSETTYPE:
1003 setResultSetType(comphelper::getINT32(rValue));
1004 break;
1005 case PROPERTY_ID_FETCHDIRECTION:
1006 setFetchDirection(comphelper::getINT32(rValue));
1007 break;
1008 case PROPERTY_ID_FETCHSIZE:
1009 setFetchSize(comphelper::getINT32(rValue));
1010 break;
1011 case PROPERTY_ID_USEBOOKMARKS:
1012 setUsingBookmarks(comphelper::getBOOL(rValue));
1013 break;
1014 case PROPERTY_ID_ESCAPEPROCESSING:
1015 setEscapeProcessing( ::comphelper::getBOOL( rValue ) );
1016 break;
1017 default:
1018 OSL_FAIL( "OStatement_Base::setFastPropertyValue_NoBroadcast: what property?" );
1019 break;
1022 catch(const SQLException& )
1024 // throw Exception(e.Message,*this);
1028 void OStatement_Base::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
1030 switch(nHandle)
1032 case PROPERTY_ID_QUERYTIMEOUT:
1033 rValue <<= getQueryTimeOut();
1034 break;
1035 case PROPERTY_ID_MAXFIELDSIZE:
1036 rValue <<= getMaxFieldSize();
1037 break;
1038 case PROPERTY_ID_MAXROWS:
1039 rValue <<= getMaxRows();
1040 break;
1041 case PROPERTY_ID_CURSORNAME:
1042 rValue <<= getCursorName();
1043 break;
1044 case PROPERTY_ID_RESULTSETCONCURRENCY:
1045 rValue <<= getResultSetConcurrency();
1046 break;
1047 case PROPERTY_ID_RESULTSETTYPE:
1048 rValue <<= getResultSetType();
1049 break;
1050 case PROPERTY_ID_FETCHDIRECTION:
1051 rValue <<= getFetchDirection();
1052 break;
1053 case PROPERTY_ID_FETCHSIZE:
1054 rValue <<= getFetchSize();
1055 break;
1056 case PROPERTY_ID_USEBOOKMARKS:
1057 rValue <<= isUsingBookmarks();
1058 break;
1059 case PROPERTY_ID_ESCAPEPROCESSING:
1060 rValue <<= getEscapeProcessing();
1061 break;
1062 default:
1063 OSL_FAIL( "OStatement_Base::getFastPropertyValue: what property?" );
1064 break;
1068 IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
1070 void SAL_CALL OStatement_Base::acquire() throw()
1072 OStatement_BASE::acquire();
1075 void SAL_CALL OStatement_Base::release() throw()
1077 OStatement_BASE::release();
1080 void SAL_CALL OStatement::acquire() throw()
1082 OStatement_BASE2::acquire();
1085 void SAL_CALL OStatement::release() throw()
1087 OStatement_BASE2::release();
1090 OResultSet* OStatement_Base::createResulSet()
1092 return new OResultSet(m_aStatementHandle,this);
1095 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo( ) throw(RuntimeException, std::exception)
1097 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1100 SQLUINTEGER OStatement_Base::getCursorProperties(SQLINTEGER _nCursorType, bool bFirst)
1102 SQLUINTEGER nValueLen = 0;
1105 SQLUSMALLINT nAskFor = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1106 if(SQL_CURSOR_KEYSET_DRIVEN == _nCursorType)
1107 nAskFor = bFirst ? SQL_KEYSET_CURSOR_ATTRIBUTES1 : SQL_KEYSET_CURSOR_ATTRIBUTES2;
1108 else if(SQL_CURSOR_STATIC == _nCursorType)
1109 nAskFor = bFirst ? SQL_STATIC_CURSOR_ATTRIBUTES1 : SQL_STATIC_CURSOR_ATTRIBUTES2;
1110 else if(SQL_CURSOR_FORWARD_ONLY == _nCursorType)
1111 nAskFor = bFirst ? SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 : SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1112 else if(SQL_CURSOR_DYNAMIC == _nCursorType)
1113 nAskFor = bFirst ? SQL_DYNAMIC_CURSOR_ATTRIBUTES1 : SQL_DYNAMIC_CURSOR_ATTRIBUTES2;
1116 OTools::GetInfo(getOwnConnection(),getConnectionHandle(),nAskFor,nValueLen,NULL);
1118 catch(const Exception&)
1119 { // we don't want our result destroy here
1120 nValueLen = 0;
1122 return nValueLen;
1126 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */