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