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