1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: OStatement.cxx,v $
10 * $Revision: 1.40.56.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
35 #include <osl/diagnose.h>
36 #include "odbc/OStatement.hxx"
37 #include "odbc/OConnection.hxx"
38 #include "odbc/OResultSet.hxx"
39 #include <comphelper/property.hxx>
40 #include "odbc/OTools.hxx"
41 #include <comphelper/uno3.hxx>
42 #include <osl/thread.h>
43 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
44 #include <com/sun/star/sdbc/ResultSetType.hpp>
45 #include <com/sun/star/sdbc/FetchDirection.hpp>
46 #include <com/sun/star/lang/DisposedException.hpp>
47 #include <comphelper/sequence.hxx>
48 #include <cppuhelper/typeprovider.hxx>
49 #include <comphelper/extract.hxx>
50 #include <comphelper/types.hxx>
51 #include "diagnose_ex.h"
53 #include "resource/common_res.hrc"
54 #include "connectivity/dbexception.hxx"
56 using namespace ::comphelper
;
58 #define THROW_SQL(x) \
59 OTools::ThrowException(m_pConnection,x,m_aStatementHandle,SQL_HANDLE_STMT,*this)
61 #if OSL_DEBUG_LEVEL > 1
65 THROW_SQL(nRetCode); \
67 catch(SQLException&) \
69 OSL_ENSURE(0,"Exception in odbc catched"); \
75 using namespace connectivity::odbc
;
76 //------------------------------------------------------------------------------
77 using namespace com::sun::star::uno
;
78 using namespace com::sun::star::lang
;
79 using namespace com::sun::star::beans
;
80 using namespace com::sun::star::sdbc
;
81 using namespace com::sun::star::sdbcx
;
82 using namespace com::sun::star::container
;
83 using namespace com::sun::star::io
;
84 using namespace com::sun::star::util
;
85 //------------------------------------------------------------------------------
86 OStatement_Base::OStatement_Base(OConnection
* _pConnection
)
87 :OStatement_BASE(m_aMutex
)
88 ,OPropertySetHelper(OStatement_BASE::rBHelper
)
89 ,m_pConnection(_pConnection
)
90 ,m_aStatementHandle(SQL_NULL_HANDLE
)
92 ,rBHelper(OStatement_BASE::rBHelper
)
94 osl_incrementInterlockedCount( &m_refCount
);
95 m_pConnection
->acquire();
96 m_aStatementHandle
= m_pConnection
->createStatementHandle();
99 // Don't do this. By ODBC spec, "0" is the default for the SQL_ATTR_MAX_LENGTH attribute. We once introduced
100 // this line since an PostgreSQL ODBC driver had a default other than 0. However, current drivers (at least 8.3
101 // and later) have a proper default of 0, so there should be no need anymore.
102 // On the other hand, the NotesSQL driver (IBM's ODBC driver for the Lotus Notes series) wrongly interprets
103 // "0" as "0", whereas the ODBC spec says it should in fact mean "unlimited".
104 // So, removing this line seems to be the best option for now.
105 // If we ever again encounter a ODBC driver which needs this option, then we should introduce a data source
106 // setting for it, instead of unconditionally doing it.
108 osl_decrementInterlockedCount( &m_refCount
);
110 // -----------------------------------------------------------------------------
111 OStatement_Base::~OStatement_Base()
113 OSL_ENSURE(!m_aStatementHandle
,"Sohould ne null here!");
115 //------------------------------------------------------------------------------
116 void OStatement_Base::disposeResultSet()
118 // free the cursor if alive
119 Reference
< XComponent
> xComp(m_xResultSet
.get(), UNO_QUERY
);
122 m_xResultSet
= Reference
< XResultSet
>();
124 // -----------------------------------------------------------------------------
125 void SAL_CALL
OStatement_Base::disposing(void)
127 ::osl::MutexGuard
aGuard(m_aMutex
);
130 ::comphelper::disposeComponent(m_xGeneratedStatement
);
132 OSL_ENSURE(m_aStatementHandle
,"OStatement_BASE2::disposing: StatementHandle is null!");
135 m_pConnection
->freeStatementHandle(m_aStatementHandle
);
136 m_pConnection
->release();
137 m_pConnection
= NULL
;
139 OSL_ENSURE(!m_aStatementHandle
,"Sohould ne null here!");
141 OStatement_BASE::disposing();
143 //------------------------------------------------------------------------------
144 void OStatement_BASE2::disposing()
146 ::osl::MutexGuard
aGuard(m_aMutex
);
149 OStatement_Base::disposing();
151 //-----------------------------------------------------------------------------
152 void SAL_CALL
OStatement_BASE2::release() throw()
156 //-----------------------------------------------------------------------------
157 Any SAL_CALL
OStatement_Base::queryInterface( const Type
& rType
) throw(RuntimeException
)
159 if ( m_pConnection
&& !m_pConnection
->isAutoRetrievingEnabled() && rType
== ::getCppuType( (const Reference
< XGeneratedResultSet
> *)0 ) )
161 Any aRet
= OStatement_BASE::queryInterface(rType
);
162 return aRet
.hasValue() ? aRet
: OPropertySetHelper::queryInterface(rType
);
164 // -------------------------------------------------------------------------
165 Sequence
< Type
> SAL_CALL
OStatement_Base::getTypes( ) throw(RuntimeException
)
167 ::cppu::OTypeCollection
aTypes( ::getCppuType( (const Reference
< XMultiPropertySet
> *)0 ),
168 ::getCppuType( (const Reference
< XFastPropertySet
> *)0 ),
169 ::getCppuType( (const Reference
< XPropertySet
> *)0 ));
170 Sequence
< Type
> aOldTypes
= OStatement_BASE::getTypes();
171 if ( m_pConnection
&& !m_pConnection
->isAutoRetrievingEnabled() )
173 ::std::remove(aOldTypes
.getArray(),aOldTypes
.getArray() + aOldTypes
.getLength(),
174 ::getCppuType( (const Reference
< XGeneratedResultSet
> *)0 ));
175 aOldTypes
.realloc(aOldTypes
.getLength() - 1);
178 return ::comphelper::concatSequences(aTypes
.getTypes(),aOldTypes
);
180 // -------------------------------------------------------------------------
181 Reference
< XResultSet
> SAL_CALL
OStatement_Base::getGeneratedValues( ) throw (SQLException
, RuntimeException
)
183 OSL_ENSURE( m_pConnection
&& m_pConnection
->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!");
184 Reference
< XResultSet
> xRes
;
187 ::rtl::OUString sStmt
= m_pConnection
->getTransformedGeneratedStatement(m_sSqlStatement
);
188 if ( sStmt
.getLength() )
190 ::comphelper::disposeComponent(m_xGeneratedStatement
);
191 m_xGeneratedStatement
= m_pConnection
->createStatement();
192 xRes
= m_xGeneratedStatement
->executeQuery(sStmt
);
197 // -----------------------------------------------------------------------------
198 void SAL_CALL
OStatement_Base::cancel( ) throw(RuntimeException
)
200 ::osl::MutexGuard
aGuard( m_aMutex
);
201 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
203 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
204 OTools::ThrowException(m_pConnection
,N3SQLCancel(m_aStatementHandle
),m_aStatementHandle
,SQL_HANDLE_STMT
,*this);
206 // -------------------------------------------------------------------------
208 void SAL_CALL
OStatement_Base::close( ) throw(SQLException
, RuntimeException
)
211 ::osl::MutexGuard
aGuard( m_aMutex
);
212 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
217 // -------------------------------------------------------------------------
219 void SAL_CALL
OStatement::clearBatch( ) throw(SQLException
, RuntimeException
)
223 // -------------------------------------------------------------------------
225 void OStatement_Base::reset() throw (SQLException
)
227 ::osl::MutexGuard
aGuard( m_aMutex
);
228 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
233 if (m_xResultSet
.get().is())
237 if(m_aStatementHandle
)
239 THROW_SQL(N3SQLFreeStmt(m_aStatementHandle
, SQL_CLOSE
));
242 //--------------------------------------------------------------------
244 // If a ResultSet was created for this Statement, close it
245 //--------------------------------------------------------------------
247 void OStatement_Base::clearMyResultSet () throw (SQLException
)
249 ::osl::MutexGuard
aGuard( m_aMutex
);
250 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
254 Reference
<XCloseable
> xCloseable
;
255 if ( ::comphelper::query_interface( m_xResultSet
.get(), xCloseable
) )
258 catch( const DisposedException
& ) { }
260 m_xResultSet
= Reference
< XResultSet
>();
262 //--------------------------------------------------------------------
263 SQLLEN
OStatement_Base::getRowCount () throw( SQLException
)
265 ::osl::MutexGuard
aGuard( m_aMutex
);
266 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
272 THROW_SQL(N3SQLRowCount(m_aStatementHandle
,&numRows
));
274 catch (SQLException
&)
279 //--------------------------------------------------------------------
281 // If the given SQL statement contains a 'FOR UPDATE' clause, change
282 // the concurrency to lock so that the row can then be updated. Returns
283 // true if the concurrency has been changed
284 //--------------------------------------------------------------------
286 sal_Bool
OStatement_Base::lockIfNecessary (const ::rtl::OUString
& sql
) throw( SQLException
)
288 sal_Bool rc
= sal_False
;
290 // First, convert the statement to upper case
292 ::rtl::OUString sqlStatement
= sql
.toAsciiUpperCase ();
294 // Now, look for the FOR UPDATE keywords. If there is any extra white
295 // space between the FOR and UPDATE, this will fail.
297 sal_Int32 index
= sqlStatement
.indexOf(::rtl::OUString::createFromAscii(" FOR UPDATE"));
299 // We found it. Change our concurrency level to ensure that the
300 // row can be updated.
304 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
307 SQLINTEGER nLock
= SQL_CONCUR_LOCK
;
308 THROW_SQL(N3SQLSetStmtAttr(m_aStatementHandle
, SQL_CONCURRENCY
,(SQLPOINTER
)nLock
,SQL_IS_UINTEGER
));
310 catch (SQLWarning
& warn
)
312 // Catch any warnings and place on the warning stack
320 //--------------------------------------------------------------------
323 //--------------------------------------------------------------------
325 void OStatement_Base::setWarning (const SQLWarning
&ex
) throw( SQLException
)
327 ::osl::MutexGuard
aGuard( m_aMutex
);
328 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
334 //--------------------------------------------------------------------
336 // Return the number of columns in the ResultSet
337 //--------------------------------------------------------------------
339 sal_Int32
OStatement_Base::getColumnCount () throw( SQLException
)
341 ::osl::MutexGuard
aGuard( m_aMutex
);
342 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
345 sal_Int16 numCols
= 0;
346 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
349 THROW_SQL(N3SQLNumResultCols(m_aStatementHandle
,&numCols
));
351 catch (SQLException
&)
356 // -------------------------------------------------------------------------
358 sal_Bool SAL_CALL
OStatement_Base::execute( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
360 ::osl::MutexGuard
aGuard( m_aMutex
);
361 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
362 m_sSqlStatement
= sql
;
365 ::rtl::OString
aSql(::rtl::OUStringToOString(sql
,getOwnConnection()->getTextEncoding()));
367 sal_Bool hasResultSet
= sal_False
;
370 // Reset the statement handle and warning
374 // Check for a 'FOR UPDATE' statement. If present, change
375 // the concurrency to lock
377 lockIfNecessary (sql
);
379 // Call SQLExecDirect
380 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
383 THROW_SQL(N3SQLExecDirect(m_aStatementHandle
, (SDB_ODBC_CHAR
*)aSql
.getStr(),aSql
.getLength()));
385 catch (SQLWarning
& ex
) {
387 // Save pointer to warning and save with ResultSet
388 // object once it is created.
393 // Now determine if there is a result set associated with
394 // the SQL statement that was executed. Get the column
395 // count, and if it is not zero, there is a result set.
397 if (getColumnCount () > 0)
399 hasResultSet
= sal_True
;
404 //--------------------------------------------------------------------
406 // getResultSet returns the current result as a ResultSet. It
407 // returns NULL if the current result is not a ResultSet.
408 //--------------------------------------------------------------------
409 Reference
< XResultSet
> OStatement_Base::getResultSet (sal_Bool checkCount
) throw( SQLException
)
411 ::osl::MutexGuard
aGuard( m_aMutex
);
412 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
415 if (m_xResultSet
.get().is()) // if resultset already retrieved,
417 // throw exception to avoid sequence error
418 ::dbtools::throwFunctionSequenceException(*this,Any());
421 OResultSet
* pRs
= NULL
;
422 sal_Int32 numCols
= 1;
424 // If we already know we have result columns, checkCount
425 // is false. This is an optimization to prevent unneeded
426 // calls to getColumnCount
429 numCols
= getColumnCount ();
431 // Only return a result set if there are result columns
435 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
436 pRs
= createResulSet();
439 // Save a copy of our last result set
440 // Changed to save copy at getResultSet.
448 //--------------------------------------------------------------------
450 // Invoke SQLGetStmtOption with the given option.
451 //--------------------------------------------------------------------
453 sal_Int32
OStatement_Base::getStmtOption (short fOption
) const
455 sal_Int32 result
= 0;
456 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
457 N3SQLGetStmtAttr(m_aStatementHandle
, fOption
,&result
,SQL_IS_INTEGER
,NULL
);
460 // -------------------------------------------------------------------------
462 Reference
< XResultSet
> SAL_CALL
OStatement_Base::executeQuery( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
464 ::osl::MutexGuard
aGuard( m_aMutex
);
465 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
468 Reference
< XResultSet
> xRS
= NULL
;
470 // Execute the statement. If execute returns true, a result
475 xRS
= getResultSet (sal_False
);
480 // No ResultSet was produced. Raise an exception
481 m_pConnection
->throwGenericSQLException(STR_NO_RESULTSET
,*this);
485 // -------------------------------------------------------------------------
487 Reference
< XConnection
> SAL_CALL
OStatement_Base::getConnection( ) throw(SQLException
, RuntimeException
)
489 ::osl::MutexGuard
aGuard( m_aMutex
);
490 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
492 return (Reference
< XConnection
>)m_pConnection
;
494 // -------------------------------------------------------------------------
496 Any SAL_CALL
OStatement::queryInterface( const Type
& rType
) throw(RuntimeException
)
498 Any aRet
= ::cppu::queryInterface(rType
,static_cast< XBatchExecution
*> (this));
499 return aRet
.hasValue() ? aRet
: OStatement_Base::queryInterface(rType
);
501 // -------------------------------------------------------------------------
503 void SAL_CALL
OStatement::addBatch( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
505 ::osl::MutexGuard
aGuard( m_aMutex
);
506 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
509 m_aBatchList
.push_back(sql
);
511 // -------------------------------------------------------------------------
512 Sequence
< sal_Int32
> SAL_CALL
OStatement::executeBatch( ) throw(SQLException
, RuntimeException
)
514 ::osl::MutexGuard
aGuard( m_aMutex
);
515 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
518 ::rtl::OString aBatchSql
;
520 for(::std::list
< ::rtl::OUString
>::const_iterator i
=m_aBatchList
.begin();i
!= m_aBatchList
.end();++i
,++nLen
)
522 aBatchSql
+= ::rtl::OUStringToOString(*i
,getOwnConnection()->getTextEncoding());
526 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
527 THROW_SQL(N3SQLExecDirect(m_aStatementHandle
, (SDB_ODBC_CHAR
*)aBatchSql
.getStr(),aBatchSql
.getLength()));
529 Sequence
< sal_Int32
> aRet(nLen
);
530 sal_Int32
* pArray
= aRet
.getArray();
531 for(sal_Int32 j
=0;j
<nLen
;++j
)
533 SQLRETURN nError
= N3SQLMoreResults(m_aStatementHandle
);
534 if(nError
== SQL_SUCCESS
)
537 N3SQLRowCount(m_aStatementHandle
,&nRowCount
);
538 pArray
[j
] = nRowCount
;
543 // -------------------------------------------------------------------------
546 sal_Int32 SAL_CALL
OStatement_Base::executeUpdate( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
548 ::osl::MutexGuard
aGuard( m_aMutex
);
549 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
552 sal_Int32 numRows
= -1;
554 // Execute the statement. If execute returns false, a
557 if (!execute (sql
)) {
558 numRows
= getUpdateCount();
562 // No update count was produced (a ResultSet was). Raise
565 ::connectivity::SharedResources aResources
;
566 const ::rtl::OUString
sError( aResources
.getResourceString(STR_NO_ROWCOUNT
));
567 throw SQLException (sError
, *this,::rtl::OUString(),0,Any());
572 // -------------------------------------------------------------------------
574 Reference
< XResultSet
> SAL_CALL
OStatement_Base::getResultSet( ) throw(SQLException
, RuntimeException
)
576 ::osl::MutexGuard
aGuard( m_aMutex
);
577 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
580 m_xResultSet
= getResultSet(sal_True
);
583 // -------------------------------------------------------------------------
585 sal_Int32 SAL_CALL
OStatement_Base::getUpdateCount( ) throw(SQLException
, RuntimeException
)
587 ::osl::MutexGuard
aGuard( m_aMutex
);
588 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
591 sal_Int32 rowCount
= -1;
593 // Only return a row count for SQL statements that did not
594 // return a result set.
596 if (getColumnCount () == 0)
597 rowCount
= getRowCount ();
601 // -------------------------------------------------------------------------
603 sal_Bool SAL_CALL
OStatement_Base::getMoreResults( ) throw(SQLException
, RuntimeException
)
605 ::osl::MutexGuard
aGuard( m_aMutex
);
606 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
610 sal_Bool hasResultSet
= sal_False
;
612 // clear previous warnings
616 // Call SQLMoreResults
617 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
620 hasResultSet
= N3SQLMoreResults(m_aStatementHandle
) == SQL_SUCCESS
;
622 catch (SQLWarning
&ex
) {
624 // Save pointer to warning and save with ResultSet
625 // object once it is created.
630 // There are more results (it may not be a result set, though)
635 // Now determine if there is a result set associated
636 // with the SQL statement that was executed. Get the
637 // column count, and if it is zero, there is not a
640 if (getColumnCount () == 0)
641 hasResultSet
= sal_False
;
644 // Set the warning for the statement, if one was generated
646 setWarning (warning
);
648 // Return the result set indicator
652 // -------------------------------------------------------------------------
654 // -------------------------------------------------------------------------
655 Any SAL_CALL
OStatement_Base::getWarnings( ) throw(SQLException
, RuntimeException
)
657 ::osl::MutexGuard
aGuard( m_aMutex
);
658 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
661 return makeAny(m_aLastWarning
);
663 // -------------------------------------------------------------------------
665 // -------------------------------------------------------------------------
666 void SAL_CALL
OStatement_Base::clearWarnings( ) throw(SQLException
, RuntimeException
)
668 ::osl::MutexGuard
aGuard( m_aMutex
);
669 checkDisposed(OStatement_BASE::rBHelper
.bDisposed
);
672 m_aLastWarning
= SQLWarning();
674 // -------------------------------------------------------------------------
675 //------------------------------------------------------------------------------
676 sal_Int32
OStatement_Base::getQueryTimeOut() const
678 return getStmtOption(SQL_ATTR_QUERY_TIMEOUT
);
680 //------------------------------------------------------------------------------
681 sal_Int32
OStatement_Base::getMaxRows() const
683 return getStmtOption(SQL_ATTR_MAX_ROWS
);
685 //------------------------------------------------------------------------------
686 sal_Int32
OStatement_Base::getResultSetConcurrency() const
688 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
690 SQLRETURN nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_CONCURRENCY
,&nValue
,SQL_IS_UINTEGER
,0);
691 OSL_UNUSED( nRetCode
);
692 if(nValue
== SQL_CONCUR_READ_ONLY
)
693 nValue
= ResultSetConcurrency::READ_ONLY
;
695 nValue
= ResultSetConcurrency::UPDATABLE
;
698 //------------------------------------------------------------------------------
699 sal_Int32
OStatement_Base::getResultSetType() const
701 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
702 sal_uInt32 nValue
= SQL_CURSOR_FORWARD_ONLY
;
703 SQLRETURN nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_CURSOR_SENSITIVITY
,&nValue
,SQL_IS_UINTEGER
,0);
704 nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_CURSOR_TYPE
,&nValue
,SQL_IS_UINTEGER
,0);
707 case SQL_CURSOR_FORWARD_ONLY
:
708 nValue
= ResultSetType::FORWARD_ONLY
;
710 case SQL_CURSOR_KEYSET_DRIVEN
:
711 case SQL_CURSOR_STATIC
:
712 nValue
= ResultSetType::SCROLL_INSENSITIVE
;
714 case SQL_CURSOR_DYNAMIC
:
715 nValue
= ResultSetType::SCROLL_SENSITIVE
;
721 //------------------------------------------------------------------------------
722 sal_Int32
OStatement_Base::getFetchDirection() const
724 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
725 sal_uInt32 nValue
= 0;
726 SQLRETURN nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_CURSOR_SCROLLABLE
,&nValue
,SQL_IS_UINTEGER
,0);
727 OSL_UNUSED( nRetCode
);
732 nValue
= FetchDirection::REVERSE
;
735 nValue
= FetchDirection::FORWARD
;
741 //------------------------------------------------------------------------------
742 sal_Int32
OStatement_Base::getFetchSize() const
744 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
746 SQLRETURN nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_ROW_ARRAY_SIZE
,&nValue
,SQL_IS_UINTEGER
,0);
747 OSL_UNUSED( nRetCode
);
750 //------------------------------------------------------------------------------
751 sal_Int32
OStatement_Base::getMaxFieldSize() const
753 return getStmtOption(SQL_ATTR_MAX_LENGTH
);
755 //------------------------------------------------------------------------------
756 ::rtl::OUString
OStatement_Base::getCursorName() const
758 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
760 SQLSMALLINT nRealLen
= 0;
761 SQLRETURN nRetCode
= N3SQLGetCursorName(m_aStatementHandle
,(SQLCHAR
*)pName
,256,&nRealLen
);
762 OSL_UNUSED( nRetCode
);
763 return ::rtl::OUString::createFromAscii((const char*)pName
);
765 //------------------------------------------------------------------------------
766 void OStatement_Base::setQueryTimeOut(sal_Int32 seconds
)
768 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
769 SQLRETURN nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_QUERY_TIMEOUT
,(SQLPOINTER
)seconds
,SQL_IS_UINTEGER
);
770 OSL_UNUSED( nRetCode
);
772 //------------------------------------------------------------------------------
773 void OStatement_Base::setMaxRows(sal_Int32 _par0
)
775 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
776 SQLRETURN nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_MAX_ROWS
, (SQLPOINTER
)_par0
,SQL_IS_UINTEGER
);
777 OSL_UNUSED( nRetCode
);
779 //------------------------------------------------------------------------------
780 void OStatement_Base::setResultSetConcurrency(sal_Int32 _par0
)
783 if(_par0
== ResultSetConcurrency::READ_ONLY
)
784 nSet
= SQL_CONCUR_READ_ONLY
;
786 nSet
= SQL_CONCUR_VALUES
;
788 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
789 N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_CONCURRENCY
,(SQLPOINTER
)nSet
,SQL_IS_UINTEGER
);
792 //------------------------------------------------------------------------------
793 void OStatement_Base::setResultSetType(sal_Int32 _par0
)
796 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
797 SQLRETURN nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_ROW_BIND_TYPE
,(SQLPOINTER
)SQL_BIND_BY_COLUMN
,SQL_IS_UINTEGER
);
798 OSL_UNUSED( nRetCode
);
800 sal_Bool bUseBookmark
= isUsingBookmarks();
801 SQLUINTEGER
nSet( SQL_UNSPECIFIED
);
804 case ResultSetType::FORWARD_ONLY
:
805 nSet
= SQL_UNSPECIFIED
;
807 case ResultSetType::SCROLL_INSENSITIVE
:
808 nSet
= SQL_INSENSITIVE
;
809 N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_CURSOR_TYPE
,(SQLPOINTER
)SQL_CURSOR_KEYSET_DRIVEN
,SQL_IS_UINTEGER
);
811 case ResultSetType::SCROLL_SENSITIVE
:
814 SQLUINTEGER nCurProp
= getCursorProperties(SQL_CURSOR_DYNAMIC
,sal_True
);
815 if((nCurProp
& SQL_CA1_BOOKMARK
) != SQL_CA1_BOOKMARK
) // check if bookmark for this type isn't supported
816 { // we have to test the next one
817 nCurProp
= getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN
,sal_True
);
818 sal_Bool bNotBookmarks
= ((nCurProp
& SQL_CA1_BOOKMARK
) != SQL_CA1_BOOKMARK
);
819 nCurProp
= getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN
,sal_False
);
820 nSet
= SQL_CURSOR_KEYSET_DRIVEN
;
822 ((nCurProp
& SQL_CA2_SENSITIVITY_DELETIONS
) != SQL_CA2_SENSITIVITY_DELETIONS
) ||
823 ((nCurProp
& SQL_CA2_SENSITIVITY_ADDITIONS
) != SQL_CA2_SENSITIVITY_ADDITIONS
))
825 // bookmarks for keyset isn't supported so reset bookmark setting
826 setUsingBookmarks(sal_False
);
827 nSet
= SQL_CURSOR_DYNAMIC
;
831 nSet
= SQL_CURSOR_DYNAMIC
;
834 nSet
= SQL_CURSOR_DYNAMIC
;
835 if(N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_CURSOR_TYPE
,(SQLPOINTER
)nSet
,SQL_IS_UINTEGER
) != SQL_SUCCESS
)
837 nSet
= SQL_CURSOR_KEYSET_DRIVEN
;
838 N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_CURSOR_TYPE
,(SQLPOINTER
)nSet
,SQL_IS_UINTEGER
);
840 nSet
= SQL_SENSITIVE
;
843 OSL_ENSURE( false, "OStatement_Base::setResultSetType: invalid result set type!" );
848 N3SQLSetStmtAttr(m_aStatementHandle
, SQL_ATTR_CURSOR_SENSITIVITY
,(SQLPOINTER
)nSet
,SQL_IS_UINTEGER
);
850 //------------------------------------------------------------------------------
851 void OStatement_Base::setEscapeProcessing( const sal_Bool _bEscapeProc
)
853 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
854 SQLUINTEGER
nEscapeProc( _bEscapeProc
? SQL_NOSCAN_OFF
: SQL_NOSCAN_ON
);
855 SQLRETURN nRetCode
= N3SQLSetStmtAttr( m_aStatementHandle
, SQL_ATTR_NOSCAN
, (SQLPOINTER
)nEscapeProc
, SQL_IS_UINTEGER
);
859 //------------------------------------------------------------------------------
860 void OStatement_Base::setFetchDirection(sal_Int32 _par0
)
862 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
863 sal_Int32 nCursType
= 0;
864 SQLRETURN nRetCode
= SQL_SUCCESS
;
865 if(_par0
== FetchDirection::FORWARD
)
867 nCursType
= SQL_NONSCROLLABLE
;
868 nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_CURSOR_SCROLLABLE
,(SQLPOINTER
)nCursType
,SQL_IS_UINTEGER
);
870 else if(_par0
== FetchDirection::REVERSE
)
872 nCursType
= SQL_SCROLLABLE
;
873 nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_CURSOR_SCROLLABLE
,(SQLPOINTER
)nCursType
,SQL_IS_UINTEGER
);
875 OSL_UNUSED( nRetCode
);
877 //------------------------------------------------------------------------------
878 void OStatement_Base::setFetchSize(sal_Int32 _par0
)
880 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
882 SQLRETURN nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_ROW_ARRAY_SIZE
,(SQLPOINTER
)_par0
,SQL_IS_UINTEGER
);
884 delete m_pRowStatusArray
;
885 m_pRowStatusArray
= new SQLUSMALLINT
[_par0
];
886 nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_ROW_STATUS_PTR
,m_pRowStatusArray
,SQL_IS_POINTER
);
888 //------------------------------------------------------------------------------
889 void OStatement_Base::setMaxFieldSize(sal_Int32 _par0
)
891 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
892 N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_MAX_LENGTH
,(SQLPOINTER
)_par0
,SQL_IS_UINTEGER
);
894 //------------------------------------------------------------------------------
895 void OStatement_Base::setCursorName(const ::rtl::OUString
&_par0
)
897 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
898 ::rtl::OString
aName(::rtl::OUStringToOString(_par0
,getOwnConnection()->getTextEncoding()));
899 N3SQLSetCursorName(m_aStatementHandle
,(SDB_ODBC_CHAR
*)aName
.getStr(),(SQLSMALLINT
)aName
.getLength());
901 // -------------------------------------------------------------------------
902 sal_Bool
OStatement_Base::isUsingBookmarks() const
904 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
905 sal_uInt32 nValue
= SQL_UB_OFF
;
906 SQLRETURN nRetCode
= N3SQLGetStmtAttr(m_aStatementHandle
,SQL_ATTR_USE_BOOKMARKS
,&nValue
,SQL_IS_UINTEGER
,NULL
);
907 OSL_UNUSED( nRetCode
);
908 return nValue
!= SQL_UB_OFF
;
910 // -------------------------------------------------------------------------
911 sal_Bool
OStatement_Base::getEscapeProcessing() const
913 OSL_ENSURE( m_aStatementHandle
, "StatementHandle is null!" );
914 sal_uInt32 nValue
= SQL_NOSCAN_OFF
;
915 SQLRETURN nRetCode
= N3SQLGetStmtAttr( m_aStatementHandle
, SQL_ATTR_NOSCAN
, &nValue
, SQL_IS_UINTEGER
, NULL
);
917 return nValue
== SQL_NOSCAN_OFF
;
919 // -------------------------------------------------------------------------
920 void OStatement_Base::setUsingBookmarks(sal_Bool _bUseBookmark
)
922 OSL_ENSURE(m_aStatementHandle
,"StatementHandle is null!");
923 sal_uInt32 nValue
= _bUseBookmark
? SQL_UB_VARIABLE
: SQL_UB_OFF
;
924 SQLRETURN nRetCode
= N3SQLSetStmtAttr(m_aStatementHandle
,SQL_ATTR_USE_BOOKMARKS
,(SQLPOINTER
)nValue
,SQL_IS_UINTEGER
);
925 OSL_UNUSED( nRetCode
);
927 // -------------------------------------------------------------------------
928 ::cppu::IPropertyArrayHelper
* OStatement_Base::createArrayHelper( ) const
930 Sequence
< Property
> aProps(10);
931 Property
* pProperties
= aProps
.getArray();
933 DECL_PROP0(CURSORNAME
, ::rtl::OUString
);
934 DECL_BOOL_PROP0(ESCAPEPROCESSING
);
935 DECL_PROP0(FETCHDIRECTION
,sal_Int32
);
936 DECL_PROP0(FETCHSIZE
, sal_Int32
);
937 DECL_PROP0(MAXFIELDSIZE
,sal_Int32
);
938 DECL_PROP0(MAXROWS
, sal_Int32
);
939 DECL_PROP0(QUERYTIMEOUT
,sal_Int32
);
940 DECL_PROP0(RESULTSETCONCURRENCY
,sal_Int32
);
941 DECL_PROP0(RESULTSETTYPE
,sal_Int32
);
942 DECL_BOOL_PROP0(USEBOOKMARKS
);
944 return new ::cppu::OPropertyArrayHelper(aProps
);
947 // -------------------------------------------------------------------------
948 ::cppu::IPropertyArrayHelper
& OStatement_Base::getInfoHelper()
950 return *const_cast<OStatement_Base
*>(this)->getArrayHelper();
952 // -------------------------------------------------------------------------
953 sal_Bool
OStatement_Base::convertFastPropertyValue(
954 Any
& rConvertedValue
,
958 throw (::com::sun::star::lang::IllegalArgumentException
)
960 sal_Bool bConverted
= sal_False
;
965 case PROPERTY_ID_QUERYTIMEOUT
:
966 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getQueryTimeOut());
969 case PROPERTY_ID_MAXFIELDSIZE
:
970 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getMaxFieldSize());
973 case PROPERTY_ID_MAXROWS
:
974 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getMaxRows());
977 case PROPERTY_ID_CURSORNAME
:
978 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getCursorName());
981 case PROPERTY_ID_RESULTSETCONCURRENCY
:
982 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getResultSetConcurrency());
985 case PROPERTY_ID_RESULTSETTYPE
:
986 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getResultSetType());
989 case PROPERTY_ID_FETCHDIRECTION
:
990 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getFetchDirection());
993 case PROPERTY_ID_FETCHSIZE
:
994 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, getFetchSize());
997 case PROPERTY_ID_USEBOOKMARKS
:
998 bConverted
= ::comphelper::tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, isUsingBookmarks());
1001 case PROPERTY_ID_ESCAPEPROCESSING
:
1002 bConverted
= ::comphelper::tryPropertyValue( rConvertedValue
, rOldValue
, rValue
, getEscapeProcessing() );
1007 catch(const SQLException
&)
1009 // throw Exception(e.Message,*this);
1013 // -------------------------------------------------------------------------
1014 void OStatement_Base::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
) throw (Exception
)
1020 case PROPERTY_ID_QUERYTIMEOUT
:
1021 setQueryTimeOut(comphelper::getINT32(rValue
));
1023 case PROPERTY_ID_MAXFIELDSIZE
:
1024 setMaxFieldSize(comphelper::getINT32(rValue
));
1026 case PROPERTY_ID_MAXROWS
:
1027 setMaxRows(comphelper::getINT32(rValue
));
1029 case PROPERTY_ID_CURSORNAME
:
1030 setCursorName(comphelper::getString(rValue
));
1032 case PROPERTY_ID_RESULTSETCONCURRENCY
:
1033 setResultSetConcurrency(comphelper::getINT32(rValue
));
1035 case PROPERTY_ID_RESULTSETTYPE
:
1036 setResultSetType(comphelper::getINT32(rValue
));
1038 case PROPERTY_ID_FETCHDIRECTION
:
1039 setFetchDirection(comphelper::getINT32(rValue
));
1041 case PROPERTY_ID_FETCHSIZE
:
1042 setFetchSize(comphelper::getINT32(rValue
));
1044 case PROPERTY_ID_USEBOOKMARKS
:
1045 setUsingBookmarks(comphelper::getBOOL(rValue
));
1047 case PROPERTY_ID_ESCAPEPROCESSING
:
1048 setEscapeProcessing( ::comphelper::getBOOL( rValue
) );
1051 OSL_ENSURE( false, "OStatement_Base::setFastPropertyValue_NoBroadcast: what property?" );
1055 catch(const SQLException
& )
1057 // throw Exception(e.Message,*this);
1060 // -------------------------------------------------------------------------
1061 void OStatement_Base::getFastPropertyValue(Any
& rValue
,sal_Int32 nHandle
) const
1065 case PROPERTY_ID_QUERYTIMEOUT
:
1066 rValue
<<= getQueryTimeOut();
1068 case PROPERTY_ID_MAXFIELDSIZE
:
1069 rValue
<<= getMaxFieldSize();
1071 case PROPERTY_ID_MAXROWS
:
1072 rValue
<<= getMaxRows();
1074 case PROPERTY_ID_CURSORNAME
:
1075 rValue
<<= getCursorName();
1077 case PROPERTY_ID_RESULTSETCONCURRENCY
:
1078 rValue
<<= getResultSetConcurrency();
1080 case PROPERTY_ID_RESULTSETTYPE
:
1081 rValue
<<= getResultSetType();
1083 case PROPERTY_ID_FETCHDIRECTION
:
1084 rValue
<<= getFetchDirection();
1086 case PROPERTY_ID_FETCHSIZE
:
1087 rValue
<<= getFetchSize();
1089 case PROPERTY_ID_USEBOOKMARKS
:
1090 rValue
<<= isUsingBookmarks();
1092 case PROPERTY_ID_ESCAPEPROCESSING
:
1093 rValue
<<= getEscapeProcessing();
1096 OSL_ENSURE( false, "OStatement_Base::getFastPropertyValue: what property?" );
1100 // -------------------------------------------------------------------------
1101 IMPLEMENT_SERVICE_INFO(OStatement
,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
1102 // -----------------------------------------------------------------------------
1103 void SAL_CALL
OStatement_Base::acquire() throw()
1105 OStatement_BASE::acquire();
1107 // -----------------------------------------------------------------------------
1108 void SAL_CALL
OStatement_Base::release() throw()
1110 OStatement_BASE::release();
1112 // -----------------------------------------------------------------------------
1113 void SAL_CALL
OStatement::acquire() throw()
1115 OStatement_BASE2::acquire();
1117 // -----------------------------------------------------------------------------
1118 void SAL_CALL
OStatement::release() throw()
1120 OStatement_BASE2::release();
1122 // -----------------------------------------------------------------------------
1123 OResultSet
* OStatement_Base::createResulSet()
1125 return new OResultSet(m_aStatementHandle
,this);
1127 // -----------------------------------------------------------------------------
1128 Reference
< ::com::sun::star::beans::XPropertySetInfo
> SAL_CALL
OStatement_Base::getPropertySetInfo( ) throw(RuntimeException
)
1130 return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1132 // -----------------------------------------------------------------------------
1133 SQLUINTEGER
OStatement_Base::getCursorProperties(SQLINTEGER _nCursorType
,sal_Bool bFirst
)
1135 SQLUINTEGER nValueLen
= 0;
1138 SQLUSMALLINT nAskFor
= SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2
;
1139 if(SQL_CURSOR_KEYSET_DRIVEN
== _nCursorType
)
1140 nAskFor
= bFirst
? SQL_KEYSET_CURSOR_ATTRIBUTES1
: SQL_KEYSET_CURSOR_ATTRIBUTES2
;
1141 else if(SQL_CURSOR_STATIC
== _nCursorType
)
1142 nAskFor
= bFirst
? SQL_STATIC_CURSOR_ATTRIBUTES1
: SQL_STATIC_CURSOR_ATTRIBUTES2
;
1143 else if(SQL_CURSOR_FORWARD_ONLY
== _nCursorType
)
1144 nAskFor
= bFirst
? SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1
: SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2
;
1145 else if(SQL_CURSOR_DYNAMIC
== _nCursorType
)
1146 nAskFor
= bFirst
? SQL_DYNAMIC_CURSOR_ATTRIBUTES1
: SQL_DYNAMIC_CURSOR_ATTRIBUTES2
;
1149 OTools::GetInfo(getOwnConnection(),getConnectionHandle(),nAskFor
,nValueLen
,NULL
);
1152 { // we don't want our result destroy here
1157 // -----------------------------------------------------------------------------