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