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 #include "odbc/OTools.hxx" 31 #include "odbc/OConnection.hxx" 32 #include "odbc/ODatabaseMetaData.hxx" 33 #include "odbc/OFunctions.hxx" 34 #include "odbc/ODriver.hxx" 35 #include "odbc/OStatement.hxx" 36 #include "odbc/OPreparedStatement.hxx" 37 #include <com/sun/star/sdbc/ColumnValue.hpp> 38 #include <com/sun/star/sdbc/XRow.hpp> 39 #include <com/sun/star/lang/DisposedException.hpp> 40 #include <connectivity/dbcharset.hxx> 41 #include <connectivity/FValue.hxx> 42 #include <comphelper/extract.hxx> 43 #include "diagnose_ex.h" 44 #include <connectivity/dbexception.hxx> 45 46 #include <string.h> 47 48 using namespace connectivity::odbc; 49 using namespace connectivity; 50 using namespace dbtools; 51 52 //------------------------------------------------------------------------------ 53 using namespace com::sun::star::uno; 54 using namespace com::sun::star::lang; 55 using namespace com::sun::star::beans; 56 using namespace com::sun::star::sdbc; 57 // -------------------------------------------------------------------------------- 58 OConnection::OConnection(const SQLHANDLE _pDriverHandle,ODBCDriver* _pDriver) 59 : OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this) 60 ,m_pDriver(_pDriver) 61 ,m_pDriverHandleCopy(_pDriverHandle) 62 ,m_nStatementCount(0) 63 ,m_bClosed(sal_True) 64 ,m_bUseCatalog(sal_False) 65 ,m_bUseOldDateFormat(sal_False) 66 ,m_bParameterSubstitution(sal_False) 67 ,m_bIgnoreDriverPrivileges(sal_False) 68 ,m_bPreventGetVersionColumns(sal_False) 69 ,m_bReadOnly(sal_True) 70 { 71 m_pDriver->acquire(); 72 } 73 //----------------------------------------------------------------------------- 74 OConnection::~OConnection() 75 { 76 if(!isClosed( )) 77 close(); 78 79 if ( SQL_NULL_HANDLE != m_aConnectionHandle ) 80 N3SQLFreeHandle( SQL_HANDLE_DBC, m_aConnectionHandle ); 81 m_aConnectionHandle = SQL_NULL_HANDLE; 82 83 m_pDriver->release(); 84 m_pDriver = NULL; 85 } 86 //----------------------------------------------------------------------------- 87 void SAL_CALL OConnection::release() throw() 88 { 89 relase_ChildImpl(); 90 } 91 // ----------------------------------------------------------------------------- 92 oslGenericFunction OConnection::getOdbcFunction(sal_Int32 _nIndex) const 93 { 94 OSL_ENSURE(m_pDriver,"OConnection::getOdbcFunction: m_pDriver is null!"); 95 return m_pDriver->getOdbcFunction(_nIndex); 96 } 97 //----------------------------------------------------------------------------- 98 SQLRETURN OConnection::OpenConnection(const ::rtl::OUString& aConnectStr,sal_Int32 nTimeOut, sal_Bool bSilent) 99 { 100 ::osl::MutexGuard aGuard( m_aMutex ); 101 102 if (m_aConnectionHandle == SQL_NULL_HANDLE) 103 return -1; 104 105 SQLRETURN nSQLRETURN = 0; 106 SDB_ODBC_CHAR szConnStrOut[4096]; 107 SDB_ODBC_CHAR szConnStrIn[2048]; 108 SQLSMALLINT cbConnStrOut; 109 memset(szConnStrOut,'\0',4096); 110 memset(szConnStrIn,'\0',2048); 111 ::rtl::OString aConStr(::rtl::OUStringToOString(aConnectStr,getTextEncoding())); 112 memcpy(szConnStrIn, (SDB_ODBC_CHAR*) aConStr.getStr(), ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength())); 113 114 #ifndef MACOSX 115 N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_LOGIN_TIMEOUT,(SQLPOINTER)nTimeOut,SQL_IS_UINTEGER); 116 // Verbindung aufbauen 117 #endif 118 119 #ifdef LINUX 120 OSL_UNUSED( bSilent ); 121 nSQLRETURN = N3SQLDriverConnect(m_aConnectionHandle, 122 NULL, 123 szConnStrIn, 124 (SQLSMALLINT) ::std::min((sal_Int32)2048,aConStr.getLength()), 125 szConnStrOut, 126 (SQLSMALLINT) (sizeof(szConnStrOut)/sizeof(SDB_ODBC_CHAR)) -1, 127 &cbConnStrOut, 128 SQL_DRIVER_NOPROMPT); 129 if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA || SQL_SUCCESS_WITH_INFO == nSQLRETURN) 130 return nSQLRETURN; 131 #else 132 133 SQLUSMALLINT nSilent = bSilent ? SQL_DRIVER_NOPROMPT : SQL_DRIVER_COMPLETE; 134 nSQLRETURN = N3SQLDriverConnect(m_aConnectionHandle, 135 NULL, 136 szConnStrIn, 137 (SQLSMALLINT) ::std::min<sal_Int32>((sal_Int32)2048,aConStr.getLength()), 138 szConnStrOut, 139 (SQLSMALLINT) sizeof szConnStrOut, 140 &cbConnStrOut, 141 nSilent); 142 if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA) 143 return nSQLRETURN; 144 145 m_bClosed = sal_False; 146 147 #endif //LINUX 148 149 try 150 { 151 ::rtl::OUString aVal; 152 OTools::GetInfo(this,m_aConnectionHandle,SQL_DATA_SOURCE_READ_ONLY,aVal,*this,getTextEncoding()); 153 m_bReadOnly = !aVal.compareToAscii("Y"); 154 } 155 catch(Exception&) 156 { 157 m_bReadOnly = sal_True; 158 } 159 try 160 { 161 ::rtl::OUString sVersion; 162 OTools::GetInfo(this,m_aConnectionHandle,SQL_DRIVER_ODBC_VER,sVersion,*this,getTextEncoding()); 163 m_bUseOldDateFormat = sVersion == ::rtl::OUString::createFromAscii("02.50") || sVersion == ::rtl::OUString::createFromAscii("02.00"); 164 } 165 catch(Exception&) 166 { 167 } 168 169 170 // autocoomit ist immer default 171 172 if (!m_bReadOnly) 173 N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_AUTOCOMMIT,(SQLPOINTER)SQL_AUTOCOMMIT_ON,SQL_IS_INTEGER); 174 175 return nSQLRETURN; 176 } 177 //----------------------------------------------------------------------------- 178 SQLRETURN OConnection::Construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info) throw(SQLException) 179 { 180 m_aConnectionHandle = SQL_NULL_HANDLE; 181 m_sURL = url; 182 setConnectionInfo(info); 183 184 // Connection allozieren 185 N3SQLAllocHandle(SQL_HANDLE_DBC,m_pDriverHandleCopy,&m_aConnectionHandle); 186 if(m_aConnectionHandle == SQL_NULL_HANDLE) 187 throw SQLException(); 188 189 sal_Int32 nLen = url.indexOf(':'); 190 nLen = url.indexOf(':',nLen+1); 191 ::rtl::OUString aDSN(RTL_CONSTASCII_USTRINGPARAM("DSN=")), aUID, aPWD, aSysDrvSettings; 192 aDSN += url.copy(nLen+1); 193 194 const char* pUser = "user"; 195 const char* pTimeout = "Timeout"; 196 const char* pSilent = "Silent"; 197 const char* pPwd = "password"; 198 const char* pUseCatalog = "UseCatalog"; 199 const char* pSysDrv = "SystemDriverSettings"; 200 const char* pCharSet = "CharSet"; 201 const char* pParaName = "ParameterNameSubstitution"; 202 const char* pPrivName = "IgnoreDriverPrivileges"; 203 const char* pVerColName = "PreventGetVersionColumns"; // #i60273# 204 const char* pRetrieving = "IsAutoRetrievingEnabled"; 205 const char* pRetriStmt = "AutoRetrievingStatement"; 206 207 sal_Int32 nTimeout = 20; 208 sal_Bool bSilent = sal_True; 209 const PropertyValue *pBegin = info.getConstArray(); 210 const PropertyValue *pEnd = pBegin + info.getLength(); 211 for(;pBegin != pEnd;++pBegin) 212 { 213 if(!pBegin->Name.compareToAscii(pTimeout)) 214 OSL_VERIFY( pBegin->Value >>= nTimeout ); 215 else if(!pBegin->Name.compareToAscii(pSilent)) 216 OSL_VERIFY( pBegin->Value >>= bSilent ); 217 else if(!pBegin->Name.compareToAscii(pPrivName)) 218 OSL_VERIFY( pBegin->Value >>= m_bIgnoreDriverPrivileges ); 219 else if(!pBegin->Name.compareToAscii(pVerColName)) 220 OSL_VERIFY( pBegin->Value >>= m_bPreventGetVersionColumns ); 221 else if(!pBegin->Name.compareToAscii(pParaName)) 222 OSL_VERIFY( pBegin->Value >>= m_bParameterSubstitution ); 223 else if(!pBegin->Name.compareToAscii(pRetrieving)) 224 { 225 sal_Bool bAutoRetrievingEnabled = sal_False; 226 OSL_VERIFY( pBegin->Value >>= bAutoRetrievingEnabled ); 227 enableAutoRetrievingEnabled(bAutoRetrievingEnabled); 228 } 229 else if(!pBegin->Name.compareToAscii(pRetriStmt)) 230 { 231 ::rtl::OUString sGeneratedValueStatement; 232 OSL_VERIFY( pBegin->Value >>= sGeneratedValueStatement ); 233 setAutoRetrievingStatement(sGeneratedValueStatement); 234 } 235 else if(!pBegin->Name.compareToAscii(pUser)) 236 { 237 OSL_VERIFY( pBegin->Value >>= aUID ); 238 aDSN = aDSN + ::rtl::OUString::createFromAscii(";UID=") + aUID; 239 } 240 else if(!pBegin->Name.compareToAscii(pPwd)) 241 { 242 OSL_VERIFY( pBegin->Value >>= aPWD ); 243 aDSN = aDSN + ::rtl::OUString::createFromAscii(";PWD=") + aPWD; 244 } 245 else if(!pBegin->Name.compareToAscii(pUseCatalog)) 246 { 247 OSL_VERIFY( pBegin->Value >>= m_bUseCatalog ); 248 } 249 else if(!pBegin->Name.compareToAscii(pSysDrv)) 250 { 251 OSL_VERIFY( pBegin->Value >>= aSysDrvSettings ); 252 aDSN += ::rtl::OUString::createFromAscii(";"); 253 aDSN += aSysDrvSettings; 254 } 255 else if(0 == pBegin->Name.compareToAscii(pCharSet)) 256 { 257 ::rtl::OUString sIanaName; 258 OSL_VERIFY( pBegin->Value >>= sIanaName ); 259 260 ::dbtools::OCharsetMap aLookupIanaName; 261 ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.find(sIanaName, ::dbtools::OCharsetMap::IANA()); 262 if (aLookup != aLookupIanaName.end()) 263 m_nTextEncoding = (*aLookup).getEncoding(); 264 else 265 m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW; 266 if(m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW) 267 m_nTextEncoding = osl_getThreadTextEncoding(); 268 } 269 } 270 m_sUser = aUID; 271 272 SQLRETURN nSQLRETURN = OpenConnection(aDSN,nTimeout, bSilent); 273 if (nSQLRETURN == SQL_ERROR || nSQLRETURN == SQL_NO_DATA) 274 { 275 OTools::ThrowException(this,nSQLRETURN,m_aConnectionHandle,SQL_HANDLE_DBC,*this,sal_False); 276 } 277 return nSQLRETURN; 278 } 279 // XServiceInfo 280 // -------------------------------------------------------------------------------- 281 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.odbc.OConnection", "com.sun.star.sdbc.Connection") 282 283 // -------------------------------------------------------------------------------- 284 Reference< XStatement > SAL_CALL OConnection::createStatement( ) throw(SQLException, RuntimeException) 285 { 286 ::osl::MutexGuard aGuard( m_aMutex ); 287 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 288 289 Reference< XStatement > xReturn = new OStatement(this); 290 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 291 return xReturn; 292 } 293 // -------------------------------------------------------------------------------- 294 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 295 { 296 ::osl::MutexGuard aGuard( m_aMutex ); 297 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 298 299 Reference< XPreparedStatement > xReturn = new OPreparedStatement(this,sql); 300 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 301 return xReturn; 302 } 303 // -------------------------------------------------------------------------------- 304 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const ::rtl::OUString& /*sql*/ ) throw(SQLException, RuntimeException) 305 { 306 ::dbtools::throwFeatureNotImplementedException( "XConnection::prepareCall", *this ); 307 return NULL; 308 } 309 // -------------------------------------------------------------------------------- 310 ::rtl::OUString SAL_CALL OConnection::nativeSQL( const ::rtl::OUString& sql ) throw(SQLException, RuntimeException) 311 { 312 ::osl::MutexGuard aGuard( m_aMutex ); 313 314 ::rtl::OString aSql(::rtl::OUStringToOString(sql.getStr(),getTextEncoding())); 315 char pOut[2048]; 316 SQLINTEGER nOutLen; 317 OTools::ThrowException(this,N3SQLNativeSql(m_aConnectionHandle,(SDB_ODBC_CHAR*)aSql.getStr(),aSql.getLength(),(SDB_ODBC_CHAR*)pOut,sizeof pOut - 1,&nOutLen),m_aConnectionHandle,SQL_HANDLE_DBC,*this); 318 return ::rtl::OUString(pOut,nOutLen,getTextEncoding()); 319 } 320 // -------------------------------------------------------------------------------- 321 void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) throw(SQLException, RuntimeException) 322 { 323 ::osl::MutexGuard aGuard( m_aMutex ); 324 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 325 326 327 OTools::ThrowException(this,N3SQLSetConnectAttr(m_aConnectionHandle, 328 SQL_ATTR_AUTOCOMMIT, 329 (SQLPOINTER)((autoCommit) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF) ,SQL_IS_INTEGER), 330 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 331 } 332 // -------------------------------------------------------------------------------- 333 sal_Bool SAL_CALL OConnection::getAutoCommit( ) throw(SQLException, RuntimeException) 334 { 335 ::osl::MutexGuard aGuard( m_aMutex ); 336 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 337 338 339 sal_uInt32 nOption = 0; 340 OTools::ThrowException(this,N3SQLGetConnectAttr(m_aConnectionHandle, 341 SQL_ATTR_AUTOCOMMIT, &nOption,0,0),m_aConnectionHandle,SQL_HANDLE_DBC,*this); 342 return nOption == SQL_AUTOCOMMIT_ON ; 343 } 344 // -------------------------------------------------------------------------------- 345 void SAL_CALL OConnection::commit( ) throw(SQLException, RuntimeException) 346 { 347 ::osl::MutexGuard aGuard( m_aMutex ); 348 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 349 350 351 OTools::ThrowException(this,N3SQLEndTran(SQL_HANDLE_DBC,m_aConnectionHandle,SQL_COMMIT),m_aConnectionHandle,SQL_HANDLE_DBC,*this); 352 } 353 // -------------------------------------------------------------------------------- 354 void SAL_CALL OConnection::rollback( ) throw(SQLException, RuntimeException) 355 { 356 ::osl::MutexGuard aGuard( m_aMutex ); 357 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 358 359 360 OTools::ThrowException(this,N3SQLEndTran(SQL_HANDLE_DBC,m_aConnectionHandle,SQL_ROLLBACK),m_aConnectionHandle,SQL_HANDLE_DBC,*this); 361 } 362 // -------------------------------------------------------------------------------- 363 sal_Bool SAL_CALL OConnection::isClosed( ) throw(SQLException, RuntimeException) 364 { 365 ::osl::MutexGuard aGuard( m_aMutex ); 366 367 return OConnection_BASE::rBHelper.bDisposed; 368 } 369 // -------------------------------------------------------------------------------- 370 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( ) throw(SQLException, RuntimeException) 371 { 372 ::osl::MutexGuard aGuard( m_aMutex ); 373 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 374 375 Reference< XDatabaseMetaData > xMetaData = m_xMetaData; 376 if(!xMetaData.is()) 377 { 378 xMetaData = new ODatabaseMetaData(m_aConnectionHandle,this); 379 m_xMetaData = xMetaData; 380 } 381 382 return xMetaData; 383 } 384 // -------------------------------------------------------------------------------- 385 void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) throw(SQLException, RuntimeException) 386 { 387 ::osl::MutexGuard aGuard( m_aMutex ); 388 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 389 390 391 OTools::ThrowException(this, 392 N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_ACCESS_MODE,reinterpret_cast< SQLPOINTER >( readOnly ),SQL_IS_INTEGER), 393 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 394 } 395 // -------------------------------------------------------------------------------- 396 sal_Bool SAL_CALL OConnection::isReadOnly() throw(SQLException, RuntimeException) 397 { 398 // const member which will initialized only once 399 return m_bReadOnly; 400 } 401 // -------------------------------------------------------------------------------- 402 void SAL_CALL OConnection::setCatalog( const ::rtl::OUString& catalog ) throw(SQLException, RuntimeException) 403 { 404 ::osl::MutexGuard aGuard( m_aMutex ); 405 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 406 407 408 ::rtl::OString aCat(::rtl::OUStringToOString(catalog.getStr(),getTextEncoding())); 409 OTools::ThrowException(this, 410 N3SQLSetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,(SDB_ODBC_CHAR*)aCat.getStr(),SQL_NTS), 411 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 412 } 413 // -------------------------------------------------------------------------------- 414 ::rtl::OUString SAL_CALL OConnection::getCatalog( ) throw(SQLException, RuntimeException) 415 { 416 ::osl::MutexGuard aGuard( m_aMutex ); 417 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 418 419 420 sal_Int32 nValueLen; 421 char pCat[1024]; 422 OTools::ThrowException(this, 423 N3SQLGetConnectAttr(m_aConnectionHandle,SQL_ATTR_CURRENT_CATALOG,(SDB_ODBC_CHAR*)pCat,(sizeof pCat)-1,&nValueLen), 424 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 425 426 return ::rtl::OUString(pCat,nValueLen,getTextEncoding()); 427 } 428 // -------------------------------------------------------------------------------- 429 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 level ) throw(SQLException, RuntimeException) 430 { 431 ::osl::MutexGuard aGuard( m_aMutex ); 432 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 433 434 435 OTools::ThrowException(this,N3SQLSetConnectAttr(m_aConnectionHandle, 436 SQL_ATTR_TXN_ISOLATION, 437 (SQLPOINTER)level,SQL_IS_INTEGER), 438 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 439 } 440 // -------------------------------------------------------------------------------- 441 sal_Int32 SAL_CALL OConnection::getTransactionIsolation( ) throw(SQLException, RuntimeException) 442 { 443 ::osl::MutexGuard aGuard( m_aMutex ); 444 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 445 446 447 sal_Int32 nTxn = 0; 448 SQLINTEGER nValueLen; 449 OTools::ThrowException(this, 450 N3SQLGetConnectAttr(m_aConnectionHandle,SQL_ATTR_TXN_ISOLATION,&nTxn,sizeof nTxn,&nValueLen), 451 m_aConnectionHandle,SQL_HANDLE_DBC,*this); 452 return nTxn; 453 } 454 // -------------------------------------------------------------------------------- 455 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getTypeMap( ) throw(SQLException, RuntimeException) 456 { 457 ::osl::MutexGuard aGuard( m_aMutex ); 458 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 459 460 461 return NULL; 462 } 463 // -------------------------------------------------------------------------------- 464 void SAL_CALL OConnection::setTypeMap( const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException) 465 { 466 ::dbtools::throwFeatureNotImplementedException( "XConnection::setTypeMap", *this ); 467 } 468 // -------------------------------------------------------------------------------- 469 // XCloseable 470 void SAL_CALL OConnection::close( ) throw(SQLException, RuntimeException) 471 { 472 { 473 ::osl::MutexGuard aGuard( m_aMutex ); 474 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 475 476 } 477 dispose(); 478 } 479 // -------------------------------------------------------------------------------- 480 // XWarningsSupplier 481 Any SAL_CALL OConnection::getWarnings( ) throw(SQLException, RuntimeException) 482 { 483 return Any(); 484 } 485 // -------------------------------------------------------------------------------- 486 void SAL_CALL OConnection::clearWarnings( ) throw(SQLException, RuntimeException) 487 { 488 } 489 //-------------------------------------------------------------------- 490 void OConnection::buildTypeInfo() throw( SQLException) 491 { 492 ::osl::MutexGuard aGuard( m_aMutex ); 493 494 Reference< XResultSet> xRs = getMetaData ()->getTypeInfo (); 495 if(xRs.is()) 496 { 497 Reference< XRow> xRow(xRs,UNO_QUERY); 498 // Information for a single SQL type 499 500 ::connectivity::ORowSetValue aValue; 501 ::std::vector<sal_Int32> aTypes; 502 Reference<XResultSetMetaData> xResultSetMetaData = Reference<XResultSetMetaDataSupplier>(xRs,UNO_QUERY)->getMetaData(); 503 sal_Int32 nCount = xResultSetMetaData->getColumnCount(); 504 // Loop on the result set until we reach end of file 505 while (xRs->next ()) 506 { 507 OTypeInfo aInfo; 508 sal_Int32 nPos = 1; 509 if ( aTypes.empty() ) 510 { 511 if ( nCount < 1 ) 512 nCount = 18; 513 aTypes.reserve(nCount+1); 514 aTypes.push_back(-1); 515 for (sal_Int32 j = 1; j <= nCount ; ++j) 516 aTypes.push_back(xResultSetMetaData->getColumnType(j)); 517 } 518 519 aValue.fill(nPos,aTypes[nPos],xRow); 520 aInfo.aTypeName = aValue; 521 ++nPos; 522 aValue.fill(nPos,aTypes[nPos],xRow); 523 aInfo.nType = aValue; 524 ++nPos; 525 aValue.fill(nPos,aTypes[nPos],xRow); 526 aInfo.nPrecision = aValue; 527 ++nPos; 528 aValue.fill(nPos,aTypes[nPos],xRow); 529 aInfo.aLiteralPrefix = aValue; 530 ++nPos; 531 aValue.fill(nPos,aTypes[nPos],xRow); 532 aInfo.aLiteralSuffix = aValue; 533 ++nPos; 534 aValue.fill(nPos,aTypes[nPos],xRow); 535 aInfo.aCreateParams = aValue; 536 ++nPos; 537 aValue.fill(nPos,aTypes[nPos],xRow); 538 aInfo.bNullable = (sal_Int32)aValue == ColumnValue::NULLABLE; 539 ++nPos; 540 aValue.fill(nPos,aTypes[nPos],xRow); 541 aInfo.bCaseSensitive = (sal_Bool)aValue; 542 ++nPos; 543 aValue.fill(nPos,aTypes[nPos],xRow); 544 aInfo.nSearchType = aValue; 545 ++nPos; 546 aValue.fill(nPos,aTypes[nPos],xRow); 547 aInfo.bUnsigned = (sal_Bool)aValue; 548 ++nPos; 549 aValue.fill(nPos,aTypes[nPos],xRow); 550 aInfo.bCurrency = (sal_Bool)aValue; 551 ++nPos; 552 aValue.fill(nPos,aTypes[nPos],xRow); 553 aInfo.bAutoIncrement = (sal_Bool)aValue; 554 ++nPos; 555 aValue.fill(nPos,aTypes[nPos],xRow); 556 aInfo.aLocalTypeName = aValue; 557 ++nPos; 558 aValue.fill(nPos,aTypes[nPos],xRow); 559 aInfo.nMinimumScale = aValue; 560 ++nPos; 561 aValue.fill(nPos,aTypes[nPos],xRow); 562 aInfo.nMaximumScale = aValue; 563 if ( nCount >= 18 ) 564 { 565 nPos = 18; 566 aValue.fill(nPos,aTypes[nPos],xRow); 567 aInfo.nNumPrecRadix = aValue; 568 } 569 570 // check if values are less than zero like it happens in a oracle jdbc driver 571 if( aInfo.nPrecision < 0) 572 aInfo.nPrecision = 0; 573 if( aInfo.nMinimumScale < 0) 574 aInfo.nMinimumScale = 0; 575 if( aInfo.nMaximumScale < 0) 576 aInfo.nMaximumScale = 0; 577 if( aInfo.nNumPrecRadix < 0) 578 aInfo.nNumPrecRadix = 10; 579 580 // Now that we have the type info, save it 581 // in the Hashtable if we don't already have an 582 // entry for this SQL type. 583 584 m_aTypeInfo.push_back(aInfo); 585 } 586 587 // Close the result set/statement. 588 589 Reference< XCloseable> xClose(xRs,UNO_QUERY); 590 if(xClose.is()) 591 xClose->close(); 592 } 593 } 594 //------------------------------------------------------------------------------ 595 void OConnection::disposing() 596 { 597 ::osl::MutexGuard aGuard(m_aMutex); 598 599 OConnection_BASE::disposing(); 600 601 for (::std::map< SQLHANDLE,OConnection*>::iterator aConIter = m_aConnections.begin();aConIter != m_aConnections.end();++aConIter ) 602 aConIter->second->dispose(); 603 604 ::std::map< SQLHANDLE,OConnection*>().swap(m_aConnections); 605 606 if(!m_bClosed) 607 N3SQLDisconnect(m_aConnectionHandle); 608 m_bClosed = sal_True; 609 610 dispose_ChildImpl(); 611 } 612 // ----------------------------------------------------------------------------- 613 OConnection* OConnection::cloneConnection() 614 { 615 return new OConnection(m_pDriverHandleCopy,m_pDriver); 616 } 617 // ----------------------------------------------------------------------------- 618 SQLHANDLE OConnection::createStatementHandle() 619 { 620 OConnection* pConnectionTemp = this; 621 sal_Bool bNew = sal_False; 622 try 623 { 624 sal_Int32 nMaxStatements = getMetaData()->getMaxStatements(); 625 if(nMaxStatements && nMaxStatements <= m_nStatementCount) 626 { 627 OConnection* pConnection = cloneConnection(); 628 pConnection->acquire(); 629 pConnection->Construct(m_sURL,getConnectionInfo()); 630 pConnectionTemp = pConnection; 631 bNew = sal_True; 632 } 633 } 634 catch(SQLException&) 635 { 636 } 637 638 SQLHANDLE aStatementHandle = SQL_NULL_HANDLE; 639 SQLRETURN nRetcode = N3SQLAllocHandle(SQL_HANDLE_STMT,pConnectionTemp->getConnection(),&aStatementHandle); 640 OSL_UNUSED( nRetcode ); 641 ++m_nStatementCount; 642 if(bNew) 643 m_aConnections.insert(::std::map< SQLHANDLE,OConnection*>::value_type(aStatementHandle,pConnectionTemp)); 644 645 return aStatementHandle; 646 647 } 648 // ----------------------------------------------------------------------------- 649 void OConnection::freeStatementHandle(SQLHANDLE& _pHandle) 650 { 651 ::std::map< SQLHANDLE,OConnection*>::iterator aFind = m_aConnections.find(_pHandle); 652 653 N3SQLFreeStmt(_pHandle,SQL_RESET_PARAMS); 654 N3SQLFreeStmt(_pHandle,SQL_UNBIND); 655 N3SQLFreeStmt(_pHandle,SQL_CLOSE); 656 N3SQLFreeHandle(SQL_HANDLE_STMT,_pHandle); 657 658 _pHandle = SQL_NULL_HANDLE; 659 660 if(aFind != m_aConnections.end()) 661 { 662 aFind->second->dispose(); 663 m_aConnections.erase(aFind); 664 } 665 --m_nStatementCount; 666 } 667 // ----------------------------------------------------------------------------- 668 669 670 671