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 #include "SConnection.hxx" 25 26 #include "SDatabaseMetaData.hxx" 27 #include "SDriver.hxx" 28 #include "SStatement.hxx" 29 #include "SPreparedStatement.hxx" 30 #include <com/sun/star/sdbc/ColumnValue.hpp> 31 #include <com/sun/star/sdbc/XRow.hpp> 32 #include <com/sun/star/sdbc/TransactionIsolation.hpp> 33 #include <com/sun/star/lang/DisposedException.hpp> 34 35 using namespace connectivity::skeleton; 36 37 //------------------------------------------------------------------------------ 38 using namespace com::sun::star::uno; 39 using namespace com::sun::star::lang; 40 using namespace com::sun::star::beans; 41 using namespace com::sun::star::sdbc; 42 // -------------------------------------------------------------------------------- 43 OConnection::OConnection(SkeletonDriver* _pDriver) 44 : OSubComponent<OConnection, OConnection_BASE>((::cppu::OWeakObject*)_pDriver, this), 45 OMetaConnection_BASE(m_aMutex), 46 m_pDriver(_pDriver), 47 m_bClosed(sal_False), 48 m_xMetaData(NULL), 49 m_bUseCatalog(sal_False), 50 m_bUseOldDateFormat(sal_False) 51 { 52 m_pDriver->acquire(); 53 } 54 //----------------------------------------------------------------------------- 55 OConnection::~OConnection() 56 { 57 if(!isClosed()) 58 close(); 59 m_pDriver->release(); 60 m_pDriver = NULL; 61 } 62 //----------------------------------------------------------------------------- 63 void SAL_CALL OConnection::release() throw() 64 { 65 relase_ChildImpl(); 66 } 67 // ----------------------------------------------------------------------------- 68 //----------------------------------------------------------------------------- 69 void OConnection::construct(const ::rtl::OUString& url,const Sequence< PropertyValue >& info) throw(SQLException) 70 { 71 osl_incrementInterlockedCount( &m_refCount ); 72 73 // some example code how to get the information out of the sequence 74 75 sal_Int32 nLen = url.indexOf(':'); 76 nLen = url.indexOf(':',nLen+1); 77 ::rtl::OUString aDSN(RTL_CONSTASCII_USTRINGPARAM("DSN=")), aUID, aPWD, aSysDrvSettings; 78 aDSN += url.copy(nLen+1); 79 80 const char* pUser = "user"; 81 const char* pTimeout = "Timeout"; 82 const char* pSilent = "Silent"; 83 const char* pPwd = "password"; 84 const char* pUseCatalog = "UseCatalog"; 85 const char* pSysDrv = "SystemDriverSettings"; 86 87 sal_Int32 nTimeout = 20; 88 sal_Bool bSilent = sal_True; 89 const PropertyValue *pBegin = info.getConstArray(); 90 const PropertyValue *pEnd = pBegin + info.getLength(); 91 for(;pBegin != pEnd;++pBegin) 92 { 93 if(!pBegin->Name.compareToAscii(pTimeout)) 94 pBegin->Value >>= nTimeout; 95 else if(!pBegin->Name.compareToAscii(pSilent)) 96 pBegin->Value >>= bSilent; 97 else if(!pBegin->Name.compareToAscii(pUser)) 98 { 99 pBegin->Value >>= aUID; 100 aDSN = aDSN + ::rtl::OUString::createFromAscii(";UID=") + aUID; 101 } 102 else if(!pBegin->Name.compareToAscii(pPwd)) 103 { 104 pBegin->Value >>= aPWD; 105 aDSN = aDSN + ::rtl::OUString::createFromAscii(";PWD=") + aPWD; 106 } 107 else if(!pBegin->Name.compareToAscii(pUseCatalog)) 108 { 109 pBegin->Value >>= m_bUseCatalog; 110 } 111 else if(!pBegin->Name.compareToAscii(pSysDrv)) 112 { 113 pBegin->Value >>= aSysDrvSettings; 114 aDSN += ::rtl::OUString::createFromAscii(";"); 115 aDSN += aSysDrvSettings; 116 } 117 } 118 m_sUser = aUID; 119 120 osl_decrementInterlockedCount( &m_refCount ); 121 } 122 // XServiceInfo 123 // -------------------------------------------------------------------------------- 124 IMPLEMENT_SERVICE_INFO(OConnection, "com.sun.star.sdbc.drivers.skeleton.OConnection", "com.sun.star.sdbc.Connection") 125 126 // -------------------------------------------------------------------------------- 127 Reference< XStatement > SAL_CALL OConnection::createStatement( ) throw(SQLException, RuntimeException) 128 { 129 ::osl::MutexGuard aGuard( m_aMutex ); 130 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 131 132 // create a statement 133 // the statement can only be executed once 134 Reference< XStatement > xReturn = new OStatement(this); 135 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 136 return xReturn; 137 } 138 // -------------------------------------------------------------------------------- 139 Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException) 140 { 141 ::osl::MutexGuard aGuard( m_aMutex ); 142 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 143 144 // the pre 145 if(m_aTypeInfo.empty()) 146 buildTypeInfo(); 147 148 // create a statement 149 // the statement can only be executed more than once 150 Reference< XPreparedStatement > xReturn = new OPreparedStatement(this,m_aTypeInfo,_sSql); 151 m_aStatements.push_back(WeakReferenceHelper(xReturn)); 152 return xReturn; 153 } 154 // -------------------------------------------------------------------------------- 155 Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException) 156 { 157 ::osl::MutexGuard aGuard( m_aMutex ); 158 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 159 160 // not implemented yet :-) a task to do 161 return NULL; 162 } 163 // -------------------------------------------------------------------------------- 164 ::rtl::OUString SAL_CALL OConnection::nativeSQL( const ::rtl::OUString& _sSql ) throw(SQLException, RuntimeException) 165 { 166 ::osl::MutexGuard aGuard( m_aMutex ); 167 // when you need to transform SQL92 to you driver specific you can do it here 168 169 return _sSql; 170 } 171 // -------------------------------------------------------------------------------- 172 void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) throw(SQLException, RuntimeException) 173 { 174 ::osl::MutexGuard aGuard( m_aMutex ); 175 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 176 // here you have to set your commit mode please have a look at the jdbc documentation to get a clear explanation 177 } 178 // -------------------------------------------------------------------------------- 179 sal_Bool SAL_CALL OConnection::getAutoCommit( ) throw(SQLException, RuntimeException) 180 { 181 ::osl::MutexGuard aGuard( m_aMutex ); 182 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 183 // you have to distinguish which if you are in autocommit mode or not 184 // at normal case true should be fine here 185 186 return sal_True; 187 } 188 // -------------------------------------------------------------------------------- 189 void SAL_CALL OConnection::commit( ) throw(SQLException, RuntimeException) 190 { 191 ::osl::MutexGuard aGuard( m_aMutex ); 192 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 193 194 // when you database does support transactions you should commit here 195 } 196 // -------------------------------------------------------------------------------- 197 void SAL_CALL OConnection::rollback( ) throw(SQLException, RuntimeException) 198 { 199 ::osl::MutexGuard aGuard( m_aMutex ); 200 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 201 202 203 // same as commit but for the other case 204 } 205 // -------------------------------------------------------------------------------- 206 sal_Bool SAL_CALL OConnection::isClosed( ) throw(SQLException, RuntimeException) 207 { 208 ::osl::MutexGuard aGuard( m_aMutex ); 209 210 // just simple -> we are close when we are disposed taht means someone called dispose(); (XComponent) 211 return OConnection_BASE::rBHelper.bDisposed; 212 } 213 // -------------------------------------------------------------------------------- 214 Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( ) throw(SQLException, RuntimeException) 215 { 216 ::osl::MutexGuard aGuard( m_aMutex ); 217 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 218 219 // here we have to create the class with biggest interface 220 // The answer is 42 :-) 221 Reference< XDatabaseMetaData > xMetaData = m_xMetaData; 222 if(!xMetaData.is()) 223 { 224 xMetaData = new ODatabaseMetaData(this); // need the connection because it can return it 225 m_xMetaData = xMetaData; 226 } 227 228 return xMetaData; 229 } 230 // -------------------------------------------------------------------------------- 231 void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) throw(SQLException, RuntimeException) 232 { 233 ::osl::MutexGuard aGuard( m_aMutex ); 234 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 235 236 // set you connection to readonly 237 } 238 // -------------------------------------------------------------------------------- 239 sal_Bool SAL_CALL OConnection::isReadOnly( ) throw(SQLException, RuntimeException) 240 { 241 ::osl::MutexGuard aGuard( m_aMutex ); 242 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 243 244 // return if your connection to readonly 245 return sal_False; 246 } 247 // -------------------------------------------------------------------------------- 248 void SAL_CALL OConnection::setCatalog( const ::rtl::OUString& catalog ) throw(SQLException, RuntimeException) 249 { 250 ::osl::MutexGuard aGuard( m_aMutex ); 251 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 252 253 // if your database doesn't work with catalogs you go to next method otherwise you kjnow what to do 254 } 255 // -------------------------------------------------------------------------------- 256 ::rtl::OUString SAL_CALL OConnection::getCatalog( ) throw(SQLException, RuntimeException) 257 { 258 ::osl::MutexGuard aGuard( m_aMutex ); 259 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 260 261 262 // return your current catalog 263 return ::rtl::OUString(); 264 } 265 // -------------------------------------------------------------------------------- 266 void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 level ) throw(SQLException, RuntimeException) 267 { 268 ::osl::MutexGuard aGuard( m_aMutex ); 269 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 270 271 // set your isolation level 272 // please have a look at @see com.sun.star.sdbc.TransactionIsolation 273 } 274 // -------------------------------------------------------------------------------- 275 sal_Int32 SAL_CALL OConnection::getTransactionIsolation( ) throw(SQLException, RuntimeException) 276 { 277 ::osl::MutexGuard aGuard( m_aMutex ); 278 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 279 280 281 // please have a look at @see com.sun.star.sdbc.TransactionIsolation 282 return TransactionIsolation::NONE; 283 } 284 // -------------------------------------------------------------------------------- 285 Reference< ::com::sun::star::container::XNameAccess > SAL_CALL OConnection::getTypeMap( ) throw(SQLException, RuntimeException) 286 { 287 ::osl::MutexGuard aGuard( m_aMutex ); 288 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 289 290 // if your driver has special database types you can return it here 291 292 return NULL; 293 } 294 // -------------------------------------------------------------------------------- 295 void SAL_CALL OConnection::setTypeMap( const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException) 296 { 297 // the other way around 298 } 299 // -------------------------------------------------------------------------------- 300 // XCloseable 301 void SAL_CALL OConnection::close( ) throw(SQLException, RuntimeException) 302 { 303 // we just dispose us 304 { 305 ::osl::MutexGuard aGuard( m_aMutex ); 306 checkDisposed(OConnection_BASE::rBHelper.bDisposed); 307 308 } 309 dispose(); 310 } 311 // -------------------------------------------------------------------------------- 312 // XWarningsSupplier 313 Any SAL_CALL OConnection::getWarnings( ) throw(SQLException, RuntimeException) 314 { 315 // when you collected some warnings -> return it 316 return Any(); 317 } 318 // -------------------------------------------------------------------------------- 319 void SAL_CALL OConnection::clearWarnings( ) throw(SQLException, RuntimeException) 320 { 321 // you should clear your collected warnings here 322 } 323 //-------------------------------------------------------------------- 324 void OConnection::buildTypeInfo() throw( SQLException) 325 { 326 ::osl::MutexGuard aGuard( m_aMutex ); 327 328 Reference< XResultSet> xRs = getMetaData ()->getTypeInfo (); 329 Reference< XRow> xRow(xRs,UNO_QUERY); 330 // Information for a single SQL type 331 332 // Loop on the result set until we reach end of file 333 334 while (xRs->next ()) 335 { 336 OTypeInfo aInfo; 337 aInfo.aTypeName = xRow->getString (1); 338 aInfo.nType = xRow->getShort (2); 339 aInfo.nPrecision = xRow->getInt (3); 340 aInfo.aLiteralPrefix = xRow->getString (4); 341 aInfo.aLiteralSuffix = xRow->getString (5); 342 aInfo.aCreateParams = xRow->getString (6); 343 aInfo.bNullable = xRow->getBoolean (7) == ColumnValue::NULLABLE; 344 aInfo.bCaseSensitive = xRow->getBoolean (8); 345 aInfo.nSearchType = xRow->getShort (9); 346 aInfo.bUnsigned = xRow->getBoolean (10); 347 aInfo.bCurrency = xRow->getBoolean (11); 348 aInfo.bAutoIncrement = xRow->getBoolean (12); 349 aInfo.aLocalTypeName = xRow->getString (13); 350 aInfo.nMinimumScale = xRow->getShort (14); 351 aInfo.nMaximumScale = xRow->getShort (15); 352 aInfo.nNumPrecRadix = (sal_Int16)xRow->getInt(18); 353 354 355 356 // Now that we have the type info, save it 357 // in the Hashtable if we don't already have an 358 // entry for this SQL type. 359 360 m_aTypeInfo.push_back(aInfo); 361 } 362 363 // Close the result set/statement. 364 365 Reference< XCloseable> xClose(xRs,UNO_QUERY); 366 xClose->close(); 367 } 368 //------------------------------------------------------------------------------ 369 void OConnection::disposing() 370 { 371 // we noticed that we should be destroied in near future so we have to dispose our statements 372 ::osl::MutexGuard aGuard(m_aMutex); 373 374 for (OWeakRefArray::iterator i = m_aStatements.begin(); m_aStatements.end() != i; ++i) 375 { 376 Reference< XComponent > xComp(i->get(), UNO_QUERY); 377 if (xComp.is()) 378 xComp->dispose(); 379 } 380 m_aStatements.clear(); 381 382 m_bClosed = sal_True; 383 m_xMetaData = ::com::sun::star::uno::WeakReference< ::com::sun::star::sdbc::XDatabaseMetaData>(); 384 385 dispose_ChildImpl(); 386 OConnection_BASE::disposing(); 387 } 388 // ----------------------------------------------------------------------------- 389 390 391 392