xref: /trunk/main/connectivity/source/drivers/odbcbase/OStatement.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 
31 #include <stdio.h>
32 #include <osl/diagnose.h>
33 #include "odbc/OStatement.hxx"
34 #include "odbc/OConnection.hxx"
35 #include "odbc/OResultSet.hxx"
36 #include <comphelper/property.hxx>
37 #include "odbc/OTools.hxx"
38 #include <comphelper/uno3.hxx>
39 #include <osl/thread.h>
40 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
41 #include <com/sun/star/sdbc/ResultSetType.hpp>
42 #include <com/sun/star/sdbc/FetchDirection.hpp>
43 #include <com/sun/star/lang/DisposedException.hpp>
44 #include <comphelper/sequence.hxx>
45 #include <cppuhelper/typeprovider.hxx>
46 #include <comphelper/extract.hxx>
47 #include <comphelper/types.hxx>
48 #include "diagnose_ex.h"
49 #include <algorithm>
50 #include "resource/common_res.hrc"
51 #include "connectivity/dbexception.hxx"
52 
53 using namespace ::comphelper;
54 
55 #define THROW_SQL(x) \
56     OTools::ThrowException(m_pConnection,x,m_aStatementHandle,SQL_HANDLE_STMT,*this)
57 
58 #if OSL_DEBUG_LEVEL > 1
59 #define DEBUG_THROW                 \
60     try                                 \
61     {                                   \
62         THROW_SQL(nRetCode);            \
63     }                                   \
64     catch(SQLException&)                \
65     {                                   \
66         OSL_ENSURE(0,"Exception in odbc catched"); \
67     }
68 #endif
69 
70 
71 
72 using namespace connectivity::odbc;
73 //------------------------------------------------------------------------------
74 using namespace com::sun::star::uno;
75 using namespace com::sun::star::lang;
76 using namespace com::sun::star::beans;
77 using namespace com::sun::star::sdbc;
78 using namespace com::sun::star::sdbcx;
79 using namespace com::sun::star::container;
80 using namespace com::sun::star::io;
81 using namespace com::sun::star::util;
82 //------------------------------------------------------------------------------
83 OStatement_Base::OStatement_Base(OConnection* _pConnection )
84     :OStatement_BASE(m_aMutex)
85     ,OPropertySetHelper(OStatement_BASE::rBHelper)
86     ,m_pConnection(_pConnection)
87     ,m_aStatementHandle(SQL_NULL_HANDLE)
88     ,m_pRowStatusArray(0)
89     ,rBHelper(OStatement_BASE::rBHelper)
90 {
91     osl_incrementInterlockedCount( &m_refCount );
92     m_pConnection->acquire();
93     m_aStatementHandle = m_pConnection->createStatementHandle();
94 
95     //setMaxFieldSize(0);
96     // Don't do this. By ODBC spec, "0" is the default for the SQL_ATTR_MAX_LENGTH attribute. We once introduced
97     // this line since an PostgreSQL ODBC driver had a default other than 0. However, current drivers (at least 8.3
98     // and later) have a proper default of 0, so there should be no need anymore.
99     // On the other hand, the NotesSQL driver (IBM's ODBC driver for the Lotus Notes series) wrongly interprets
100     // "0" as "0", whereas the ODBC spec says it should in fact mean "unlimited".
101     // So, removing this line seems to be the best option for now.
102     // If we ever again encounter a ODBC driver which needs this option, then we should introduce a data source
103     // setting for it, instead of unconditionally doing it.
104 
105     osl_decrementInterlockedCount( &m_refCount );
106 }
107 // -----------------------------------------------------------------------------
108 OStatement_Base::~OStatement_Base()
109 {
110     OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
111 }
112 //------------------------------------------------------------------------------
113 void OStatement_Base::disposeResultSet()
114 {
115     // free the cursor if alive
116     Reference< XComponent > xComp(m_xResultSet.get(), UNO_QUERY);
117     if (xComp.is())
118         xComp->dispose();
119     m_xResultSet = Reference< XResultSet>();
120 }
121 // -----------------------------------------------------------------------------
122 void SAL_CALL OStatement_Base::disposing(void)
123 {
124     ::osl::MutexGuard aGuard(m_aMutex);
125 
126     disposeResultSet();
127     ::comphelper::disposeComponent(m_xGeneratedStatement);
128 
129     OSL_ENSURE(m_aStatementHandle,"OStatement_BASE2::disposing: StatementHandle is null!");
130     if (m_pConnection)
131     {
132         m_pConnection->freeStatementHandle(m_aStatementHandle);
133         m_pConnection->release();
134         m_pConnection = NULL;
135     }
136     OSL_ENSURE(!m_aStatementHandle,"Sohould ne null here!");
137 
138     OStatement_BASE::disposing();
139 }
140 //------------------------------------------------------------------------------
141 void OStatement_BASE2::disposing()
142 {
143     ::osl::MutexGuard aGuard(m_aMutex);
144 
145     dispose_ChildImpl();
146     OStatement_Base::disposing();
147 }
148 //-----------------------------------------------------------------------------
149 void SAL_CALL OStatement_BASE2::release() throw()
150 {
151     relase_ChildImpl();
152 }
153 //-----------------------------------------------------------------------------
154 Any SAL_CALL OStatement_Base::queryInterface( const Type & rType ) throw(RuntimeException)
155 {
156     if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() && rType == ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ) )
157         return Any();
158     Any aRet = OStatement_BASE::queryInterface(rType);
159     return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType);
160 }
161 // -------------------------------------------------------------------------
162 Sequence< Type > SAL_CALL OStatement_Base::getTypes(  ) throw(RuntimeException)
163 {
164     ::cppu::OTypeCollection aTypes( ::getCppuType( (const Reference< XMultiPropertySet > *)0 ),
165                                     ::getCppuType( (const Reference< XFastPropertySet > *)0 ),
166                                     ::getCppuType( (const Reference< XPropertySet > *)0 ));
167     Sequence< Type > aOldTypes = OStatement_BASE::getTypes();
168     if ( m_pConnection && !m_pConnection->isAutoRetrievingEnabled() )
169     {
170         ::std::remove(aOldTypes.getArray(),aOldTypes.getArray() + aOldTypes.getLength(),
171                         ::getCppuType( (const Reference< XGeneratedResultSet > *)0 ));
172         aOldTypes.realloc(aOldTypes.getLength() - 1);
173     }
174 
175     return ::comphelper::concatSequences(aTypes.getTypes(),aOldTypes);
176 }
177 // -------------------------------------------------------------------------
178 Reference< XResultSet > SAL_CALL OStatement_Base::getGeneratedValues(  ) throw (SQLException, RuntimeException)
179 {
180     OSL_ENSURE( m_pConnection && m_pConnection->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!");
181     Reference< XResultSet > xRes;
182     if ( m_pConnection )
183     {
184         ::rtl::OUString sStmt = m_pConnection->getTransformedGeneratedStatement(m_sSqlStatement);
185         if ( sStmt.getLength() )
186         {
187             ::comphelper::disposeComponent(m_xGeneratedStatement);
188             m_xGeneratedStatement = m_pConnection->createStatement();
189             xRes = m_xGeneratedStatement->executeQuery(sStmt);
190         }
191     }
192     return xRes;
193 }
194 // -----------------------------------------------------------------------------
195 void SAL_CALL OStatement_Base::cancel(  ) throw(RuntimeException)
196 {
197     ::osl::MutexGuard aGuard( m_aMutex );
198     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
199 
200     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
201     OTools::ThrowException(m_pConnection,N3SQLCancel(m_aStatementHandle),m_aStatementHandle,SQL_HANDLE_STMT,*this);
202 }
203 // -------------------------------------------------------------------------
204 
205 void SAL_CALL OStatement_Base::close(  ) throw(SQLException, RuntimeException)
206 {
207     {
208         ::osl::MutexGuard aGuard( m_aMutex );
209         checkDisposed(OStatement_BASE::rBHelper.bDisposed);
210 
211     }
212     dispose();
213 }
214 // -------------------------------------------------------------------------
215 
216 void SAL_CALL OStatement::clearBatch(  ) throw(SQLException, RuntimeException)
217 {
218 
219 }
220 // -------------------------------------------------------------------------
221 
222 void OStatement_Base::reset() throw (SQLException)
223 {
224     ::osl::MutexGuard aGuard( m_aMutex );
225     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
226 
227 
228     clearWarnings ();
229 
230     if (m_xResultSet.get().is())
231     {
232         clearMyResultSet();
233     }
234     if(m_aStatementHandle)
235     {
236         THROW_SQL(N3SQLFreeStmt(m_aStatementHandle, SQL_CLOSE));
237     }
238 }
239 //--------------------------------------------------------------------
240 // clearMyResultSet
241 // If a ResultSet was created for this Statement, close it
242 //--------------------------------------------------------------------
243 
244 void OStatement_Base::clearMyResultSet () throw (SQLException)
245 {
246     ::osl::MutexGuard aGuard( m_aMutex );
247     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
248 
249     try
250     {
251         Reference<XCloseable> xCloseable;
252         if ( ::comphelper::query_interface( m_xResultSet.get(), xCloseable ) )
253             xCloseable->close();
254     }
255     catch( const DisposedException& ) { }
256 
257     m_xResultSet = Reference< XResultSet >();
258 }
259 //--------------------------------------------------------------------
260 SQLLEN OStatement_Base::getRowCount () throw( SQLException)
261 {
262     ::osl::MutexGuard aGuard( m_aMutex );
263     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
264 
265 
266     SQLLEN numRows = 0;
267 
268     try {
269         THROW_SQL(N3SQLRowCount(m_aStatementHandle,&numRows));
270     }
271     catch (SQLException&)
272     {
273     }
274     return numRows;
275 }
276 //--------------------------------------------------------------------
277 // lockIfNecessary
278 // If the given SQL statement contains a 'FOR UPDATE' clause, change
279 // the concurrency to lock so that the row can then be updated.  Returns
280 // true if the concurrency has been changed
281 //--------------------------------------------------------------------
282 
283 sal_Bool OStatement_Base::lockIfNecessary (const ::rtl::OUString& sql) throw( SQLException)
284 {
285     sal_Bool rc = sal_False;
286 
287     // First, convert the statement to upper case
288 
289     ::rtl::OUString sqlStatement = sql.toAsciiUpperCase ();
290 
291     // Now, look for the FOR UPDATE keywords.  If there is any extra white
292     // space between the FOR and UPDATE, this will fail.
293 
294     sal_Int32 index = sqlStatement.indexOf(::rtl::OUString::createFromAscii(" FOR UPDATE"));
295 
296     // We found it.  Change our concurrency level to ensure that the
297     // row can be updated.
298 
299     if (index > 0)
300     {
301         OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
302         try
303         {
304             SQLINTEGER nLock = SQL_CONCUR_LOCK;
305             THROW_SQL(N3SQLSetStmtAttr(m_aStatementHandle, SQL_CONCURRENCY,(SQLPOINTER)nLock,SQL_IS_UINTEGER));
306         }
307         catch (SQLWarning& warn)
308         {
309             // Catch any warnings and place on the warning stack
310             setWarning (warn);
311         }
312         rc = sal_True;
313     }
314 
315     return rc;
316 }
317 //--------------------------------------------------------------------
318 // setWarning
319 // Sets the warning
320 //--------------------------------------------------------------------
321 
322 void OStatement_Base::setWarning (const SQLWarning &ex) throw( SQLException)
323 {
324     ::osl::MutexGuard aGuard( m_aMutex );
325     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
326 
327 
328     m_aLastWarning = ex;
329 }
330 
331 //--------------------------------------------------------------------
332 // getColumnCount
333 // Return the number of columns in the ResultSet
334 //--------------------------------------------------------------------
335 
336 sal_Int32 OStatement_Base::getColumnCount () throw( SQLException)
337 {
338     ::osl::MutexGuard aGuard( m_aMutex );
339     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
340 
341 
342     sal_Int16   numCols = 0;
343     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
344 
345     try {
346         THROW_SQL(N3SQLNumResultCols(m_aStatementHandle,&numCols));
347     }
348     catch (SQLException&)
349     {
350     }
351     return numCols;
352 }
353 // -------------------------------------------------------------------------
354 
355 sal_Bool SAL_CALL OStatement_Base::execute( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
356 {
357     ::osl::MutexGuard aGuard( m_aMutex );
358     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
359     m_sSqlStatement = sql;
360 
361 
362     ::rtl::OString aSql(::rtl::OUStringToOString(sql,getOwnConnection()->getTextEncoding()));
363 
364     sal_Bool hasResultSet = sal_False;
365     SQLWarning aWarning;
366 
367     // Reset the statement handle and warning
368 
369     reset();
370 
371     // Check for a 'FOR UPDATE' statement.  If present, change
372     // the concurrency to lock
373 
374     lockIfNecessary (sql);
375 
376     // Call SQLExecDirect
377     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
378 
379     try {
380         THROW_SQL(N3SQLExecDirect(m_aStatementHandle, (SDB_ODBC_CHAR*)aSql.getStr(),aSql.getLength()));
381     }
382     catch (SQLWarning& ex) {
383 
384         // Save pointer to warning and save with ResultSet
385         // object once it is created.
386 
387         aWarning = ex;
388     }
389 
390     // Now determine if there is a result set associated with
391     // the SQL statement that was executed.  Get the column
392     // count, and if it is not zero, there is a result set.
393 
394     if (getColumnCount () > 0)
395     {
396         hasResultSet = sal_True;
397     }
398 
399     return hasResultSet;
400 }
401 //--------------------------------------------------------------------
402 // getResultSet
403 // getResultSet returns the current result as a ResultSet.  It
404 // returns NULL if the current result is not a ResultSet.
405 //--------------------------------------------------------------------
406 Reference< XResultSet > OStatement_Base::getResultSet (sal_Bool checkCount) throw( SQLException)
407 {
408     ::osl::MutexGuard aGuard( m_aMutex );
409     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
410 
411 
412     if (m_xResultSet.get().is())  // if resultset already retrieved,
413     {
414         // throw exception to avoid sequence error
415         ::dbtools::throwFunctionSequenceException(*this,Any());
416     }
417 
418     OResultSet* pRs = NULL;
419     sal_Int32 numCols = 1;
420 
421     // If we already know we have result columns, checkCount
422     // is false.  This is an optimization to prevent unneeded
423     // calls to getColumnCount
424 
425     if (checkCount)
426         numCols = getColumnCount ();
427 
428     // Only return a result set if there are result columns
429 
430     if (numCols > 0)
431     {
432         OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
433         pRs = createResulSet();
434         pRs->construct();
435 
436         // Save a copy of our last result set
437         // Changed to save copy at getResultSet.
438         //m_xResultSet = rs;
439     }
440     else
441         clearMyResultSet ();
442 
443     return pRs;
444 }
445 //--------------------------------------------------------------------
446 // getStmtOption
447 // Invoke SQLGetStmtOption with the given option.
448 //--------------------------------------------------------------------
449 
450 sal_Int32 OStatement_Base::getStmtOption (short fOption) const
451 {
452     sal_Int32   result = 0;
453     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
454     N3SQLGetStmtAttr(m_aStatementHandle, fOption,&result,SQL_IS_INTEGER,NULL);
455     return result;
456 }
457 // -------------------------------------------------------------------------
458 
459 Reference< XResultSet > SAL_CALL OStatement_Base::executeQuery( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
460 {
461     ::osl::MutexGuard aGuard( m_aMutex );
462     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
463 
464 
465     Reference< XResultSet > xRS = NULL;
466 
467     // Execute the statement.  If execute returns true, a result
468     // set exists.
469 
470     if (execute (sql))
471     {
472         xRS = getResultSet (sal_False);
473         m_xResultSet = xRS;
474     }
475     else
476     {
477         // No ResultSet was produced.  Raise an exception
478         m_pConnection->throwGenericSQLException(STR_NO_RESULTSET,*this);
479     }
480     return xRS;
481 }
482 // -------------------------------------------------------------------------
483 
484 Reference< XConnection > SAL_CALL OStatement_Base::getConnection(  ) throw(SQLException, RuntimeException)
485 {
486     ::osl::MutexGuard aGuard( m_aMutex );
487     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
488 
489     return (Reference< XConnection >)m_pConnection;
490 }
491 // -------------------------------------------------------------------------
492 
493 Any SAL_CALL OStatement::queryInterface( const Type & rType ) throw(RuntimeException)
494 {
495     Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this));
496     return aRet.hasValue() ? aRet : OStatement_Base::queryInterface(rType);
497 }
498 // -------------------------------------------------------------------------
499 
500 void SAL_CALL OStatement::addBatch( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
501 {
502     ::osl::MutexGuard aGuard( m_aMutex );
503     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
504 
505 
506     m_aBatchList.push_back(sql);
507 }
508 // -------------------------------------------------------------------------
509 Sequence< sal_Int32 > SAL_CALL OStatement::executeBatch(  ) throw(SQLException, RuntimeException)
510 {
511     ::osl::MutexGuard aGuard( m_aMutex );
512     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
513 
514 
515     ::rtl::OString aBatchSql;
516     sal_Int32 nLen = 0;
517     for(::std::list< ::rtl::OUString>::const_iterator i=m_aBatchList.begin();i != m_aBatchList.end();++i,++nLen)
518     {
519         aBatchSql += ::rtl::OUStringToOString(*i,getOwnConnection()->getTextEncoding());
520         aBatchSql += ";";
521     }
522 
523     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
524     THROW_SQL(N3SQLExecDirect(m_aStatementHandle, (SDB_ODBC_CHAR*)aBatchSql.getStr(),aBatchSql.getLength()));
525 
526     Sequence< sal_Int32 > aRet(nLen);
527     sal_Int32* pArray = aRet.getArray();
528     for(sal_Int32 j=0;j<nLen;++j)
529     {
530         SQLRETURN nError = N3SQLMoreResults(m_aStatementHandle);
531         if(nError == SQL_SUCCESS)
532         {
533             SQLLEN nRowCount=0;
534             N3SQLRowCount(m_aStatementHandle,&nRowCount);
535             pArray[j] = nRowCount;
536         }
537     }
538     return aRet;
539 }
540 // -------------------------------------------------------------------------
541 
542 
543 sal_Int32 SAL_CALL OStatement_Base::executeUpdate( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException)
544 {
545     ::osl::MutexGuard aGuard( m_aMutex );
546     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
547 
548 
549     sal_Int32 numRows = -1;
550 
551     // Execute the statement.  If execute returns false, a
552     // row count exists.
553 
554     if (!execute (sql)) {
555         numRows = getUpdateCount();
556     }
557     else {
558 
559         // No update count was produced (a ResultSet was).  Raise
560         // an exception
561 
562         ::connectivity::SharedResources aResources;
563         const ::rtl::OUString sError( aResources.getResourceString(STR_NO_ROWCOUNT));
564         throw SQLException (sError, *this,::rtl::OUString(),0,Any());
565     }
566     return numRows;
567 
568 }
569 // -------------------------------------------------------------------------
570 
571 Reference< XResultSet > SAL_CALL OStatement_Base::getResultSet(  ) throw(SQLException, RuntimeException)
572 {
573     ::osl::MutexGuard aGuard( m_aMutex );
574     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
575 
576 
577     m_xResultSet = getResultSet(sal_True);
578     return m_xResultSet;
579 }
580 // -------------------------------------------------------------------------
581 
582 sal_Int32 SAL_CALL OStatement_Base::getUpdateCount(  ) throw(SQLException, RuntimeException)
583 {
584     ::osl::MutexGuard aGuard( m_aMutex );
585     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
586 
587 
588     sal_Int32 rowCount = -1;
589 
590     // Only return a row count for SQL statements that did not
591     // return a result set.
592 
593     if (getColumnCount () == 0)
594         rowCount = getRowCount ();
595 
596     return rowCount;
597 }
598 // -------------------------------------------------------------------------
599 
600 sal_Bool SAL_CALL OStatement_Base::getMoreResults(  ) throw(SQLException, RuntimeException)
601 {
602     ::osl::MutexGuard aGuard( m_aMutex );
603     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
604 
605 
606     SQLWarning  warning;
607     sal_Bool hasResultSet = sal_False;
608 
609     // clear previous warnings
610 
611     clearWarnings ();
612 
613     // Call SQLMoreResults
614     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
615 
616     try {
617         hasResultSet = N3SQLMoreResults(m_aStatementHandle) == SQL_SUCCESS;
618     }
619     catch (SQLWarning &ex) {
620 
621         // Save pointer to warning and save with ResultSet
622         // object once it is created.
623 
624         warning = ex;
625     }
626 
627     // There are more results (it may not be a result set, though)
628 
629     if (hasResultSet)
630     {
631 
632         // Now determine if there is a result set associated
633         // with the SQL statement that was executed.  Get the
634         // column count, and if it is zero, there is not a
635         // result set.
636 
637         if (getColumnCount () == 0)
638             hasResultSet = sal_False;
639     }
640 
641     // Set the warning for the statement, if one was generated
642 
643     setWarning (warning);
644 
645     // Return the result set indicator
646 
647     return hasResultSet;
648 }
649 // -------------------------------------------------------------------------
650 
651 // -------------------------------------------------------------------------
652 Any SAL_CALL OStatement_Base::getWarnings(  ) throw(SQLException, RuntimeException)
653 {
654     ::osl::MutexGuard aGuard( m_aMutex );
655     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
656 
657 
658     return makeAny(m_aLastWarning);
659 }
660 // -------------------------------------------------------------------------
661 
662 // -------------------------------------------------------------------------
663 void SAL_CALL OStatement_Base::clearWarnings(  ) throw(SQLException, RuntimeException)
664 {
665     ::osl::MutexGuard aGuard( m_aMutex );
666     checkDisposed(OStatement_BASE::rBHelper.bDisposed);
667 
668 
669     m_aLastWarning = SQLWarning();
670 }
671 // -------------------------------------------------------------------------
672 //------------------------------------------------------------------------------
673 sal_Int32 OStatement_Base::getQueryTimeOut() const
674 {
675     return getStmtOption(SQL_ATTR_QUERY_TIMEOUT);
676 }
677 //------------------------------------------------------------------------------
678 sal_Int32 OStatement_Base::getMaxRows() const
679 {
680     return getStmtOption(SQL_ATTR_MAX_ROWS);
681 }
682 //------------------------------------------------------------------------------
683 sal_Int32 OStatement_Base::getResultSetConcurrency() const
684 {
685     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
686     sal_uInt32 nValue;
687     SQLRETURN nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CONCURRENCY,&nValue,SQL_IS_UINTEGER,0);
688     OSL_UNUSED( nRetCode );
689     if(nValue == SQL_CONCUR_READ_ONLY)
690         nValue = ResultSetConcurrency::READ_ONLY;
691     else
692         nValue = ResultSetConcurrency::UPDATABLE;
693     return nValue;
694 }
695 //------------------------------------------------------------------------------
696 sal_Int32 OStatement_Base::getResultSetType() const
697 {
698     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
699     sal_uInt32 nValue = SQL_CURSOR_FORWARD_ONLY;
700     SQLRETURN nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_SENSITIVITY,&nValue,SQL_IS_UINTEGER,0);
701     nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_TYPE,&nValue,SQL_IS_UINTEGER,0);
702     switch(nValue)
703     {
704         case SQL_CURSOR_FORWARD_ONLY:
705             nValue = ResultSetType::FORWARD_ONLY;
706             break;
707         case SQL_CURSOR_KEYSET_DRIVEN:
708         case SQL_CURSOR_STATIC:
709             nValue = ResultSetType::SCROLL_INSENSITIVE;
710             break;
711         case SQL_CURSOR_DYNAMIC:
712             nValue = ResultSetType::SCROLL_SENSITIVE;
713             break;
714     }
715 
716     return nValue;
717 }
718 //------------------------------------------------------------------------------
719 sal_Int32 OStatement_Base::getFetchDirection() const
720 {
721     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
722     sal_uInt32 nValue = 0;
723     SQLRETURN nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_SCROLLABLE,&nValue,SQL_IS_UINTEGER,0);
724     OSL_UNUSED( nRetCode );
725 
726     switch(nValue)
727     {
728         case SQL_SCROLLABLE:
729             nValue = FetchDirection::REVERSE;
730             break;
731         default:
732             nValue = FetchDirection::FORWARD;
733             break;
734     }
735 
736     return nValue;
737 }
738 //------------------------------------------------------------------------------
739 sal_Int32 OStatement_Base::getFetchSize() const
740 {
741     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
742     sal_uInt32 nValue;
743     SQLRETURN nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE,&nValue,SQL_IS_UINTEGER,0);
744     OSL_UNUSED( nRetCode );
745     return nValue;
746 }
747 //------------------------------------------------------------------------------
748 sal_Int32 OStatement_Base::getMaxFieldSize() const
749 {
750     return getStmtOption(SQL_ATTR_MAX_LENGTH);
751 }
752 //------------------------------------------------------------------------------
753 ::rtl::OUString OStatement_Base::getCursorName() const
754 {
755     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
756     SQLCHAR pName[258];
757     SQLSMALLINT nRealLen = 0;
758     SQLRETURN nRetCode = N3SQLGetCursorName(m_aStatementHandle,(SQLCHAR*)pName,256,&nRealLen);
759     OSL_UNUSED( nRetCode );
760     return ::rtl::OUString::createFromAscii((const char*)pName);
761 }
762 //------------------------------------------------------------------------------
763 void OStatement_Base::setQueryTimeOut(sal_Int32 seconds)
764 {
765     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
766     SQLRETURN nRetCode = N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_QUERY_TIMEOUT,(SQLPOINTER)seconds,SQL_IS_UINTEGER);
767     OSL_UNUSED( nRetCode );
768 }
769 //------------------------------------------------------------------------------
770 void OStatement_Base::setMaxRows(sal_Int32 _par0)
771 {
772     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
773     SQLRETURN nRetCode = N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_MAX_ROWS, (SQLPOINTER)_par0,SQL_IS_UINTEGER);
774     OSL_UNUSED( nRetCode );
775 }
776 //------------------------------------------------------------------------------
777 void OStatement_Base::setResultSetConcurrency(sal_Int32 _par0)
778 {
779     SQLINTEGER nSet;
780     if(_par0 == ResultSetConcurrency::READ_ONLY)
781         nSet = SQL_CONCUR_READ_ONLY;
782     else
783         nSet = SQL_CONCUR_VALUES;
784 
785     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
786     N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_CONCURRENCY,(SQLPOINTER)nSet,SQL_IS_UINTEGER);
787 
788 }
789 //------------------------------------------------------------------------------
790 void OStatement_Base::setResultSetType(sal_Int32 _par0)
791 {
792 
793     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
794     SQLRETURN nRetCode = N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_ROW_BIND_TYPE,(SQLPOINTER)SQL_BIND_BY_COLUMN,SQL_IS_UINTEGER);
795     OSL_UNUSED( nRetCode );
796 
797     sal_Bool bUseBookmark = isUsingBookmarks();
798     SQLUINTEGER nSet( SQL_UNSPECIFIED );
799     switch(_par0)
800     {
801         case ResultSetType::FORWARD_ONLY:
802             nSet =  SQL_UNSPECIFIED;
803             break;
804         case ResultSetType::SCROLL_INSENSITIVE:
805             nSet =  SQL_INSENSITIVE;
806             N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_CURSOR_TYPE,(SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN,SQL_IS_UINTEGER);
807             break;
808         case ResultSetType::SCROLL_SENSITIVE:
809             if(bUseBookmark)
810             {
811                 SQLUINTEGER nCurProp = getCursorProperties(SQL_CURSOR_DYNAMIC,sal_True);
812                 if((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK) // check if bookmark for this type isn't supported
813                 { // we have to test the next one
814                     nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,sal_True);
815                     sal_Bool bNotBookmarks = ((nCurProp & SQL_CA1_BOOKMARK) != SQL_CA1_BOOKMARK);
816                     nCurProp = getCursorProperties(SQL_CURSOR_KEYSET_DRIVEN,sal_False);
817                     nSet = SQL_CURSOR_KEYSET_DRIVEN;
818                     if( bNotBookmarks ||
819                         ((nCurProp & SQL_CA2_SENSITIVITY_DELETIONS) != SQL_CA2_SENSITIVITY_DELETIONS) ||
820                         ((nCurProp & SQL_CA2_SENSITIVITY_ADDITIONS) != SQL_CA2_SENSITIVITY_ADDITIONS))
821                     {
822                         // bookmarks for keyset isn't supported so reset bookmark setting
823                         setUsingBookmarks(sal_False);
824                         nSet = SQL_CURSOR_DYNAMIC;
825                     }
826                 }
827                 else
828                     nSet = SQL_CURSOR_DYNAMIC;
829             }
830             else
831                 nSet = SQL_CURSOR_DYNAMIC;
832             if(N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_CURSOR_TYPE,(SQLPOINTER)nSet,SQL_IS_UINTEGER) != SQL_SUCCESS)
833             {
834                 nSet = SQL_CURSOR_KEYSET_DRIVEN;
835                 N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_CURSOR_TYPE,(SQLPOINTER)nSet,SQL_IS_UINTEGER);
836             }
837             nSet =  SQL_SENSITIVE;
838             break;
839         default:
840             OSL_ENSURE( false, "OStatement_Base::setResultSetType: invalid result set type!" );
841             break;
842     }
843 
844 
845     N3SQLSetStmtAttr(m_aStatementHandle, SQL_ATTR_CURSOR_SENSITIVITY,(SQLPOINTER)nSet,SQL_IS_UINTEGER);
846 }
847 //------------------------------------------------------------------------------
848 void OStatement_Base::setEscapeProcessing( const sal_Bool _bEscapeProc )
849 {
850     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
851     SQLUINTEGER nEscapeProc( _bEscapeProc ? SQL_NOSCAN_OFF : SQL_NOSCAN_ON );
852     SQLRETURN nRetCode = N3SQLSetStmtAttr( m_aStatementHandle, SQL_ATTR_NOSCAN, (SQLPOINTER)nEscapeProc, SQL_IS_UINTEGER );
853     (void)nRetCode;
854 }
855 
856 //------------------------------------------------------------------------------
857 void OStatement_Base::setFetchDirection(sal_Int32 _par0)
858 {
859     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
860     sal_Int32 nCursType = 0;
861     SQLRETURN nRetCode  = SQL_SUCCESS;
862     if(_par0 == FetchDirection::FORWARD)
863     {
864         nCursType = SQL_NONSCROLLABLE;
865         nRetCode = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_SCROLLABLE,(SQLPOINTER)nCursType,SQL_IS_UINTEGER);
866     }
867     else if(_par0 == FetchDirection::REVERSE)
868     {
869         nCursType = SQL_SCROLLABLE;
870         nRetCode = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_CURSOR_SCROLLABLE,(SQLPOINTER)nCursType,SQL_IS_UINTEGER);
871     }
872     OSL_UNUSED( nRetCode );
873 }
874 //------------------------------------------------------------------------------
875 void OStatement_Base::setFetchSize(sal_Int32 _par0)
876 {
877     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
878     OSL_ENSURE(_par0>0,"Illegal fetch size!");
879     if ( _par0 > 0 )
880     {
881 
882         SQLRETURN nRetCode = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_ROW_ARRAY_SIZE,(SQLPOINTER)_par0,SQL_IS_UINTEGER);
883 
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);
887     }
888 }
889 //------------------------------------------------------------------------------
890 void OStatement_Base::setMaxFieldSize(sal_Int32 _par0)
891 {
892     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
893     N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_MAX_LENGTH,(SQLPOINTER)_par0,SQL_IS_UINTEGER);
894 }
895 //------------------------------------------------------------------------------
896 void OStatement_Base::setCursorName(const ::rtl::OUString &_par0)
897 {
898     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
899     ::rtl::OString aName(::rtl::OUStringToOString(_par0,getOwnConnection()->getTextEncoding()));
900     N3SQLSetCursorName(m_aStatementHandle,(SDB_ODBC_CHAR*)aName.getStr(),(SQLSMALLINT)aName.getLength());
901 }
902 // -------------------------------------------------------------------------
903 sal_Bool OStatement_Base::isUsingBookmarks() const
904 {
905     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
906     sal_uInt32 nValue = SQL_UB_OFF;
907     SQLRETURN nRetCode = N3SQLGetStmtAttr(m_aStatementHandle,SQL_ATTR_USE_BOOKMARKS,&nValue,SQL_IS_UINTEGER,NULL);
908     OSL_UNUSED( nRetCode );
909     return nValue != SQL_UB_OFF;
910 }
911 // -------------------------------------------------------------------------
912 sal_Bool OStatement_Base::getEscapeProcessing() const
913 {
914     OSL_ENSURE( m_aStatementHandle, "StatementHandle is null!" );
915     sal_uInt32 nValue = SQL_NOSCAN_OFF;
916     SQLRETURN nRetCode = N3SQLGetStmtAttr( m_aStatementHandle, SQL_ATTR_NOSCAN, &nValue, SQL_IS_UINTEGER, NULL );
917     (void)nRetCode;
918     return nValue == SQL_NOSCAN_OFF;
919 }
920 // -------------------------------------------------------------------------
921 void OStatement_Base::setUsingBookmarks(sal_Bool _bUseBookmark)
922 {
923     OSL_ENSURE(m_aStatementHandle,"StatementHandle is null!");
924     sal_uInt32 nValue = _bUseBookmark ? SQL_UB_VARIABLE : SQL_UB_OFF;
925     SQLRETURN nRetCode = N3SQLSetStmtAttr(m_aStatementHandle,SQL_ATTR_USE_BOOKMARKS,(SQLPOINTER)nValue,SQL_IS_UINTEGER);
926     OSL_UNUSED( nRetCode );
927 }
928 // -------------------------------------------------------------------------
929 ::cppu::IPropertyArrayHelper* OStatement_Base::createArrayHelper( ) const
930 {
931     Sequence< Property > aProps(10);
932     Property* pProperties = aProps.getArray();
933     sal_Int32 nPos = 0;
934     DECL_PROP0(CURSORNAME,  ::rtl::OUString);
935     DECL_BOOL_PROP0(ESCAPEPROCESSING);
936     DECL_PROP0(FETCHDIRECTION,sal_Int32);
937     DECL_PROP0(FETCHSIZE,   sal_Int32);
938     DECL_PROP0(MAXFIELDSIZE,sal_Int32);
939     DECL_PROP0(MAXROWS,     sal_Int32);
940     DECL_PROP0(QUERYTIMEOUT,sal_Int32);
941     DECL_PROP0(RESULTSETCONCURRENCY,sal_Int32);
942     DECL_PROP0(RESULTSETTYPE,sal_Int32);
943     DECL_BOOL_PROP0(USEBOOKMARKS);
944 
945     return new ::cppu::OPropertyArrayHelper(aProps);
946 }
947 
948 // -------------------------------------------------------------------------
949 ::cppu::IPropertyArrayHelper & OStatement_Base::getInfoHelper()
950 {
951     return *const_cast<OStatement_Base*>(this)->getArrayHelper();
952 }
953 // -------------------------------------------------------------------------
954 sal_Bool OStatement_Base::convertFastPropertyValue(
955                             Any & rConvertedValue,
956                             Any & rOldValue,
957                             sal_Int32 nHandle,
958                             const Any& rValue )
959                                 throw (::com::sun::star::lang::IllegalArgumentException)
960 {
961     sal_Bool bConverted = sal_False;
962     try
963     {
964         switch(nHandle)
965         {
966             case PROPERTY_ID_QUERYTIMEOUT:
967                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getQueryTimeOut());
968                 break;
969 
970             case PROPERTY_ID_MAXFIELDSIZE:
971                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxFieldSize());
972                 break;
973 
974             case PROPERTY_ID_MAXROWS:
975                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxRows());
976                 break;
977 
978             case PROPERTY_ID_CURSORNAME:
979                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getCursorName());
980                 break;
981 
982             case PROPERTY_ID_RESULTSETCONCURRENCY:
983                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetConcurrency());
984                 break;
985 
986             case PROPERTY_ID_RESULTSETTYPE:
987                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetType());
988                 break;
989 
990             case PROPERTY_ID_FETCHDIRECTION:
991                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection());
992                 break;
993 
994             case PROPERTY_ID_FETCHSIZE:
995                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize());
996                 break;
997 
998             case PROPERTY_ID_USEBOOKMARKS:
999                 bConverted = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, isUsingBookmarks());
1000                 break;
1001 
1002             case PROPERTY_ID_ESCAPEPROCESSING:
1003                 bConverted = ::comphelper::tryPropertyValue( rConvertedValue, rOldValue, rValue, getEscapeProcessing() );
1004                 break;
1005 
1006         }
1007     }
1008     catch(const SQLException&)
1009     {
1010         //  throw Exception(e.Message,*this);
1011     }
1012     return bConverted;
1013 }
1014 // -------------------------------------------------------------------------
1015 void OStatement_Base::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
1016 {
1017     try
1018     {
1019         switch(nHandle)
1020         {
1021             case PROPERTY_ID_QUERYTIMEOUT:
1022                 setQueryTimeOut(comphelper::getINT32(rValue));
1023                 break;
1024             case PROPERTY_ID_MAXFIELDSIZE:
1025                 setMaxFieldSize(comphelper::getINT32(rValue));
1026                 break;
1027             case PROPERTY_ID_MAXROWS:
1028                 setMaxRows(comphelper::getINT32(rValue));
1029                 break;
1030             case PROPERTY_ID_CURSORNAME:
1031                 setCursorName(comphelper::getString(rValue));
1032                 break;
1033             case PROPERTY_ID_RESULTSETCONCURRENCY:
1034                 setResultSetConcurrency(comphelper::getINT32(rValue));
1035                 break;
1036             case PROPERTY_ID_RESULTSETTYPE:
1037                 setResultSetType(comphelper::getINT32(rValue));
1038                 break;
1039             case PROPERTY_ID_FETCHDIRECTION:
1040                 setFetchDirection(comphelper::getINT32(rValue));
1041                 break;
1042             case PROPERTY_ID_FETCHSIZE:
1043                 setFetchSize(comphelper::getINT32(rValue));
1044                 break;
1045             case PROPERTY_ID_USEBOOKMARKS:
1046                 setUsingBookmarks(comphelper::getBOOL(rValue));
1047                 break;
1048             case PROPERTY_ID_ESCAPEPROCESSING:
1049                 setEscapeProcessing( ::comphelper::getBOOL( rValue ) );
1050                 break;
1051             default:
1052                 OSL_ENSURE( false, "OStatement_Base::setFastPropertyValue_NoBroadcast: what property?" );
1053                 break;
1054         }
1055     }
1056     catch(const SQLException& )
1057     {
1058         //  throw Exception(e.Message,*this);
1059     }
1060 }
1061 // -------------------------------------------------------------------------
1062 void OStatement_Base::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
1063 {
1064     switch(nHandle)
1065     {
1066         case PROPERTY_ID_QUERYTIMEOUT:
1067             rValue <<= getQueryTimeOut();
1068             break;
1069         case PROPERTY_ID_MAXFIELDSIZE:
1070             rValue <<= getMaxFieldSize();
1071             break;
1072         case PROPERTY_ID_MAXROWS:
1073             rValue <<= getMaxRows();
1074             break;
1075         case PROPERTY_ID_CURSORNAME:
1076             rValue <<= getCursorName();
1077             break;
1078         case PROPERTY_ID_RESULTSETCONCURRENCY:
1079             rValue <<= getResultSetConcurrency();
1080             break;
1081         case PROPERTY_ID_RESULTSETTYPE:
1082             rValue <<= getResultSetType();
1083             break;
1084         case PROPERTY_ID_FETCHDIRECTION:
1085             rValue <<= getFetchDirection();
1086             break;
1087         case PROPERTY_ID_FETCHSIZE:
1088             rValue <<= getFetchSize();
1089             break;
1090         case PROPERTY_ID_USEBOOKMARKS:
1091             rValue <<= isUsingBookmarks();
1092             break;
1093         case PROPERTY_ID_ESCAPEPROCESSING:
1094             rValue <<= getEscapeProcessing();
1095             break;
1096         default:
1097             OSL_ENSURE( false, "OStatement_Base::getFastPropertyValue: what property?" );
1098             break;
1099     }
1100 }
1101 // -------------------------------------------------------------------------
1102 IMPLEMENT_SERVICE_INFO(OStatement,"com.sun.star.sdbcx.OStatement","com.sun.star.sdbc.Statement");
1103 // -----------------------------------------------------------------------------
1104 void SAL_CALL OStatement_Base::acquire() throw()
1105 {
1106     OStatement_BASE::acquire();
1107 }
1108 // -----------------------------------------------------------------------------
1109 void SAL_CALL OStatement_Base::release() throw()
1110 {
1111     OStatement_BASE::release();
1112 }
1113 // -----------------------------------------------------------------------------
1114 void SAL_CALL OStatement::acquire() throw()
1115 {
1116     OStatement_BASE2::acquire();
1117 }
1118 // -----------------------------------------------------------------------------
1119 void SAL_CALL OStatement::release() throw()
1120 {
1121     OStatement_BASE2::release();
1122 }
1123 // -----------------------------------------------------------------------------
1124 OResultSet* OStatement_Base::createResulSet()
1125 {
1126     return new OResultSet(m_aStatementHandle,this);
1127 }
1128 // -----------------------------------------------------------------------------
1129 Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OStatement_Base::getPropertySetInfo(  ) throw(RuntimeException)
1130 {
1131     return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
1132 }
1133 // -----------------------------------------------------------------------------
1134 SQLUINTEGER OStatement_Base::getCursorProperties(SQLINTEGER _nCursorType,sal_Bool bFirst)
1135 {
1136     SQLUINTEGER nValueLen = 0;
1137     try
1138     {
1139         SQLUSMALLINT nAskFor = SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1140         if(SQL_CURSOR_KEYSET_DRIVEN == _nCursorType)
1141             nAskFor = bFirst ? SQL_KEYSET_CURSOR_ATTRIBUTES1 : SQL_KEYSET_CURSOR_ATTRIBUTES2;
1142         else if(SQL_CURSOR_STATIC  == _nCursorType)
1143             nAskFor = bFirst ? SQL_STATIC_CURSOR_ATTRIBUTES1 : SQL_STATIC_CURSOR_ATTRIBUTES2;
1144         else if(SQL_CURSOR_FORWARD_ONLY == _nCursorType)
1145             nAskFor = bFirst ? SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1 : SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2;
1146         else if(SQL_CURSOR_DYNAMIC == _nCursorType)
1147             nAskFor = bFirst ? SQL_DYNAMIC_CURSOR_ATTRIBUTES1 : SQL_DYNAMIC_CURSOR_ATTRIBUTES2;
1148 
1149 
1150         OTools::GetInfo(getOwnConnection(),getConnectionHandle(),nAskFor,nValueLen,NULL);
1151     }
1152     catch(Exception&)
1153     { // we don't want our result destroy here
1154         nValueLen = 0;
1155     }
1156     return nValueLen;
1157 }
1158 // -----------------------------------------------------------------------------
1159