1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 #include <sal/log.hxx> 22 23 #include <map> 24 #include <utility> 25 26 #include <string.h> 27 #include "RowSet.hxx" 28 #include <stringconstants.hxx> 29 #include <sdbcoretools.hxx> 30 #include <SingleSelectQueryComposer.hxx> 31 #include "CRowSetColumn.hxx" 32 #include "CRowSetDataColumn.hxx" 33 #include "RowSetCache.hxx" 34 #include <strings.hrc> 35 #include <core_resource.hxx> 36 #include <tablecontainer.hxx> 37 38 #include <com/sun/star/beans/PropertyAttribute.hpp> 39 #include <com/sun/star/container/XChild.hpp> 40 #include <com/sun/star/lang/DisposedException.hpp> 41 #include <com/sun/star/sdb/CommandType.hpp> 42 #include <com/sun/star/sdb/DatabaseContext.hpp> 43 #include <com/sun/star/sdb/ErrorCondition.hpp> 44 #include <com/sun/star/sdb/RowChangeAction.hpp> 45 #include <com/sun/star/sdb/RowSetVetoException.hpp> 46 #include <com/sun/star/sdb/XCompletedConnection.hpp> 47 #include <com/sun/star/sdb/XParametersSupplier.hpp> 48 #include <com/sun/star/sdb/XQueriesSupplier.hpp> 49 #include <com/sun/star/sdbc/FetchDirection.hpp> 50 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp> 51 #include <com/sun/star/sdbc/XDataSource.hpp> 52 #include <com/sun/star/sdbc/XDriverAccess.hpp> 53 #include <com/sun/star/sdbcx/CompareBookmark.hpp> 54 #include <com/sun/star/sdbcx/Privilege.hpp> 55 #include <com/sun/star/sdbcx/XDataDefinitionSupplier.hpp> 56 #include <com/sun/star/uno/XNamingService.hpp> 57 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 58 59 #include <comphelper/property.hxx> 60 #include <comphelper/seqstream.hxx> 61 #include <comphelper/sequence.hxx> 62 #include <comphelper/types.hxx> 63 #include <comphelper/uno3.hxx> 64 #include <connectivity/BlobHelper.hxx> 65 #include <connectivity/dbconversion.hxx> 66 #include <connectivity/dbexception.hxx> 67 #include <connectivity/dbtools.hxx> 68 #include <cppuhelper/exc_hlp.hxx> 69 #include <cppuhelper/interfacecontainer.h> 70 #include <cppuhelper/supportsservice.hxx> 71 #include <cppuhelper/typeprovider.hxx> 72 #include <unotools/syslocale.hxx> 73 #include <tools/debug.hxx> 74 #include <tools/diagnose_ex.h> 75 #include <tools/solar.h> 76 #include <unotools/configmgr.hxx> 77 78 using namespace utl; 79 using namespace dbaccess; 80 using namespace connectivity; 81 using namespace comphelper; 82 using namespace dbtools; 83 using namespace ::com::sun::star; 84 using namespace ::com::sun::star::uno; 85 using namespace ::com::sun::star::beans; 86 using namespace ::com::sun::star::sdbc; 87 using namespace ::com::sun::star::sdb; 88 using namespace ::com::sun::star::sdbcx; 89 using namespace ::com::sun::star::container; 90 using namespace ::com::sun::star::lang; 91 using namespace ::com::sun::star::task; 92 using namespace ::com::sun::star::util; 93 using namespace ::cppu; 94 using namespace ::osl; 95 96 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* 97 com_sun_star_comp_dba_ORowSet_get_implementation(css::uno::XComponentContext* context, 98 css::uno::Sequence<css::uno::Any> const &) 99 { 100 return cppu::acquire(new ORowSet(context)); 101 } 102 103 #define NOTIFY_LISTENERS_CHECK(_rListeners,T,method) \ 104 std::vector< Reference< XInterface > > aListenerSeq = _rListeners.getElements(); \ 105 \ 106 _rGuard.clear(); \ 107 bool bCheck = std::all_of(aListenerSeq.rbegin(), aListenerSeq.rend(), \ 108 [&aEvt](Reference<XInterface>& rxItem) { \ 109 try \ 110 { \ 111 return static_cast<bool>(static_cast<T*>(rxItem.get())->method(aEvt)); \ 112 } \ 113 catch( RuntimeException& ) \ 114 { \ 115 return true; \ 116 } \ 117 }); \ 118 _rGuard.reset(); 119 120 121 namespace dbaccess 122 { 123 ORowSet::ORowSet( const Reference< css::uno::XComponentContext >& _rxContext ) 124 :ORowSet_BASE1(m_aMutex) 125 ,ORowSetBase( _rxContext, ORowSet_BASE1::rBHelper, &m_aMutex ) 126 ,m_aPrematureParamValues(new ORowSetValueVector) 127 ,m_aParameterValueForCache(new ORowSetValueVector) 128 ,m_aRowsetListeners(*m_pMutex) 129 ,m_aApproveListeners(*m_pMutex) 130 ,m_aRowsChangeListener(*m_pMutex) 131 ,m_nFetchDirection(FetchDirection::FORWARD) 132 ,m_nFetchSize(50) 133 ,m_nMaxFieldSize(0) 134 ,m_nMaxRows(0) 135 ,m_nQueryTimeOut(0) 136 ,m_nCommandType(CommandType::COMMAND) 137 ,m_nTransactionIsolation(0) 138 ,m_nPrivileges(0) 139 ,m_nLastKnownRowCount(0) 140 ,m_nInAppend(0) 141 ,m_bInsertingRow(false) 142 ,m_bLastKnownRowCountFinal(false) 143 ,m_bUseEscapeProcessing(true) 144 ,m_bApplyFilter(false) 145 ,m_bCommandFacetsDirty( true ) 146 ,m_bParametersDirty( true ) 147 ,m_bModified(false) 148 ,m_bRebuildConnOnExecute(false) 149 ,m_bIsBookmarkable(true) 150 ,m_bNew(false) 151 ,m_bCanUpdateInsertedRows(true) 152 ,m_bOwnConnection(false) 153 ,m_bPropChangeNotifyEnabled(true) 154 { 155 m_nResultSetType = ResultSetType::SCROLL_SENSITIVE; 156 m_nResultSetConcurrency = ResultSetConcurrency::UPDATABLE; 157 m_pMySelf = this; 158 m_aActiveConnection <<= m_xActiveConnection; 159 160 sal_Int32 const nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; 161 sal_Int32 const nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; 162 sal_Int32 const nBT = PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT; 163 164 m_aPrematureParamValues->get().resize( 0 ); 165 166 // sdb.RowSet Properties 167 registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT|PropertyAttribute::BOUND, &m_aActiveConnection, cppu::UnoType<XConnection>::get()); 168 registerProperty(PROPERTY_DATASOURCENAME, PROPERTY_ID_DATASOURCENAME, PropertyAttribute::BOUND, &m_aDataSourceName, ::cppu::UnoType<OUString>::get()); 169 registerProperty(PROPERTY_COMMAND, PROPERTY_ID_COMMAND, PropertyAttribute::BOUND, &m_aCommand, ::cppu::UnoType<OUString>::get()); 170 registerProperty(PROPERTY_COMMAND_TYPE, PROPERTY_ID_COMMAND_TYPE, PropertyAttribute::BOUND, &m_nCommandType, ::cppu::UnoType<sal_Int32>::get()); 171 registerProperty(PROPERTY_ACTIVECOMMAND, PROPERTY_ID_ACTIVECOMMAND, nRBT, &m_aActiveCommand, ::cppu::UnoType<OUString>::get()); 172 registerProperty(PROPERTY_IGNORERESULT, PROPERTY_ID_IGNORERESULT, PropertyAttribute::BOUND, &m_bIgnoreResult, cppu::UnoType<bool>::get()); 173 registerProperty(PROPERTY_FILTER, PROPERTY_ID_FILTER, PropertyAttribute::BOUND, &m_aFilter, ::cppu::UnoType<OUString>::get()); 174 registerProperty(PROPERTY_HAVING_CLAUSE, PROPERTY_ID_HAVING_CLAUSE, PropertyAttribute::BOUND, &m_aHavingClause, ::cppu::UnoType<OUString>::get()); 175 registerProperty(PROPERTY_GROUP_BY, PROPERTY_ID_GROUP_BY, PropertyAttribute::BOUND, &m_aGroupBy, ::cppu::UnoType<OUString>::get()); 176 registerProperty(PROPERTY_APPLYFILTER, PROPERTY_ID_APPLYFILTER, PropertyAttribute::BOUND, &m_bApplyFilter, cppu::UnoType<bool>::get()); 177 registerProperty(PROPERTY_ORDER, PROPERTY_ID_ORDER, PropertyAttribute::BOUND, &m_aOrder, ::cppu::UnoType<OUString>::get()); 178 registerProperty(PROPERTY_PRIVILEGES, PROPERTY_ID_PRIVILEGES, nRT, &m_nPrivileges, ::cppu::UnoType<sal_Int32>::get()); 179 registerProperty(PROPERTY_ISMODIFIED, PROPERTY_ID_ISMODIFIED, nBT, &m_bModified, cppu::UnoType<bool>::get()); 180 registerProperty(PROPERTY_ISNEW, PROPERTY_ID_ISNEW, nRBT, &m_bNew, cppu::UnoType<bool>::get()); 181 registerProperty(PROPERTY_SINGLESELECTQUERYCOMPOSER,PROPERTY_ID_SINGLESELECTQUERYCOMPOSER, nRT, &m_xComposer, cppu::UnoType<XSingleSelectQueryComposer>::get()); 182 183 // sdbcx.ResultSet Properties 184 registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarkable, cppu::UnoType<bool>::get()); 185 registerProperty(PROPERTY_CANUPDATEINSERTEDROWS,PROPERTY_ID_CANUPDATEINSERTEDROWS, nRT, &m_bCanUpdateInsertedRows, cppu::UnoType<bool>::get()); 186 // sdbc.ResultSet Properties 187 registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::TRANSIENT, &m_nResultSetConcurrency,::cppu::UnoType<sal_Int32>::get()); 188 registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::TRANSIENT, &m_nResultSetType, ::cppu::UnoType<sal_Int32>::get()); 189 registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::cppu::UnoType<sal_Int32>::get()); 190 registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::cppu::UnoType<sal_Int32>::get()); 191 192 // sdbc.RowSet Properties 193 registerProperty(PROPERTY_URL, PROPERTY_ID_URL, 0, &m_aURL, ::cppu::UnoType<OUString>::get()); 194 registerProperty(PROPERTY_TRANSACTIONISOLATION, PROPERTY_ID_TRANSACTIONISOLATION, PropertyAttribute::TRANSIENT, &m_nTransactionIsolation,::cppu::UnoType<sal_Int32>::get()); 195 registerMayBeVoidProperty(PROPERTY_TYPEMAP, PROPERTY_ID_TYPEMAP, PropertyAttribute::MAYBEVOID|PropertyAttribute::TRANSIENT, &m_aTypeMap, cppu::UnoType<XNameAccess>::get()); 196 registerProperty(PROPERTY_ESCAPE_PROCESSING,PROPERTY_ID_ESCAPE_PROCESSING, PropertyAttribute::BOUND, &m_bUseEscapeProcessing,cppu::UnoType<bool>::get() ); 197 registerProperty(PROPERTY_QUERYTIMEOUT, PROPERTY_ID_QUERYTIMEOUT, PropertyAttribute::TRANSIENT, &m_nQueryTimeOut, ::cppu::UnoType<sal_Int32>::get()); 198 registerProperty(PROPERTY_MAXFIELDSIZE, PROPERTY_ID_MAXFIELDSIZE, PropertyAttribute::TRANSIENT, &m_nMaxFieldSize, ::cppu::UnoType<sal_Int32>::get()); 199 registerProperty(PROPERTY_MAXROWS, PROPERTY_ID_MAXROWS, 0, &m_nMaxRows, ::cppu::UnoType<sal_Int32>::get() ); 200 registerProperty(PROPERTY_USER, PROPERTY_ID_USER, PropertyAttribute::TRANSIENT, &m_aUser, ::cppu::UnoType<OUString>::get()); 201 registerProperty(PROPERTY_PASSWORD, PROPERTY_ID_PASSWORD, PropertyAttribute::TRANSIENT, &m_aPassword, ::cppu::UnoType<OUString>::get()); 202 203 registerProperty(PROPERTY_UPDATE_CATALOGNAME, PROPERTY_ID_UPDATE_CATALOGNAME, PropertyAttribute::BOUND, &m_aUpdateCatalogName, ::cppu::UnoType<OUString>::get()); 204 registerProperty(PROPERTY_UPDATE_SCHEMANAME, PROPERTY_ID_UPDATE_SCHEMANAME, PropertyAttribute::BOUND, &m_aUpdateSchemaName, ::cppu::UnoType<OUString>::get()); 205 registerProperty(PROPERTY_UPDATE_TABLENAME, PROPERTY_ID_UPDATE_TABLENAME, PropertyAttribute::BOUND, &m_aUpdateTableName, ::cppu::UnoType<OUString>::get()); 206 207 // ??? 208 registerProperty(PROPERTY_CHANGE_NOTIFICATION_ENABLED, PROPERTY_ID_PROPCHANGE_NOTIFY, PropertyAttribute::BOUND, &m_bPropChangeNotifyEnabled, cppu::UnoType<bool>::get()); 209 } 210 211 ORowSet::~ORowSet() 212 { 213 if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose ) 214 { 215 SAL_WARN("dbaccess", "Please check who doesn't dispose this component!"); 216 osl_atomic_increment( &m_refCount ); 217 dispose(); 218 } 219 } 220 221 void ORowSet::getPropertyDefaultByHandle( sal_Int32 _nHandle, Any& _rDefault ) const 222 { 223 switch( _nHandle ) 224 { 225 case PROPERTY_ID_COMMAND_TYPE: 226 _rDefault <<= static_cast<sal_Int32>(CommandType::COMMAND); 227 break; 228 case PROPERTY_ID_IGNORERESULT: 229 _rDefault <<= false; 230 break; 231 case PROPERTY_ID_APPLYFILTER: 232 _rDefault <<= false; 233 break; 234 case PROPERTY_ID_ISMODIFIED: 235 _rDefault <<= false; 236 break; 237 case PROPERTY_ID_ISBOOKMARKABLE: 238 _rDefault <<= true; 239 break; 240 case PROPERTY_ID_CANUPDATEINSERTEDROWS: 241 _rDefault <<= true; 242 break; 243 case PROPERTY_ID_RESULTSETTYPE: 244 _rDefault <<= ResultSetType::SCROLL_INSENSITIVE; 245 break; 246 case PROPERTY_ID_RESULTSETCONCURRENCY: 247 _rDefault <<= ResultSetConcurrency::UPDATABLE; 248 break; 249 case PROPERTY_ID_FETCHDIRECTION: 250 _rDefault <<= FetchDirection::FORWARD; 251 break; 252 case PROPERTY_ID_FETCHSIZE: 253 _rDefault <<= static_cast<sal_Int32>(1); 254 break; 255 case PROPERTY_ID_ESCAPE_PROCESSING: 256 _rDefault <<= true; 257 break; 258 case PROPERTY_ID_MAXROWS: 259 _rDefault <<= sal_Int32( 0 ); 260 break; 261 case PROPERTY_ID_FILTER: 262 case PROPERTY_ID_HAVING_CLAUSE: 263 case PROPERTY_ID_GROUP_BY: 264 case PROPERTY_ID_ORDER: 265 case PROPERTY_ID_UPDATE_CATALOGNAME: 266 case PROPERTY_ID_UPDATE_SCHEMANAME: 267 case PROPERTY_ID_UPDATE_TABLENAME: 268 _rDefault <<= OUString(); 269 break; 270 } 271 } 272 273 void SAL_CALL ORowSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) 274 { 275 switch(nHandle) 276 { 277 case PROPERTY_ID_ISMODIFIED: 278 m_bModified = cppu::any2bool(rValue); 279 break; 280 case PROPERTY_ID_FETCHDIRECTION: 281 if( m_nResultSetType == ResultSetType::FORWARD_ONLY) 282 throw Exception("resultsettype is FORWARD_ONLY", nullptr); 283 [[fallthrough]]; 284 default: 285 OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); 286 } 287 288 if ( ( nHandle == PROPERTY_ID_ACTIVE_CONNECTION ) 289 || ( nHandle == PROPERTY_ID_DATASOURCENAME ) 290 || ( nHandle == PROPERTY_ID_COMMAND ) 291 || ( nHandle == PROPERTY_ID_COMMAND_TYPE ) 292 || ( nHandle == PROPERTY_ID_IGNORERESULT ) 293 || ( nHandle == PROPERTY_ID_FILTER ) 294 || ( nHandle == PROPERTY_ID_HAVING_CLAUSE ) 295 || ( nHandle == PROPERTY_ID_GROUP_BY ) 296 || ( nHandle == PROPERTY_ID_APPLYFILTER ) 297 || ( nHandle == PROPERTY_ID_ORDER ) 298 || ( nHandle == PROPERTY_ID_URL ) 299 || ( nHandle == PROPERTY_ID_USER ) 300 ) 301 { 302 m_bCommandFacetsDirty = true; 303 } 304 305 306 switch(nHandle) 307 { 308 case PROPERTY_ID_ACTIVE_CONNECTION: 309 // the new connection 310 { 311 assert(m_aActiveConnection == rValue); 312 Reference< XConnection > xNewConnection(m_aActiveConnection,UNO_QUERY); 313 setActiveConnection(xNewConnection, false); 314 } 315 316 m_bOwnConnection = false; 317 m_bRebuildConnOnExecute = false; 318 break; 319 320 case PROPERTY_ID_DATASOURCENAME: 321 if(!m_xStatement.is()) 322 { 323 Reference< XConnection > xNewConn; 324 Any aNewConn; 325 aNewConn <<= xNewConn; 326 setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); 327 } 328 else 329 m_bRebuildConnOnExecute = true; 330 break; 331 case PROPERTY_ID_FETCHSIZE: 332 if(m_pCache) 333 { 334 m_pCache->setFetchSize(m_nFetchSize); 335 fireRowcount(); 336 } 337 break; 338 case PROPERTY_ID_URL: 339 // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ? 340 if (m_aDataSourceName.isEmpty()) 341 { 342 // are we active at the moment ? 343 if (m_xStatement.is()) 344 // yes -> the next execute needs to rebuild our connection because of this new property 345 m_bRebuildConnOnExecute = true; 346 else 347 { // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore 348 Reference< XConnection > xNewConn; 349 Any aNewConn; 350 aNewConn <<= xNewConn; 351 setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION, aNewConn); 352 } 353 } 354 m_bOwnConnection = true; 355 break; 356 case PROPERTY_ID_TYPEMAP: 357 m_xTypeMap.set(m_aTypeMap, css::uno::UNO_QUERY); 358 break; 359 case PROPERTY_ID_PROPCHANGE_NOTIFY: 360 m_bPropChangeNotifyEnabled = ::cppu::any2bool(rValue); 361 break; 362 default: 363 break; 364 }; 365 } 366 367 void SAL_CALL ORowSet::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const 368 { 369 if(m_pCache) 370 { 371 switch(nHandle) 372 { 373 case PROPERTY_ID_ISMODIFIED: 374 rValue <<= m_bModified; 375 break; 376 case PROPERTY_ID_ISNEW: 377 rValue <<= m_bNew; 378 break; 379 case PROPERTY_ID_PRIVILEGES: 380 rValue <<= m_pCache->m_nPrivileges; 381 break; 382 case PROPERTY_ID_ACTIVE_CONNECTION: 383 rValue <<= m_xActiveConnection; 384 break; 385 case PROPERTY_ID_TYPEMAP: 386 rValue <<= m_xTypeMap; 387 break; 388 default: 389 ORowSetBase::getFastPropertyValue(rValue,nHandle); 390 } 391 } 392 else 393 { 394 switch(nHandle) 395 { 396 case PROPERTY_ID_ACTIVE_CONNECTION: 397 rValue <<= m_xActiveConnection; 398 break; 399 case PROPERTY_ID_TYPEMAP: 400 rValue <<= m_xTypeMap; 401 break; 402 case PROPERTY_ID_PROPCHANGE_NOTIFY: 403 rValue <<= m_bPropChangeNotifyEnabled; 404 break; 405 default: 406 ORowSetBase::getFastPropertyValue(rValue,nHandle); 407 } 408 } 409 } 410 411 // css::XTypeProvider 412 Sequence< Type > SAL_CALL ORowSet::getTypes() 413 { 414 OTypeCollection aTypes(cppu::UnoType<XPropertySet>::get(), 415 cppu::UnoType<XFastPropertySet>::get(), 416 cppu::UnoType<XMultiPropertySet>::get(), 417 ::comphelper::concatSequences(ORowSet_BASE1::getTypes(),ORowSetBase::getTypes())); 418 return aTypes.getTypes(); 419 } 420 421 Sequence< sal_Int8 > SAL_CALL ORowSet::getImplementationId() 422 { 423 return css::uno::Sequence<sal_Int8>(); 424 } 425 426 // css::XInterface 427 Any SAL_CALL ORowSet::queryInterface( const Type & rType ) 428 { 429 return ORowSet_BASE1::queryInterface( rType); 430 } 431 432 void SAL_CALL ORowSet::acquire() throw() 433 { 434 ORowSet_BASE1::acquire(); 435 } 436 437 void SAL_CALL ORowSet::release() throw() 438 { 439 ORowSet_BASE1::release(); 440 } 441 442 // css::XUnoTunnel 443 sal_Int64 SAL_CALL ORowSet::getSomething( const Sequence< sal_Int8 >& rId ) 444 { 445 if (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 446 return reinterpret_cast<sal_Int64>(this); 447 448 return 0; 449 } 450 451 Sequence< sal_Int8 > ORowSet::getUnoTunnelImplementationId() 452 { 453 static ::cppu::OImplementationId s_Id; 454 455 return s_Id.getImplementationId(); 456 } 457 458 // css::XAggregation 459 Any SAL_CALL ORowSet::queryAggregation( const Type& rType ) 460 { 461 Any aRet(ORowSetBase::queryInterface(rType)); 462 if (!aRet.hasValue()) 463 aRet = ORowSet_BASE1::queryAggregation(rType); 464 return aRet; 465 } 466 467 // css::XServiceInfo 468 OUString SAL_CALL ORowSet::getImplementationName() 469 { 470 return OUString("com.sun.star.comp.dba.ORowSet"); 471 } 472 473 sal_Bool SAL_CALL ORowSet::supportsService( const OUString& _rServiceName ) 474 { 475 return cppu::supportsService(this, _rServiceName); 476 } 477 478 Sequence< OUString > SAL_CALL ORowSet::getSupportedServiceNames() 479 { 480 Sequence< OUString > aSNS( 5 ); 481 aSNS[0] = SERVICE_SDBC_RESULTSET; 482 aSNS[1] = SERVICE_SDBC_ROWSET; 483 aSNS[2] = SERVICE_SDBCX_RESULTSET; 484 aSNS[3] = SERVICE_SDB_RESULTSET; 485 aSNS[4] = SERVICE_SDB_ROWSET; 486 return aSNS; 487 } 488 489 // OComponentHelper 490 void SAL_CALL ORowSet::disposing() 491 { 492 OPropertyStateContainer::disposing(); 493 494 MutexGuard aGuard(m_aMutex); 495 EventObject aDisposeEvent; 496 aDisposeEvent.Source = static_cast< XComponent* >(this); 497 m_aRowsetListeners.disposeAndClear( aDisposeEvent ); 498 m_aApproveListeners.disposeAndClear( aDisposeEvent ); 499 m_aRowsChangeListener.disposeAndClear( aDisposeEvent ); 500 501 freeResources( true ); 502 503 // remove myself as dispose listener 504 Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); 505 if (xComponent.is()) 506 { 507 Reference<XEventListener> xEvt; 508 query_aggregation(this,xEvt); 509 xComponent->removeEventListener(xEvt); 510 } 511 512 m_aActiveConnection = Any(); // the any contains a reference too 513 if(m_bOwnConnection) 514 ::comphelper::disposeComponent(m_xActiveConnection); 515 m_xActiveConnection = nullptr; 516 517 518 ORowSetBase::disposing(); 519 } 520 521 void ORowSet::freeResources( bool _bComplete ) 522 { 523 MutexGuard aGuard(m_aMutex); 524 525 // free all clones 526 for (auto const& clone : m_aClones) 527 { 528 Reference< XComponent > xComp(clone.get(), UNO_QUERY); 529 if (xComp.is()) 530 xComp->dispose(); 531 } 532 m_aClones.clear(); 533 534 doCancelModification(); 535 536 m_aBookmark = Any(); 537 m_bBeforeFirst = true; 538 m_bAfterLast = false; 539 m_bNew = false; 540 m_bModified = false; 541 m_bIsInsertRow = false; 542 m_bLastKnownRowCountFinal = false; 543 m_nLastKnownRowCount = 0; 544 545 if ( _bComplete ) 546 { 547 // the columns must be disposed before the querycomposer is disposed because 548 // their owner can be the composer 549 TDataColumns().swap(m_aDataColumns);// clear and resize capacity 550 std::vector<bool>().swap(m_aReadOnlyDataColumns); 551 552 m_xColumns = nullptr; 553 if ( m_pColumns ) 554 m_pColumns->disposing(); 555 // dispose the composer to avoid that everybody knows that the querycomposer is eol 556 try { ::comphelper::disposeComponent( m_xComposer ); } 557 catch(Exception&) 558 { 559 DBG_UNHANDLED_EXCEPTION("dbaccess"); 560 m_xComposer = nullptr; 561 } 562 563 // let our warnings container forget the reference to the (possibly disposed) old result set 564 m_aWarnings.setExternalWarnings( nullptr ); 565 566 m_pCache.reset(); 567 568 impl_resetTables_nothrow(); 569 570 m_xStatement = nullptr; 571 m_xTypeMap = nullptr; 572 573 if ( m_aOldRow.is() ) 574 m_aOldRow->clearRow(); 575 576 impl_disposeParametersContainer_nothrow(); 577 578 m_bCommandFacetsDirty = true; 579 } 580 } 581 582 void ORowSet::setActiveConnection( Reference< XConnection > const & _rxNewConn, bool _bFireEvent ) 583 { 584 if (_rxNewConn.get() == m_xActiveConnection.get()) 585 // nothing to do 586 return; 587 588 // remove the event listener for the old connection 589 Reference< XComponent > xComponent(m_xActiveConnection, UNO_QUERY); 590 if (xComponent.is()) 591 { 592 Reference<XEventListener> xListener; 593 query_aggregation(this, xListener); 594 xComponent->removeEventListener(xListener); 595 } 596 597 // if we owned the connection, remember it for later disposing 598 if(m_bOwnConnection) 599 m_xOldConnection = m_xActiveConnection; 600 601 // for firing the PropertyChangeEvent 602 sal_Int32 nHandle = PROPERTY_ID_ACTIVE_CONNECTION; 603 Any aOldConnection; aOldConnection <<= m_xActiveConnection; 604 Any aNewConnection; aNewConnection <<= _rxNewConn; 605 606 // set the new connection 607 m_xActiveConnection = _rxNewConn; 608 if (m_xActiveConnection.is()) 609 m_aActiveConnection <<= m_xActiveConnection; 610 else 611 m_aActiveConnection.clear(); 612 613 // fire the event 614 if (_bFireEvent) 615 fire(&nHandle, &aNewConnection, &aOldConnection, 1, false); 616 617 // register as event listener for the new connection 618 xComponent.set(m_xActiveConnection,UNO_QUERY); 619 if (xComponent.is()) 620 { 621 Reference<XEventListener> xListener; 622 query_aggregation(this, xListener); 623 xComponent->addEventListener(xListener); 624 } 625 } 626 627 // css::XEventListener 628 void SAL_CALL ORowSet::disposing( const css::lang::EventObject& Source ) 629 { 630 // close rowset because the connection is going to be deleted (someone told me :-) 631 Reference<XConnection> xCon(Source.Source,UNO_QUERY); 632 if(m_xActiveConnection == xCon) 633 { 634 close(); 635 { 636 MutexGuard aGuard( m_aMutex ); 637 Reference< XConnection > xXConnection; 638 setActiveConnection( xXConnection ); 639 } 640 } 641 } 642 643 // XCloseable 644 void SAL_CALL ORowSet::close( ) 645 { 646 { 647 MutexGuard aGuard( m_aMutex ); 648 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 649 } 650 // additionals things to set 651 freeResources( true ); 652 } 653 654 // comphelper::OPropertyArrayUsageHelper 655 ::cppu::IPropertyArrayHelper* ORowSet::createArrayHelper( ) const 656 { 657 Sequence< Property > aProps; 658 describeProperties(aProps); 659 return new ::cppu::OPropertyArrayHelper(aProps); 660 } 661 662 // cppu::OPropertySetHelper 663 ::cppu::IPropertyArrayHelper& SAL_CALL ORowSet::getInfoHelper() 664 { 665 return *::comphelper::OPropertyArrayUsageHelper<ORowSet>::getArrayHelper(); 666 } 667 668 void ORowSet::updateValue(sal_Int32 columnIndex,const ORowSetValue& x) 669 { 670 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 671 672 ::osl::MutexGuard aGuard( *m_pMutex ); 673 checkUpdateConditions(columnIndex); 674 checkUpdateIterator(); 675 676 ORowSetValueVector::Vector& rRow = (*m_aCurrentRow)->get(); 677 ORowSetNotifier aNotify(this,rRow); 678 m_pCache->updateValue(columnIndex,x,rRow,aNotify.getChangedColumns()); 679 m_bModified = m_bModified || !aNotify.getChangedColumns().empty(); 680 aNotify.firePropertyChange(); 681 } 682 683 // XRowUpdate 684 void SAL_CALL ORowSet::updateNull( sal_Int32 columnIndex ) 685 { 686 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 687 688 ::osl::MutexGuard aGuard( *m_pMutex ); 689 checkUpdateConditions(columnIndex); 690 checkUpdateIterator(); 691 692 ORowSetValueVector::Vector& rRow = (*m_aCurrentRow)->get(); 693 ORowSetNotifier aNotify(this,rRow); 694 m_pCache->updateNull(columnIndex,rRow,aNotify.getChangedColumns()); 695 m_bModified = m_bModified || !aNotify.getChangedColumns().empty(); 696 aNotify.firePropertyChange(); 697 } 698 699 void SAL_CALL ORowSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) 700 { 701 updateValue(columnIndex, static_cast<bool>(x)); 702 } 703 704 void SAL_CALL ORowSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) 705 { 706 updateValue(columnIndex,x); 707 } 708 709 void SAL_CALL ORowSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) 710 { 711 updateValue(columnIndex,x); 712 } 713 714 void SAL_CALL ORowSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) 715 { 716 updateValue(columnIndex,x); 717 } 718 719 void SAL_CALL ORowSet::updateLong( sal_Int32 columnIndex, sal_Int64 x ) 720 { 721 updateValue(columnIndex,x); 722 } 723 724 void SAL_CALL ORowSet::updateFloat( sal_Int32 columnIndex, float x ) 725 { 726 updateValue(columnIndex,x); 727 } 728 729 void SAL_CALL ORowSet::updateDouble( sal_Int32 columnIndex, double x ) 730 { 731 updateValue(columnIndex,x); 732 } 733 734 void SAL_CALL ORowSet::updateString( sal_Int32 columnIndex, const OUString& x ) 735 { 736 updateValue(columnIndex,x); 737 } 738 739 void SAL_CALL ORowSet::updateBytes( sal_Int32 columnIndex, const Sequence< sal_Int8 >& x ) 740 { 741 updateValue(columnIndex,x); 742 } 743 744 void SAL_CALL ORowSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x ) 745 { 746 updateValue(columnIndex,x); 747 } 748 749 void SAL_CALL ORowSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x ) 750 { 751 updateValue(columnIndex,x); 752 } 753 754 void SAL_CALL ORowSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) 755 { 756 updateValue(columnIndex,x); 757 } 758 759 void SAL_CALL ORowSet::updateBinaryStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) 760 { 761 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 762 ::osl::MutexGuard aGuard( *m_pMutex ); 763 checkUpdateConditions(columnIndex); 764 checkUpdateIterator(); 765 766 { 767 Sequence<sal_Int8> aSeq; 768 if(x.is()) 769 x->readBytes(aSeq,length); 770 updateValue(columnIndex,aSeq); 771 } 772 } 773 774 void SAL_CALL ORowSet::updateCharacterStream( sal_Int32 columnIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) 775 { 776 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 777 ::osl::MutexGuard aGuard( *m_pMutex ); 778 checkUpdateConditions(columnIndex); 779 checkUpdateIterator(); 780 ORowSetValueVector::Vector& rRow = (*m_aCurrentRow)->get(); 781 ORowSetNotifier aNotify(this,rRow); 782 m_pCache->updateCharacterStream(columnIndex,x,length,rRow,aNotify.getChangedColumns()); 783 m_bModified = m_bModified || !aNotify.getChangedColumns().empty(); 784 aNotify.firePropertyChange(); 785 } 786 787 void SAL_CALL ORowSet::updateObject( sal_Int32 columnIndex, const Any& x ) 788 { 789 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 790 ::osl::MutexGuard aGuard( *m_pMutex ); 791 checkUpdateConditions(columnIndex); 792 checkUpdateIterator(); 793 794 Any aNewValue = x; 795 796 if ( m_pColumns ) 797 { 798 Reference<XPropertySet> xColumn(m_pColumns->getByIndex(columnIndex-1),UNO_QUERY); 799 sal_Int32 nColType = 0; 800 xColumn->getPropertyValue(PROPERTY_TYPE) >>= nColType; 801 switch( nColType ) 802 { 803 case DataType::DATE: 804 case DataType::TIME: 805 case DataType::TIMESTAMP: 806 { 807 double nValue = 0; 808 if ( x >>= nValue ) 809 { 810 if ( DataType::TIMESTAMP == nColType ) 811 aNewValue <<= dbtools::DBTypeConversion::toDateTime( nValue ); 812 else if ( DataType::DATE == nColType ) 813 aNewValue <<= dbtools::DBTypeConversion::toDate( nValue ); 814 else 815 aNewValue <<= dbtools::DBTypeConversion::toTime( nValue ); 816 } 817 break; 818 } 819 } 820 } 821 822 if (!::dbtools::implUpdateObject(this, columnIndex, aNewValue)) 823 { // there is no other updateXXX call which can handle the value in x 824 ORowSetValueVector::Vector& rRow = (*m_aCurrentRow)->get(); 825 ORowSetNotifier aNotify(this,rRow); 826 m_pCache->updateObject(columnIndex,aNewValue,rRow,aNotify.getChangedColumns()); 827 m_bModified = m_bModified || !aNotify.getChangedColumns().empty(); 828 aNotify.firePropertyChange(); 829 } 830 } 831 832 void SAL_CALL ORowSet::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/ ) 833 { 834 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 835 ::osl::MutexGuard aGuard( *m_pMutex ); 836 checkUpdateConditions(columnIndex); 837 checkUpdateIterator(); 838 ORowSetValueVector::Vector& rRow = (*m_aCurrentRow)->get(); 839 ORowSetNotifier aNotify(this,rRow); 840 m_pCache->updateNumericObject(columnIndex,x,rRow,aNotify.getChangedColumns()); 841 m_bModified = m_bModified || !aNotify.getChangedColumns().empty(); 842 aNotify.firePropertyChange(); 843 } 844 845 namespace 846 { 847 class ProtectFlag 848 { 849 bool& m_rInsertingRow; 850 public: 851 explicit ProtectFlag(bool& rInsertingRow) 852 : m_rInsertingRow(rInsertingRow) 853 { 854 if (m_rInsertingRow) 855 { 856 throw std::runtime_error("recursion in insertRow"); 857 } 858 m_rInsertingRow = true; 859 } 860 ~ProtectFlag() 861 { 862 m_rInsertingRow = false; 863 } 864 }; 865 } 866 867 // XResultSetUpdate 868 void SAL_CALL ORowSet::insertRow() 869 { 870 ProtectFlag aFlagControl(m_bInsertingRow); 871 872 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 873 // insertRow is not allowed when 874 // standing not on the insert row nor 875 // when the row isn't modified 876 // or the concurrency is read only 877 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 878 879 if(!m_pCache || !m_bNew || !m_bModified || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) 880 throwFunctionSequenceException(*this); 881 882 // remember old value for fire 883 bool bOld = m_bNew; 884 885 ORowSetRow aOldValues; 886 if ( !m_aCurrentRow.isNull() ) 887 aOldValues = new ORowSetValueVector( *(*m_aCurrentRow)); 888 Sequence<Any> aChangedBookmarks; 889 RowsChangeEvent aEvt(*this,RowChangeAction::INSERT,1,aChangedBookmarks); 890 notifyAllListenersRowBeforeChange(aGuard,aEvt); 891 892 std::vector< Any > aBookmarks; 893 bool bInserted = m_pCache->insertRow(aBookmarks); 894 895 // make sure that our row is set to the new inserted row before clearing the insert flags in the cache 896 m_pCache->resetInsertRow(bInserted); 897 898 // notification order 899 // - column values 900 setCurrentRow( false, true, aOldValues, aGuard ); // we don't move here 901 902 // read-only flag restored 903 impl_restoreDataColumnsWriteable_throw(); 904 905 // - rowChanged 906 notifyAllListenersRowChanged(aGuard,aEvt); 907 908 if ( !aBookmarks.empty() ) 909 { 910 RowsChangeEvent aUpEvt(*this,RowChangeAction::UPDATE,aBookmarks.size(),comphelper::containerToSequence(aBookmarks)); 911 notifyAllListenersRowChanged(aGuard,aUpEvt); 912 } 913 914 // - IsModified 915 if(!m_bModified) 916 fireProperty(PROPERTY_ID_ISMODIFIED,false,true); 917 OSL_ENSURE( !m_bModified, "ORowSet::insertRow: just updated, but _still_ modified?" ); 918 919 // - IsNew 920 if(m_bNew != bOld) 921 fireProperty(PROPERTY_ID_ISNEW,m_bNew,bOld); 922 923 // - RowCount/IsRowCountFinal 924 fireRowcount(); 925 } 926 927 void SAL_CALL ORowSet::updateRow( ) 928 { 929 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 930 // not allowed when standing on insert row 931 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 932 if ( !m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY || m_bNew || ((m_pCache->m_nPrivileges & Privilege::UPDATE ) != Privilege::UPDATE) ) 933 throwFunctionSequenceException(*this); 934 935 936 if(m_bModified) 937 { 938 ORowSetRow aOldValues; 939 if ( !m_aCurrentRow.isNull() ) 940 aOldValues = new ORowSetValueVector( *(*m_aCurrentRow) ); 941 942 Sequence<Any> aChangedBookmarks; 943 RowsChangeEvent aEvt(*this,RowChangeAction::UPDATE,1,aChangedBookmarks); 944 notifyAllListenersRowBeforeChange(aGuard,aEvt); 945 946 std::vector< Any > aBookmarks; 947 m_pCache->updateRow(m_aCurrentRow.operator ->(),aBookmarks); 948 if ( !aBookmarks.empty() ) 949 aEvt.Bookmarks = comphelper::containerToSequence(aBookmarks); 950 aEvt.Rows += aBookmarks.size(); 951 m_aBookmark = m_pCache->getBookmark(); 952 m_aCurrentRow = m_pCache->m_aMatrixIter; 953 m_bIsInsertRow = false; 954 if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && (*m_pCache->m_aMatrixIter).is() ) 955 { 956 if ( m_pCache->isResultSetChanged() ) 957 { 958 impl_rebuild_throw(aGuard); 959 } 960 else 961 { 962 m_aOldRow->setRow(new ORowSetValueVector(*(*m_aCurrentRow))); 963 964 // notification order 965 // - column values 966 ORowSetBase::firePropertyChange(aOldValues); 967 } 968 // - rowChanged 969 notifyAllListenersRowChanged(aGuard,aEvt); 970 971 // - IsModified 972 if(!m_bModified) 973 fireProperty(PROPERTY_ID_ISMODIFIED,false,true); 974 OSL_ENSURE( !m_bModified, "ORowSet::updateRow: just updated, but _still_ modified?" ); 975 976 // - RowCount/IsRowCountFinal 977 fireRowcount(); 978 } 979 else if ( !m_bAfterLast ) // the update went wrong 980 { 981 ::dbtools::throwSQLException( DBA_RES( RID_STR_UPDATE_FAILED ), StandardSQLState::INVALID_CURSOR_POSITION, *this ); 982 } 983 } 984 } 985 986 void SAL_CALL ORowSet::deleteRow( ) 987 { 988 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 989 990 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 991 checkCache(); 992 993 if ( m_bBeforeFirst || m_bAfterLast ) 994 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_BEFORE_AFTER ), StandardSQLState::INVALID_CURSOR_POSITION, *this ); 995 if ( m_bNew ) 996 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_INSERT_ROW ), StandardSQLState::INVALID_CURSOR_POSITION, *this ); 997 if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) 998 ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this ); 999 if ( ( m_pCache->m_nPrivileges & Privilege::DELETE ) != Privilege::DELETE ) 1000 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_PRIVILEGE ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this ); 1001 if ( rowDeleted() ) 1002 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this ); 1003 1004 // this call position the cache indirect 1005 Any aBookmarkToDelete( m_aBookmark ); 1006 positionCache( MOVE_NONE ); 1007 sal_Int32 nDeletePosition = m_pCache->getRow(); 1008 1009 notifyRowSetAndClonesRowDelete( aBookmarkToDelete ); 1010 1011 ORowSetRow aOldValues; 1012 if ( m_pCache->m_aMatrixIter != m_pCache->getEnd() && m_pCache->m_aMatrixIter->is() ) 1013 aOldValues = new ORowSetValueVector( *(*(m_pCache->m_aMatrixIter)) ); 1014 1015 Sequence<Any> aChangedBookmarks; 1016 RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,1,aChangedBookmarks); 1017 notifyAllListenersRowBeforeChange(aGuard,aEvt); 1018 1019 m_pCache->deleteRow(); 1020 notifyRowSetAndClonesRowDeleted( aBookmarkToDelete, nDeletePosition ); 1021 1022 ORowSetNotifier aNotifier( this ); 1023 // this will call cancelRowModification on the cache if necessary 1024 1025 // notification order 1026 // - rowChanged 1027 notifyAllListenersRowChanged(aGuard,aEvt); 1028 1029 // - IsModified 1030 // - IsNew 1031 aNotifier.fire( ); 1032 1033 // - RowCount/IsRowCountFinal 1034 fireRowcount(); 1035 } 1036 1037 void ORowSet::implCancelRowUpdates( bool _bNotifyModified ) 1038 { 1039 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1040 1041 ::osl::MutexGuard aGuard( *m_pMutex ); 1042 if ( m_bBeforeFirst || m_bAfterLast || rowDeleted() ) 1043 return; // nothing to do so return 1044 1045 checkCache(); 1046 // cancelRowUpdates is not allowed when: 1047 // - standing on the insert row 1048 // - the concurrency is read only 1049 // - the current row is deleted 1050 if ( m_bNew || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) 1051 throwFunctionSequenceException(*this); 1052 1053 positionCache( MOVE_NONE ); 1054 1055 ORowSetRow aOldValues; 1056 if ( !m_bModified && _bNotifyModified && !m_aCurrentRow.isNull() ) 1057 aOldValues = new ORowSetValueVector( *(*m_aCurrentRow) ); 1058 1059 m_pCache->cancelRowUpdates(); 1060 1061 m_aBookmark = m_pCache->getBookmark(); 1062 m_aCurrentRow = m_pCache->m_aMatrixIter; 1063 m_bIsInsertRow = false; 1064 1065 // notification order 1066 // IsModified 1067 if( !m_bModified && _bNotifyModified ) 1068 { 1069 // - column values 1070 ORowSetBase::firePropertyChange(aOldValues); 1071 fireProperty(PROPERTY_ID_ISMODIFIED,false,true); 1072 } 1073 } 1074 1075 void SAL_CALL ORowSet::cancelRowUpdates( ) 1076 { 1077 implCancelRowUpdates( true ); 1078 } 1079 1080 void SAL_CALL ORowSet::addRowSetListener( const Reference< XRowSetListener >& listener ) 1081 { 1082 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1083 1084 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 1085 if(listener.is()) 1086 m_aRowsetListeners.addInterface(listener); 1087 } 1088 1089 void SAL_CALL ORowSet::removeRowSetListener( const Reference< XRowSetListener >& listener ) 1090 { 1091 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1092 1093 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 1094 if(listener.is()) 1095 m_aRowsetListeners.removeInterface(listener); 1096 } 1097 1098 void ORowSet::notifyAllListeners(::osl::ResettableMutexGuard& _rGuard) 1099 { 1100 EventObject aEvt(*m_pMySelf); 1101 _rGuard.clear(); 1102 m_aRowsetListeners.notifyEach( &XRowSetListener::rowSetChanged, aEvt ); 1103 _rGuard.reset(); 1104 } 1105 1106 void ORowSet::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& _rGuard) 1107 { 1108 EventObject aEvt(*m_pMySelf); 1109 _rGuard.clear(); 1110 m_aRowsetListeners.notifyEach( &XRowSetListener::cursorMoved, aEvt ); 1111 _rGuard.reset(); 1112 } 1113 1114 void ORowSet::notifyAllListenersRowChanged(::osl::ResettableMutexGuard& _rGuard, const RowsChangeEvent& aEvt) 1115 { 1116 _rGuard.clear(); 1117 m_aRowsetListeners.notifyEach( &XRowSetListener::rowChanged, static_cast<EventObject>(aEvt) ); 1118 m_aRowsChangeListener.notifyEach( &XRowsChangeListener::rowsChanged, aEvt ); 1119 _rGuard.reset(); 1120 } 1121 1122 bool ORowSet::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& _rGuard) 1123 { 1124 EventObject aEvt(*m_pMySelf); 1125 NOTIFY_LISTENERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveCursorMove); 1126 return bCheck; 1127 } 1128 1129 void ORowSet::notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard& _rGuard,const RowChangeEvent &aEvt) 1130 { 1131 NOTIFY_LISTENERS_CHECK(m_aApproveListeners,XRowSetApproveListener,approveRowChange); 1132 if ( !bCheck ) 1133 m_aErrors.raiseTypedException( sdb::ErrorCondition::ROW_SET_OPERATION_VETOED, *this, ::cppu::UnoType< RowSetVetoException >::get() ); 1134 } 1135 1136 void ORowSet::fireRowcount() 1137 { 1138 sal_Int32 nCurrentRowCount( impl_getRowCount() ); 1139 bool bCurrentRowCountFinal( m_pCache->m_bRowCountFinal ); 1140 1141 if ( m_nLastKnownRowCount != nCurrentRowCount ) 1142 { 1143 sal_Int32 nHandle = PROPERTY_ID_ROWCOUNT; 1144 Any aNew,aOld; 1145 aNew <<= nCurrentRowCount; aOld <<= m_nLastKnownRowCount; 1146 fire(&nHandle,&aNew,&aOld,1,false); 1147 m_nLastKnownRowCount = nCurrentRowCount; 1148 } 1149 if ( !m_bLastKnownRowCountFinal && ( m_bLastKnownRowCountFinal != bCurrentRowCountFinal ) ) 1150 { 1151 sal_Int32 nHandle = PROPERTY_ID_ISROWCOUNTFINAL; 1152 Any aNew,aOld; 1153 aNew <<= bCurrentRowCountFinal; 1154 aOld <<= m_bLastKnownRowCountFinal; 1155 fire(&nHandle,&aNew,&aOld,1,false); 1156 m_bLastKnownRowCountFinal = bCurrentRowCountFinal; 1157 } 1158 } 1159 1160 void SAL_CALL ORowSet::moveToInsertRow( ) 1161 { 1162 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1163 1164 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 1165 checkPositioningAllowed(); 1166 if ( ( m_pCache->m_nPrivileges & Privilege::INSERT ) != Privilege::INSERT ) 1167 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_INSERT_PRIVILEGE ), StandardSQLState::GENERAL_ERROR, *this ); 1168 1169 if ( notifyAllListenersCursorBeforeMove( aGuard ) ) 1170 { 1171 // remember old value for fire 1172 ORowSetRow aOldValues; 1173 if ( rowDeleted() ) 1174 { 1175 positionCache( MOVE_FORWARD ); 1176 m_pCache->next(); 1177 setCurrentRow( true, false, aOldValues, aGuard); 1178 } 1179 else 1180 positionCache( MOVE_NONE ); 1181 1182 // check before because the resultset could be empty 1183 if ( !m_bBeforeFirst 1184 && !m_bAfterLast 1185 && m_pCache->m_aMatrixIter != m_pCache->getEnd() 1186 && m_pCache->m_aMatrixIter->is() 1187 ) 1188 aOldValues = new ORowSetValueVector( *(*(m_pCache->m_aMatrixIter)) ); 1189 1190 const bool bNewState = m_bNew; 1191 const bool bModState = m_bModified; 1192 1193 m_pCache->moveToInsertRow(); 1194 m_aCurrentRow = m_pCache->m_aInsertRow; 1195 m_bIsInsertRow = true; 1196 1197 // set read-only flag to false 1198 impl_setDataColumnsWriteable_throw(); 1199 1200 // notification order 1201 // - column values 1202 ORowSetBase::firePropertyChange(aOldValues); 1203 1204 // - cursorMoved 1205 notifyAllListenersCursorMoved(aGuard); 1206 1207 // - IsModified 1208 if ( bModState != m_bModified ) 1209 fireProperty( PROPERTY_ID_ISMODIFIED, m_bModified, bModState ); 1210 1211 // - IsNew 1212 if ( bNewState != m_bNew ) 1213 fireProperty( PROPERTY_ID_ISNEW, m_bNew, bNewState ); 1214 1215 // - RowCount/IsRowCountFinal 1216 fireRowcount(); 1217 } 1218 } 1219 1220 void ORowSet::impl_setDataColumnsWriteable_throw() 1221 { 1222 impl_restoreDataColumnsWriteable_throw(); 1223 m_aReadOnlyDataColumns.resize(m_aDataColumns.size(),false); 1224 std::vector<bool, std::allocator<bool> >::iterator aReadIter = m_aReadOnlyDataColumns.begin(); 1225 for (auto const& dataColumn : m_aDataColumns) 1226 { 1227 bool bReadOnly = false; 1228 dataColumn->getPropertyValue(PROPERTY_ISREADONLY) >>= bReadOnly; 1229 *aReadIter = bReadOnly; 1230 1231 dataColumn->setPropertyValue(PROPERTY_ISREADONLY,makeAny(false)); 1232 ++aReadIter; 1233 } 1234 } 1235 1236 void ORowSet::impl_restoreDataColumnsWriteable_throw() 1237 { 1238 assert(m_aDataColumns.size() == m_aReadOnlyDataColumns.size() || m_aReadOnlyDataColumns.size() == 0 ); 1239 TDataColumns::const_iterator aIter = m_aDataColumns.begin(); 1240 for (auto const& readOnlyDataColumn : m_aReadOnlyDataColumns) 1241 { 1242 (*aIter)->setPropertyValue(PROPERTY_ISREADONLY, makeAny( static_cast<bool>(readOnlyDataColumn)) ); 1243 ++aIter; 1244 } 1245 m_aReadOnlyDataColumns.clear(); 1246 } 1247 1248 void SAL_CALL ORowSet::moveToCurrentRow( ) 1249 { 1250 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1251 1252 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 1253 checkPositioningAllowed(); 1254 1255 if ( !m_pCache->m_bNew && !m_bModified ) 1256 // nothing to do if we're not on the insertion row, and not modified otherwise 1257 return; 1258 1259 if ( rowDeleted() ) 1260 // this would perhaps even justify a RuntimeException .... 1261 // if the current row is deleted, then no write access to this row should be possible. So, 1262 // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow, 1263 // our current row should not be deleted anymore. So, we should not have survived the above 1264 // check "if ( !m_pCache->m_bNew && !m_bModified )" 1265 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this ); 1266 1267 if ( notifyAllListenersCursorBeforeMove( aGuard ) ) 1268 { 1269 positionCache( MOVE_NONE_REFRESH ); 1270 1271 ORowSetNotifier aNotifier( this ); 1272 1273 // notification order 1274 // - cursorMoved 1275 notifyAllListenersCursorMoved(aGuard); 1276 1277 // - IsModified 1278 // - IsNew 1279 aNotifier.fire(); 1280 } 1281 } 1282 1283 // XRow 1284 sal_Bool SAL_CALL ORowSet::wasNull( ) 1285 { 1286 ::osl::MutexGuard aGuard( *m_pMutex ); 1287 checkCache(); 1288 1289 return ( m_pCache && isInsertRow() ) ? ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex].isNull() : ORowSetBase::wasNull(); 1290 } 1291 1292 const ORowSetValue& ORowSet::getInsertValue(sal_Int32 columnIndex) 1293 { 1294 checkCache(); 1295 1296 if ( m_pCache && isInsertRow() ) 1297 return ((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex]; 1298 1299 return getValue(columnIndex); 1300 } 1301 1302 OUString SAL_CALL ORowSet::getString( sal_Int32 columnIndex ) 1303 { 1304 ::osl::MutexGuard aGuard( *m_pMutex ); 1305 return getInsertValue(columnIndex); 1306 } 1307 1308 sal_Bool SAL_CALL ORowSet::getBoolean( sal_Int32 columnIndex ) 1309 { 1310 ::osl::MutexGuard aGuard( *m_pMutex ); 1311 // the extra cast is to recognise the "true" or "false" strings 1312 return static_cast<bool>(getInsertValue(columnIndex)); 1313 } 1314 1315 sal_Int8 SAL_CALL ORowSet::getByte( sal_Int32 columnIndex ) 1316 { 1317 ::osl::MutexGuard aGuard( *m_pMutex ); 1318 return getInsertValue(columnIndex); 1319 } 1320 1321 sal_Int16 SAL_CALL ORowSet::getShort( sal_Int32 columnIndex ) 1322 { 1323 ::osl::MutexGuard aGuard( *m_pMutex ); 1324 return getInsertValue(columnIndex); 1325 } 1326 1327 sal_Int32 SAL_CALL ORowSet::getInt( sal_Int32 columnIndex ) 1328 { 1329 ::osl::MutexGuard aGuard( *m_pMutex ); 1330 return getInsertValue(columnIndex); 1331 } 1332 1333 sal_Int64 SAL_CALL ORowSet::getLong( sal_Int32 columnIndex ) 1334 { 1335 ::osl::MutexGuard aGuard( *m_pMutex ); 1336 return getInsertValue(columnIndex); 1337 } 1338 1339 float SAL_CALL ORowSet::getFloat( sal_Int32 columnIndex ) 1340 { 1341 ::osl::MutexGuard aGuard( *m_pMutex ); 1342 return getInsertValue(columnIndex); 1343 } 1344 1345 double SAL_CALL ORowSet::getDouble( sal_Int32 columnIndex ) 1346 { 1347 ::osl::MutexGuard aGuard( *m_pMutex ); 1348 return getInsertValue(columnIndex); 1349 } 1350 1351 Sequence< sal_Int8 > SAL_CALL ORowSet::getBytes( sal_Int32 columnIndex ) 1352 { 1353 ::osl::MutexGuard aGuard( *m_pMutex ); 1354 return getInsertValue(columnIndex); 1355 } 1356 1357 css::util::Date SAL_CALL ORowSet::getDate( sal_Int32 columnIndex ) 1358 { 1359 ::osl::MutexGuard aGuard( *m_pMutex ); 1360 return getInsertValue(columnIndex); 1361 } 1362 1363 css::util::Time SAL_CALL ORowSet::getTime( sal_Int32 columnIndex ) 1364 { 1365 ::osl::MutexGuard aGuard( *m_pMutex ); 1366 return getInsertValue(columnIndex); 1367 } 1368 1369 css::util::DateTime SAL_CALL ORowSet::getTimestamp( sal_Int32 columnIndex ) 1370 { 1371 ::osl::MutexGuard aGuard( *m_pMutex ); 1372 return getInsertValue(columnIndex); 1373 } 1374 1375 Reference< css::io::XInputStream > SAL_CALL ORowSet::getBinaryStream( sal_Int32 columnIndex ) 1376 { 1377 ::osl::MutexGuard aGuard( *m_pMutex ); 1378 if ( m_pCache && isInsertRow() ) 1379 { 1380 checkCache(); 1381 return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); 1382 } 1383 1384 return ORowSetBase::getBinaryStream(columnIndex); 1385 } 1386 1387 Reference< css::io::XInputStream > SAL_CALL ORowSet::getCharacterStream( sal_Int32 columnIndex ) 1388 { 1389 ::osl::MutexGuard aGuard( *m_pMutex ); 1390 if(m_pCache && isInsertRow() ) 1391 { 1392 checkCache(); 1393 return new ::comphelper::SequenceInputStream(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); 1394 } 1395 1396 return ORowSetBase::getCharacterStream(columnIndex); 1397 } 1398 1399 Any SAL_CALL ORowSet::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) 1400 { 1401 ::osl::MutexGuard aGuard( *m_pMutex ); 1402 return getInsertValue(columnIndex).makeAny(); 1403 } 1404 1405 Reference< XRef > SAL_CALL ORowSet::getRef( sal_Int32 /*columnIndex*/ ) 1406 { 1407 return Reference< XRef >(); 1408 } 1409 1410 Reference< XBlob > SAL_CALL ORowSet::getBlob( sal_Int32 columnIndex ) 1411 { 1412 if ( m_pCache && isInsertRow() ) 1413 { 1414 checkCache(); 1415 return new ::connectivity::BlobHelper(((*m_pCache->m_aInsertRow)->get())[m_nLastColumnIndex = columnIndex].getSequence()); 1416 } 1417 return ORowSetBase::getBlob(columnIndex); 1418 } 1419 1420 Reference< XClob > SAL_CALL ORowSet::getClob( sal_Int32 columnIndex ) 1421 { 1422 return Reference< XClob >(getInsertValue(columnIndex).makeAny(),UNO_QUERY); 1423 } 1424 1425 Reference< XArray > SAL_CALL ORowSet::getArray( sal_Int32 /*columnIndex*/ ) 1426 { 1427 return Reference< XArray >(); 1428 } 1429 1430 void SAL_CALL ORowSet::executeWithCompletion( const Reference< XInteractionHandler >& _rxHandler ) 1431 { 1432 if (!_rxHandler.is()) 1433 execute(); 1434 1435 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1436 1437 // tell everybody that we will change the result set 1438 approveExecution(); 1439 1440 ResettableMutexGuard aGuard( m_aMutex ); 1441 1442 try 1443 { 1444 freeResources( m_bCommandFacetsDirty ); 1445 1446 // calc the connection to be used 1447 if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) 1448 { 1449 // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too 1450 Reference< XConnection > xXConnection; 1451 setActiveConnection( xXConnection ); 1452 } 1453 calcConnection( _rxHandler ); 1454 m_bRebuildConnOnExecute = false; 1455 1456 Reference< XSingleSelectQueryComposer > xComposer = getCurrentSettingsComposer( this, m_aContext ); 1457 Reference<XParametersSupplier> xParameters(xComposer, UNO_QUERY); 1458 1459 Reference<XIndexAccess> xParamsAsIndicies = xParameters.is() ? xParameters->getParameters() : Reference<XIndexAccess>(); 1460 const sal_Int32 nParamCount = xParamsAsIndicies.is() ? xParamsAsIndicies->getCount() : 0; 1461 if ( m_aParametersSet.size() < static_cast<size_t>(nParamCount) ) 1462 m_aParametersSet.resize( nParamCount ,false); 1463 1464 ::dbtools::askForParameters( xComposer, this, m_xActiveConnection, _rxHandler,m_aParametersSet ); 1465 } 1466 // ensure that only the allowed exceptions leave this block 1467 catch(SQLException&) 1468 { 1469 throw; 1470 } 1471 catch(RuntimeException&) 1472 { 1473 throw; 1474 } 1475 catch(Exception&) 1476 { 1477 SAL_WARN("dbaccess", "ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters!"); 1478 } 1479 1480 // we're done with the parameters, now for the real execution 1481 1482 // do the real execute 1483 execute_NoApprove_NoNewConn(aGuard); 1484 } 1485 1486 Reference< XIndexAccess > SAL_CALL ORowSet::getParameters( ) 1487 { 1488 ::osl::MutexGuard aGuard( *m_pMutex ); 1489 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1490 1491 if ( m_bCommandFacetsDirty ) 1492 // need to rebuild the parameters, since some property which contributes to the 1493 // complete command, and thus the parameters, changed 1494 impl_disposeParametersContainer_nothrow(); 1495 1496 if ( !m_pParameters.get() && !m_aCommand.isEmpty() ) 1497 { 1498 try 1499 { 1500 OUString sNotInterestedIn; 1501 impl_initComposer_throw( sNotInterestedIn ); 1502 } 1503 catch( const Exception& ) 1504 { 1505 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1506 } 1507 } 1508 1509 // our caller could change our parameters at any time 1510 m_bParametersDirty = true; 1511 1512 return m_pParameters.get(); 1513 } 1514 1515 void ORowSet::approveExecution() 1516 { 1517 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 1518 EventObject aEvt(*this); 1519 1520 OInterfaceIteratorHelper2 aApproveIter( m_aApproveListeners ); 1521 while ( aApproveIter.hasMoreElements() ) 1522 { 1523 Reference< XRowSetApproveListener > xListener( static_cast< XRowSetApproveListener* >( aApproveIter.next() ) ); 1524 try 1525 { 1526 if ( xListener.is() && !xListener->approveRowSetChange( aEvt ) ) 1527 throw RowSetVetoException(); 1528 } 1529 catch ( const DisposedException& e ) 1530 { 1531 if ( e.Context == xListener ) 1532 aApproveIter.remove(); 1533 } 1534 catch ( const RuntimeException& ) { throw; } 1535 catch ( const RowSetVetoException& ) { throw; } 1536 catch ( const Exception& ) 1537 { 1538 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1539 } 1540 } 1541 } 1542 1543 // XRowSet 1544 void SAL_CALL ORowSet::execute( ) 1545 { 1546 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 1547 1548 // tell everybody that we will change the result set 1549 approveExecution(); 1550 1551 ResettableMutexGuard aGuard( m_aMutex ); 1552 freeResources( m_bCommandFacetsDirty ); 1553 1554 // calc the connection to be used 1555 if (m_xActiveConnection.is() && m_bRebuildConnOnExecute) { 1556 // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too 1557 Reference< XConnection> xXConnection; 1558 setActiveConnection( xXConnection ); 1559 } 1560 1561 calcConnection(nullptr); 1562 m_bRebuildConnOnExecute = false; 1563 1564 // do the real execute 1565 execute_NoApprove_NoNewConn(aGuard); 1566 } 1567 1568 void ORowSet::setStatementResultSetType( const Reference< XPropertySet >& _rxStatement, sal_Int32 _nDesiredResultSetType, sal_Int32 _nDesiredResultSetConcurrency ) 1569 { 1570 OSL_ENSURE( _rxStatement.is(), "ORowSet::setStatementResultSetType: invalid statement - this will crash!" ); 1571 1572 sal_Int32 nResultSetType( _nDesiredResultSetType ); 1573 sal_Int32 nResultSetConcurrency( _nDesiredResultSetConcurrency ); 1574 1575 // there *might* be a data source setting which tells use to be more defensive with those settings 1576 // #i15113# 1577 bool bRespectDriverRST = false; 1578 Any aSetting; 1579 if ( getDataSourceSetting( ::dbaccess::getDataSource( m_xActiveConnection ), "RespectDriverResultSetType", aSetting ) ) 1580 { 1581 OSL_VERIFY( aSetting >>= bRespectDriverRST ); 1582 } 1583 1584 if ( bRespectDriverRST ) 1585 { 1586 // try type/concurrency settings with decreasing usefulness, and rely on what the connection claims 1587 // to support 1588 Reference< XDatabaseMetaData > xMeta( m_xActiveConnection->getMetaData() ); 1589 1590 sal_Int32 nCharacteristics[5][2] = 1591 { { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::UPDATABLE }, 1592 { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::UPDATABLE }, 1593 { ResultSetType::SCROLL_SENSITIVE, ResultSetConcurrency::READ_ONLY }, 1594 { ResultSetType::SCROLL_INSENSITIVE, ResultSetConcurrency::READ_ONLY }, 1595 { ResultSetType::FORWARD_ONLY, ResultSetConcurrency::READ_ONLY } 1596 }; 1597 sal_Int32 i=0; 1598 if ( m_xActiveConnection->getMetaData()->isReadOnly() ) 1599 i = 2; // if the database is read-only we only should use read-only concurrency 1600 1601 for ( ; i<5; ++i ) 1602 { 1603 nResultSetType = nCharacteristics[i][0]; 1604 nResultSetConcurrency = nCharacteristics[i][1]; 1605 1606 // don't try type/concurrency pairs which are more featured than what our caller requested 1607 if ( nResultSetType > _nDesiredResultSetType ) 1608 continue; 1609 if ( nResultSetConcurrency > _nDesiredResultSetConcurrency ) 1610 continue; 1611 1612 if ( xMeta.is() && xMeta->supportsResultSetConcurrency( nResultSetType, nResultSetConcurrency ) ) 1613 break; 1614 } 1615 } 1616 1617 _rxStatement->setPropertyValue( PROPERTY_RESULTSETTYPE, makeAny( nResultSetType ) ); 1618 _rxStatement->setPropertyValue( PROPERTY_RESULTSETCONCURRENCY, makeAny( nResultSetConcurrency ) ); 1619 } 1620 1621 void ORowSet::impl_ensureStatement_throw() 1622 { 1623 OUString sCommandToExecute; 1624 if(m_bCommandFacetsDirty) 1625 { 1626 impl_initComposer_throw( sCommandToExecute ); 1627 } 1628 else 1629 { 1630 sCommandToExecute = m_bUseEscapeProcessing ? m_xComposer->getQueryWithSubstitution() : m_aActiveCommand; 1631 } 1632 1633 try 1634 { 1635 m_xStatement = m_xActiveConnection->prepareStatement( sCommandToExecute ); 1636 if ( !m_xStatement.is() ) 1637 { 1638 ::dbtools::throwSQLException( DBA_RES( RID_STR_INTERNAL_ERROR ), StandardSQLState::GENERAL_ERROR, *this ); 1639 } 1640 1641 Reference< XPropertySet > xStatementProps( m_xStatement, UNO_QUERY_THROW ); 1642 // set the result set type and concurrency 1643 try 1644 { 1645 xStatementProps->setPropertyValue( PROPERTY_USEBOOKMARKS, makeAny( true ) ); 1646 xStatementProps->setPropertyValue( PROPERTY_MAXROWS, makeAny( m_nMaxRows ) ); 1647 1648 setStatementResultSetType( xStatementProps, m_nResultSetType, m_nResultSetConcurrency ); 1649 } 1650 catch ( const Exception& ) 1651 { 1652 // this exception doesn't matter here because when we catch an exception 1653 // then the driver doesn't support this feature 1654 } 1655 } 1656 catch( const SQLException& ) 1657 { 1658 SQLExceptionInfo aError( ::cppu::getCaughtException() ); 1659 OSL_ENSURE( aError.isValid(), "ORowSet::impl_makeNewStatement_throw: caught an SQLException which we cannot analyze!" ); 1660 1661 // append information about what we were actually going to execute 1662 try 1663 { 1664 OUString sInfo(DBA_RES_PARAM( RID_STR_COMMAND_LEADING_TO_ERROR, "$command$", sCommandToExecute ) ); 1665 aError.append( SQLExceptionInfo::TYPE::SQLContext, sInfo ); 1666 } 1667 catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION("dbaccess"); } 1668 1669 // propagate 1670 aError.doThrow(); 1671 } 1672 } 1673 1674 Reference< XResultSet > ORowSet::impl_prepareAndExecute_throw() 1675 { 1676 impl_ensureStatement_throw(); 1677 1678 m_aParameterValueForCache->get().resize(1); 1679 Reference< XParameters > xParam( m_xStatement, UNO_QUERY_THROW ); 1680 size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues->get().size() ); 1681 for ( size_t i=1; i<=nParamCount; ++i ) 1682 { 1683 ORowSetValue& rParamValue( getParameterStorage( static_cast<sal_Int32>(i) ) ); 1684 ::dbtools::setObjectWithInfo( xParam, i, rParamValue.makeAny(), rParamValue.getTypeKind() ); 1685 m_aParameterValueForCache->get().push_back(rParamValue); 1686 } 1687 m_bParametersDirty = false; 1688 1689 Reference< XResultSet > xResultSet(m_xStatement->executeQuery()); 1690 1691 OUString aComposedUpdateTableName; 1692 if ( !m_aUpdateTableName.isEmpty() ) 1693 aComposedUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), m_aUpdateCatalogName, m_aUpdateSchemaName, m_aUpdateTableName, false, ::dbtools::EComposeRule::InDataManipulation ); 1694 1695 SAL_INFO("dbaccess", "ORowSet::impl_prepareAndExecute_throw: creating cache" ); 1696 m_pCache.reset( 1697 new ORowSetCache(xResultSet, m_xComposer.get(), m_aContext, aComposedUpdateTableName, 1698 m_bModified, m_bNew, *m_aParameterValueForCache, m_aFilter, m_nMaxRows)); 1699 if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY ) 1700 { 1701 m_nPrivileges = Privilege::SELECT; 1702 m_pCache->m_nPrivileges = Privilege::SELECT; 1703 } 1704 m_pCache->setFetchSize(m_nFetchSize); 1705 m_aCurrentRow = m_pCache->createIterator(this); 1706 m_bIsInsertRow = false; 1707 m_aOldRow = m_pCache->registerOldRow(); 1708 1709 return xResultSet; 1710 } 1711 1712 void ORowSet::impl_initializeColumnSettings_nothrow( const Reference< XPropertySet >& _rxTemplateColumn, const Reference< XPropertySet >& _rxRowSetColumn ) 1713 { 1714 OSL_ENSURE( _rxTemplateColumn.is() && _rxRowSetColumn.is(), 1715 "ORowSet::impl_initializeColumnSettings_nothrow: this will crash!" ); 1716 1717 bool bHaveAnyColumnSetting = false; 1718 try 1719 { 1720 Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); 1721 1722 // a number of properties is plain copied 1723 const OUString aPropertyNames[] = { 1724 OUString(PROPERTY_ALIGN), OUString(PROPERTY_RELATIVEPOSITION), OUString(PROPERTY_WIDTH), OUString(PROPERTY_HIDDEN), OUString(PROPERTY_CONTROLMODEL), 1725 OUString(PROPERTY_HELPTEXT), OUString(PROPERTY_CONTROLDEFAULT) 1726 }; 1727 for (const auto & aPropertyName : aPropertyNames) 1728 { 1729 if ( xInfo->hasPropertyByName( aPropertyName ) ) 1730 { 1731 _rxRowSetColumn->setPropertyValue( aPropertyName, _rxTemplateColumn->getPropertyValue( aPropertyName ) ); 1732 bHaveAnyColumnSetting = true; 1733 } 1734 } 1735 1736 // the format key is slightly more complex 1737 sal_Int32 nFormatKey = 0; 1738 if( xInfo->hasPropertyByName( PROPERTY_NUMBERFORMAT ) ) 1739 { 1740 _rxTemplateColumn->getPropertyValue( PROPERTY_NUMBERFORMAT ) >>= nFormatKey; 1741 bHaveAnyColumnSetting = true; 1742 } 1743 if ( !nFormatKey && m_xNumberFormatTypes.is() ) 1744 nFormatKey = ::dbtools::getDefaultNumberFormat( _rxTemplateColumn, m_xNumberFormatTypes, SvtSysLocale().GetLanguageTag().getLocale() ); 1745 _rxRowSetColumn->setPropertyValue( PROPERTY_NUMBERFORMAT, makeAny( nFormatKey ) ); 1746 } 1747 catch(Exception&) 1748 { 1749 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1750 return; 1751 } 1752 1753 if ( bHaveAnyColumnSetting ) 1754 return; 1755 1756 // the template column could not provide *any* setting. Okay, probably it's a parser column, which 1757 // does not offer those. However, perhaps the template column referes to a table column, which we 1758 // can use as new template column 1759 try 1760 { 1761 Reference< XPropertySetInfo > xInfo( _rxTemplateColumn->getPropertySetInfo(), UNO_QUERY_THROW ); 1762 if ( !xInfo->hasPropertyByName( PROPERTY_TABLENAME ) ) 1763 // no chance 1764 return; 1765 1766 OUString sTableName; 1767 OSL_VERIFY( _rxTemplateColumn->getPropertyValue( PROPERTY_TABLENAME ) >>= sTableName ); 1768 1769 Reference< XNameAccess > xTables( impl_getTables_throw(), UNO_QUERY_THROW ); 1770 if ( !xTables->hasByName( sTableName ) ) 1771 // no chance 1772 return; 1773 1774 Reference< XColumnsSupplier > xTableColSup( xTables->getByName( sTableName ), UNO_QUERY_THROW ); 1775 Reference< XNameAccess > xTableCols( xTableColSup->getColumns(), UNO_QUERY_THROW ); 1776 1777 OUString sTableColumnName; 1778 1779 // get the "Name" or (preferred) "RealName" property of the column 1780 OUString sNamePropertyName( PROPERTY_NAME ); 1781 if ( xInfo->hasPropertyByName( PROPERTY_REALNAME ) ) 1782 sNamePropertyName = PROPERTY_REALNAME; 1783 OSL_VERIFY( _rxTemplateColumn->getPropertyValue( sNamePropertyName ) >>= sTableColumnName ); 1784 1785 if ( !xTableCols->hasByName( sTableColumnName ) ) 1786 return; 1787 1788 Reference< XPropertySet > xTableColumn( xTableCols->getByName( sTableColumnName ), UNO_QUERY_THROW ); 1789 impl_initializeColumnSettings_nothrow( xTableColumn, _rxRowSetColumn ); 1790 } 1791 catch( const Exception& ) 1792 { 1793 DBG_UNHANDLED_EXCEPTION("dbaccess"); 1794 } 1795 } 1796 1797 void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard& _rClearForNotification) 1798 { 1799 // now we can dispose our old connection 1800 ::comphelper::disposeComponent(m_xOldConnection); 1801 m_xOldConnection = nullptr; 1802 1803 // do we need a new statement 1804 if ( m_bCommandFacetsDirty ) 1805 { 1806 m_xStatement = nullptr; 1807 m_xComposer = nullptr; 1808 1809 Reference< XResultSet > xResultSet( impl_prepareAndExecute_throw() ); 1810 1811 // let our warnings container forget the reference to the (possibly disposed) old result set 1812 m_aWarnings.setExternalWarnings( nullptr ); 1813 // clear all current warnings 1814 m_aWarnings.clearWarnings(); 1815 // let the warnings container know about the new "external warnings" 1816 m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); 1817 1818 // get the locale 1819 Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale(); 1820 1821 // get the numberformatTypes 1822 OSL_ENSURE(m_xActiveConnection.is(),"No ActiveConnection"); 1823 Reference< XNumberFormatsSupplier> xNumberFormat = ::dbtools::getNumberFormats(m_xActiveConnection); 1824 if ( xNumberFormat.is() ) 1825 m_xNumberFormatTypes.set(xNumberFormat->getNumberFormats(),UNO_QUERY); 1826 1827 ::rtl::Reference< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); 1828 std::vector< OUString> aNames; 1829 OUString aDescription; 1830 1831 const std::map<sal_Int32,sal_Int32>& rKeyColumns = m_pCache->getKeyColumns(); 1832 if(!m_xColumns.is()) 1833 { 1834 SAL_INFO("dbaccess", "ORowSet::execute_NoApprove_NoNewConn::creating columns" ); 1835 // use the meta data 1836 Reference<XResultSetMetaDataSupplier> xMetaSup(m_xStatement,UNO_QUERY); 1837 try 1838 { 1839 Reference<XResultSetMetaData> xMetaData = xMetaSup->getMetaData(); 1840 if ( xMetaData.is() ) 1841 { 1842 sal_Int32 nCount = xMetaData->getColumnCount(); 1843 m_aDataColumns.reserve(nCount+1); 1844 aColumns->get().reserve(nCount+1); 1845 std::map< OUString, int > aColumnMap; 1846 for (sal_Int32 i = 0 ; i < nCount; ++i) 1847 { 1848 // retrieve the name of the column 1849 OUString sName = xMetaData->getColumnName(i + 1); 1850 // check for duplicate entries 1851 if(aColumnMap.find(sName) != aColumnMap.end()) 1852 { 1853 OUString sAlias(sName); 1854 sal_Int32 searchIndex=1; 1855 while(aColumnMap.find(sAlias) != aColumnMap.end()) 1856 { 1857 sAlias = sName + OUString::number(searchIndex++); 1858 } 1859 sName = sAlias; 1860 } 1861 ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), 1862 this, 1863 this, 1864 i+1, 1865 m_xActiveConnection->getMetaData(), 1866 aDescription, 1867 OUString(), 1868 [this] (sal_Int32 const column) -> ORowSetValue const& { 1869 return this->getInsertValue(column); 1870 }); 1871 aColumnMap.insert(std::make_pair(sName,0)); 1872 aColumns->get().emplace_back(pColumn); 1873 pColumn->setName(sName); 1874 aNames.push_back(sName); 1875 m_aDataColumns.push_back(pColumn); 1876 1877 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i+1) != rKeyColumns.end())); 1878 1879 try 1880 { 1881 sal_Int32 nFormatKey = 0; 1882 if(m_xNumberFormatTypes.is()) 1883 nFormatKey = ::dbtools::getDefaultNumberFormat(pColumn,m_xNumberFormatTypes,aLocale); 1884 1885 1886 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); 1887 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,makeAny(sal_Int32(i+1))); 1888 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,makeAny(sal_Int32(227))); 1889 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,makeAny(sal_Int32(0))); 1890 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN, css::uno::Any(false)); 1891 } 1892 catch(Exception&) 1893 { 1894 } 1895 } 1896 } 1897 } 1898 catch (SQLException&) 1899 { 1900 } 1901 } 1902 else 1903 { 1904 // create the rowset columns 1905 Reference< XResultSetMetaData > xMeta( getMetaData(), UNO_QUERY_THROW ); 1906 sal_Int32 nCount = xMeta->getColumnCount(); 1907 m_aDataColumns.reserve(nCount+1); 1908 aColumns->get().reserve(nCount+1); 1909 std::set< Reference< XPropertySet > > aAllColumns; 1910 1911 for(sal_Int32 i=1; i <= nCount ;++i) 1912 { 1913 OUString sName = xMeta->getColumnName(i); 1914 OUString sColumnLabel = xMeta->getColumnLabel(i); 1915 1916 // retrieve the column number |i| 1917 Reference<XPropertySet> xColumn; 1918 { 1919 bool bReFetchName = false; 1920 if (m_xColumns->hasByName(sColumnLabel)) 1921 m_xColumns->getByName(sColumnLabel) >>= xColumn; 1922 if (!xColumn.is() && m_xColumns->hasByName(sName)) 1923 m_xColumns->getByName(sName) >>= xColumn; 1924 1925 // check if column already in the list we need another 1926 if ( aAllColumns.find( xColumn ) != aAllColumns.end() ) 1927 { 1928 xColumn = nullptr; 1929 bReFetchName = true; 1930 sColumnLabel.clear(); 1931 } 1932 if(!xColumn.is()) 1933 { 1934 // no column found so we could look at the position i 1935 Reference<XIndexAccess> xIndexAccess(m_xColumns,UNO_QUERY); 1936 if(xIndexAccess.is() && i <= xIndexAccess->getCount()) 1937 { 1938 xIndexAccess->getByIndex(i-1) >>= xColumn; 1939 } 1940 else 1941 { 1942 Sequence< OUString> aSeq = m_xColumns->getElementNames(); 1943 if( i <= aSeq.getLength()) 1944 { 1945 m_xColumns->getByName(aSeq.getConstArray()[i-1]) >>= xColumn; 1946 } 1947 } 1948 } 1949 if(bReFetchName && xColumn.is()) 1950 xColumn->getPropertyValue(PROPERTY_NAME) >>= sName; 1951 aAllColumns.insert( xColumn ); 1952 } 1953 1954 // create a RowSetDataColumn 1955 { 1956 Reference<XPropertySetInfo> xInfo = xColumn.is() ? xColumn->getPropertySetInfo() : Reference<XPropertySetInfo>(); 1957 if(xInfo.is() && xInfo->hasPropertyByName(PROPERTY_DESCRIPTION)) 1958 aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); 1959 1960 OUString sParseLabel; 1961 if ( xColumn.is() ) 1962 { 1963 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; 1964 } 1965 ORowSetDataColumn* pColumn = new ORowSetDataColumn( getMetaData(), 1966 this, 1967 this, 1968 i, 1969 m_xActiveConnection->getMetaData(), 1970 aDescription, 1971 sParseLabel, 1972 [this] (sal_Int32 const column) -> ORowSetValue const& { 1973 return this->getInsertValue(column); 1974 }); 1975 aColumns->get().emplace_back(pColumn); 1976 1977 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY,makeAny(rKeyColumns.find(i) != rKeyColumns.end())); 1978 1979 if(sColumnLabel.isEmpty()) 1980 { 1981 if(xColumn.is()) 1982 xColumn->getPropertyValue(PROPERTY_NAME) >>= sColumnLabel; 1983 else 1984 sColumnLabel = DBA_RES( RID_STR_EXPRESSION1 ); 1985 } 1986 pColumn->setName(sColumnLabel); 1987 aNames.push_back(sColumnLabel); 1988 m_aDataColumns.push_back(pColumn); 1989 1990 if ( xColumn.is() ) 1991 impl_initializeColumnSettings_nothrow( xColumn, pColumn ); 1992 } 1993 } 1994 } 1995 // now create the columns we need 1996 if(m_pColumns) 1997 m_pColumns->assign(aColumns,aNames); 1998 else 1999 { 2000 Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); 2001 m_pColumns.reset( new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), 2002 aColumns,*this,m_aColumnsMutex,aNames) ); 2003 } 2004 } 2005 else // !m_bCommandFacetsDirty 2006 { 2007 Reference< XResultSet > xResultSet; 2008 if(m_bParametersDirty) 2009 { 2010 xResultSet = impl_prepareAndExecute_throw(); 2011 } 2012 else 2013 { 2014 xResultSet = m_xStatement->executeQuery(); 2015 m_pCache->reset(xResultSet); 2016 } 2017 // let our warnings container forget the reference to the (possibly disposed) old result set 2018 m_aWarnings.setExternalWarnings( nullptr ); 2019 // clear all current warnings 2020 m_aWarnings.clearWarnings(); 2021 // let the warnings container know about the new "external warnings" 2022 m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); 2023 } 2024 checkCache(); 2025 // notify the rowset listeners 2026 notifyAllListeners(_rClearForNotification); 2027 } 2028 2029 // XRowSetApproveBroadcaster 2030 void SAL_CALL ORowSet::addRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) 2031 { 2032 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2033 2034 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2035 2036 m_aApproveListeners.addInterface(listener); 2037 } 2038 2039 void SAL_CALL ORowSet::removeRowSetApproveListener( const Reference< XRowSetApproveListener >& listener ) 2040 { 2041 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2042 2043 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2044 2045 m_aApproveListeners.removeInterface(listener); 2046 } 2047 2048 // XRowsChangeBroadcaster 2049 void SAL_CALL ORowSet::addRowsChangeListener( const Reference< XRowsChangeListener >& listener ) 2050 { 2051 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2052 2053 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2054 2055 m_aRowsChangeListener.addInterface(listener); 2056 } 2057 2058 void SAL_CALL ORowSet::removeRowsChangeListener( const Reference< XRowsChangeListener >& listener ) 2059 { 2060 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2061 2062 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2063 2064 m_aRowsChangeListener.removeInterface(listener); 2065 } 2066 2067 // XResultSetAccess 2068 Reference< XResultSet > SAL_CALL ORowSet::createResultSet( ) 2069 { 2070 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2071 2072 if(m_xStatement.is()) 2073 { 2074 ORowSetClone* pClone = new ORowSetClone( m_aContext, *this, m_pMutex ); 2075 Reference< XResultSet > xRet(pClone); 2076 m_aClones.emplace_back(xRet); 2077 return xRet; 2078 } 2079 return Reference< XResultSet >(); 2080 } 2081 2082 // css::util::XCancellable 2083 void SAL_CALL ORowSet::cancel( ) 2084 { 2085 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2086 } 2087 2088 // css::sdbcx::XDeleteRows 2089 Sequence< sal_Int32 > SAL_CALL ORowSet::deleteRows( const Sequence< Any >& rows ) 2090 { 2091 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2092 2093 if(!m_pCache || m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) 2094 throwFunctionSequenceException(*this); 2095 2096 ::osl::ResettableMutexGuard aGuard( *m_pMutex ); 2097 2098 Sequence<Any> aChangedBookmarks; 2099 RowsChangeEvent aEvt(*this,RowChangeAction::DELETE,rows.getLength(),aChangedBookmarks); 2100 // notify the rowset listeners 2101 notifyAllListenersRowBeforeChange(aGuard,aEvt); 2102 2103 Sequence< sal_Int32 > aResults( rows.getLength() ); 2104 const Any* row = rows.getConstArray(); 2105 const Any* rowEnd = rows.getConstArray() + rows.getLength(); 2106 sal_Int32* result = aResults.getArray(); 2107 for ( ; row != rowEnd; ++row, ++result ) 2108 { 2109 *result = 0; 2110 if ( !m_pCache->moveToBookmark( *row ) ) 2111 continue; 2112 sal_Int32 nDeletePosition = m_pCache->getRow(); 2113 2114 // first notify the clones so that they can save their position 2115 notifyRowSetAndClonesRowDelete( *row ); 2116 2117 // now delete the row 2118 if ( !m_pCache->deleteRow() ) 2119 continue; 2120 *result = 1; 2121 // now notify that we have deleted 2122 notifyRowSetAndClonesRowDeleted( *row, nDeletePosition ); 2123 } 2124 aEvt.Rows = aResults.getLength(); 2125 2126 // we have to check if we stand on the insert row and if so we have to reset it 2127 ORowSetNotifier aNotifier( this ); 2128 // this will call cancelRowModification on the cache if necessary 2129 // notification order 2130 // - rowChanged 2131 notifyAllListenersRowChanged(aGuard,aEvt); 2132 2133 // - IsModified 2134 // - IsNew 2135 aNotifier.fire(); 2136 2137 // - RowCount/IsRowCountFinal 2138 fireRowcount(); 2139 2140 return aResults; 2141 } 2142 2143 void ORowSet::notifyRowSetAndClonesRowDelete( const Any& _rBookmark ) 2144 { 2145 // notify ourself 2146 onDeleteRow( _rBookmark ); 2147 // notify the clones 2148 for (auto const& elem : m_aClones) 2149 { 2150 Reference< XUnoTunnel > xTunnel(elem.get(),UNO_QUERY); 2151 if(xTunnel.is()) 2152 { 2153 ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); 2154 if(pClone) 2155 pClone->onDeleteRow( _rBookmark ); 2156 } 2157 } 2158 } 2159 2160 void ORowSet::notifyRowSetAndClonesRowDeleted( const Any& _rBookmark, sal_Int32 _nPos ) 2161 { 2162 // notify ourself 2163 onDeletedRow( _rBookmark, _nPos ); 2164 // notify the clones 2165 for (auto const& clone : m_aClones) 2166 { 2167 Reference< XUnoTunnel > xTunnel(clone.get(),UNO_QUERY); 2168 if(xTunnel.is()) 2169 { 2170 ORowSetClone* pClone = reinterpret_cast<ORowSetClone*>(xTunnel->getSomething(ORowSetClone::getUnoTunnelImplementationId())); 2171 if(pClone) 2172 pClone->onDeletedRow( _rBookmark, _nPos ); 2173 } 2174 } 2175 } 2176 2177 Reference< XConnection > ORowSet::calcConnection(const Reference< XInteractionHandler >& _rxHandler) 2178 { 2179 MutexGuard aGuard(m_aMutex); 2180 if (!m_xActiveConnection.is()) 2181 { 2182 Reference< XConnection > xNewConn; 2183 if ( !m_aDataSourceName.isEmpty() ) 2184 { 2185 Reference< XDatabaseContext > xDatabaseContext( DatabaseContext::create(m_aContext) ); 2186 try 2187 { 2188 Reference< XDataSource > xDataSource( xDatabaseContext->getByName( m_aDataSourceName ), UNO_QUERY_THROW ); 2189 2190 // try connecting with the interaction handler 2191 Reference< XCompletedConnection > xComplConn( xDataSource, UNO_QUERY ); 2192 if ( _rxHandler.is() && xComplConn.is() ) 2193 { 2194 xNewConn = xComplConn->connectWithCompletion( _rxHandler ); 2195 } 2196 else 2197 { 2198 xNewConn = xDataSource->getConnection( m_aUser, m_aPassword ); 2199 } 2200 } 2201 catch ( const SQLException& ) 2202 { 2203 throw; 2204 } 2205 catch ( const Exception& ) 2206 { 2207 Any aError = ::cppu::getCaughtException(); 2208 OUString sMessage = ResourceManager::loadString( RID_NO_SUCH_DATA_SOURCE, 2209 "$name$", m_aDataSourceName, "$error$", extractExceptionMessage( m_aContext, aError ) ); 2210 ::dbtools::throwGenericSQLException( sMessage, *this, aError ); 2211 } 2212 } 2213 setActiveConnection(xNewConn); 2214 m_bOwnConnection = true; 2215 } 2216 return m_xActiveConnection; 2217 } 2218 2219 Reference< XNameAccess > ORowSet::impl_getTables_throw() 2220 { 2221 Reference< XNameAccess > xTables; 2222 2223 Reference< XTablesSupplier > xTablesAccess( m_xActiveConnection, UNO_QUERY ); 2224 if ( xTablesAccess.is() ) 2225 { 2226 xTables.set( xTablesAccess->getTables(), UNO_QUERY_THROW ); 2227 } 2228 else if ( m_xTables ) 2229 { 2230 xTables = m_xTables.get(); 2231 } 2232 else 2233 { 2234 if ( !m_xActiveConnection.is() ) 2235 throw SQLException(DBA_RES(RID_STR_CONNECTION_INVALID),*this,SQLSTATE_GENERAL,1000,Any() ); 2236 2237 bool bCase = true; 2238 try 2239 { 2240 Reference<XDatabaseMetaData> xMeta = m_xActiveConnection->getMetaData(); 2241 bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(); 2242 } 2243 catch(SQLException&) 2244 { 2245 DBG_UNHANDLED_EXCEPTION("dbaccess"); 2246 } 2247 2248 m_xTables = new OTableContainer(*this,m_aMutex,m_xActiveConnection,bCase,nullptr,nullptr,m_nInAppend); 2249 xTables = m_xTables.get(); 2250 Sequence<OUString> aTableFilter { "%" }; 2251 m_xTables->construct(aTableFilter,Sequence< OUString>()); 2252 } 2253 2254 return xTables; 2255 } 2256 2257 void ORowSet::impl_resetTables_nothrow() 2258 { 2259 if ( !m_xTables ) 2260 return; 2261 2262 try 2263 { 2264 m_xTables->dispose(); 2265 } 2266 catch( const Exception& ) 2267 { 2268 DBG_UNHANDLED_EXCEPTION("dbaccess"); 2269 } 2270 2271 m_xTables.clear(); 2272 } 2273 2274 void ORowSet::impl_initComposer_throw( OUString& _out_rCommandToExecute ) 2275 { 2276 bool bUseEscapeProcessing = impl_buildActiveCommand_throw( ); 2277 _out_rCommandToExecute = m_aActiveCommand; 2278 if ( !bUseEscapeProcessing ) 2279 return; 2280 2281 if (m_bCommandFacetsDirty) 2282 m_xComposer = nullptr; 2283 2284 Reference< XMultiServiceFactory > xFactory( m_xActiveConnection, UNO_QUERY ); 2285 if ( !m_xComposer.is() && xFactory.is() ) 2286 { 2287 try 2288 { 2289 m_xComposer.set( xFactory->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER ), UNO_QUERY_THROW ); 2290 } 2291 catch (const Exception& ) { m_xComposer = nullptr; } 2292 } 2293 if ( !m_xComposer.is() ) 2294 m_xComposer = new OSingleSelectQueryComposer( impl_getTables_throw(), m_xActiveConnection, m_aContext ); 2295 2296 m_xComposer->setCommand( m_aCommand,m_nCommandType ); 2297 m_aActiveCommand = m_xComposer->getQuery(); 2298 2299 m_xComposer->setFilter( m_bApplyFilter ? m_aFilter : OUString() ); 2300 m_xComposer->setHavingClause( m_bApplyFilter ? m_aHavingClause : OUString() ); 2301 2302 if ( m_bIgnoreResult ) 2303 { // append a "0=1" filter 2304 // don't simply overwrite an existent filter, this would lead to problems if this existent 2305 // filter contains parameters (since a keyset may add parameters itself) 2306 m_xComposer->setElementaryQuery( m_xComposer->getQuery( ) ); 2307 m_xComposer->setFilter( "0 = 1" ); 2308 } 2309 2310 m_xComposer->setOrder( m_aOrder ); 2311 m_xComposer->setGroup( m_aGroupBy ); 2312 2313 if ( !m_xColumns.is() ) 2314 { 2315 Reference< XColumnsSupplier > xCols( m_xComposer, UNO_QUERY_THROW ); 2316 m_xColumns = xCols->getColumns(); 2317 } 2318 2319 impl_initParametersContainer_nothrow(); 2320 2321 _out_rCommandToExecute = m_xComposer->getQueryWithSubstitution(); 2322 2323 m_bCommandFacetsDirty = false; 2324 } 2325 2326 bool ORowSet::impl_buildActiveCommand_throw() 2327 { 2328 // create the sql command 2329 // from a table name or get the command out of a query (not a view) 2330 // the last use the command as it is 2331 bool bDoEscapeProcessing = m_bUseEscapeProcessing; 2332 2333 m_aActiveCommand.clear(); 2334 OUString sCommand; 2335 2336 if ( m_aCommand.isEmpty() ) 2337 return bDoEscapeProcessing; 2338 2339 switch (m_nCommandType) 2340 { 2341 case CommandType::TABLE: 2342 { 2343 impl_resetTables_nothrow(); 2344 if ( bDoEscapeProcessing ) 2345 { 2346 Reference< XNameAccess > xTables( impl_getTables_throw() ); 2347 if ( xTables->hasByName(m_aCommand) ) 2348 { 2349 } 2350 else 2351 { 2352 OUString sMessage( DBA_RES( RID_STR_TABLE_DOES_NOT_EXIST ) ); 2353 throwGenericSQLException(sMessage.replaceAll( "$table$", m_aCommand ),*this); 2354 } 2355 } 2356 else 2357 { 2358 sCommand = "SELECT * FROM "; 2359 OUString sCatalog, sSchema, sTable; 2360 ::dbtools::qualifiedNameComponents( m_xActiveConnection->getMetaData(), m_aCommand, sCatalog, sSchema, sTable, ::dbtools::EComposeRule::InDataManipulation ); 2361 sCommand += ::dbtools::composeTableNameForSelect( m_xActiveConnection, sCatalog, sSchema, sTable ); 2362 } 2363 } 2364 break; 2365 2366 case CommandType::QUERY: 2367 { 2368 Reference< XQueriesSupplier > xQueriesAccess(m_xActiveConnection, UNO_QUERY); 2369 if (!xQueriesAccess.is()) 2370 throw SQLException(DBA_RES(RID_STR_NO_XQUERIESSUPPLIER),*this,OUString(),0,Any()); 2371 Reference< css::container::XNameAccess > xQueries(xQueriesAccess->getQueries()); 2372 if (xQueries->hasByName(m_aCommand)) 2373 { 2374 Reference< XPropertySet > xQuery(xQueries->getByName(m_aCommand),UNO_QUERY); 2375 OSL_ENSURE(xQuery.is(),"ORowSet::impl_buildActiveCommand_throw: Query is NULL!"); 2376 if ( xQuery.is() ) 2377 { 2378 xQuery->getPropertyValue(PROPERTY_COMMAND) >>= sCommand; 2379 xQuery->getPropertyValue(PROPERTY_ESCAPE_PROCESSING) >>= bDoEscapeProcessing; 2380 if ( bDoEscapeProcessing != m_bUseEscapeProcessing ) 2381 { 2382 bool bOldValue = m_bUseEscapeProcessing; 2383 m_bUseEscapeProcessing = bDoEscapeProcessing; 2384 fireProperty(PROPERTY_ID_ESCAPE_PROCESSING,bOldValue,bDoEscapeProcessing); 2385 } 2386 2387 OUString aCatalog,aSchema,aTable; 2388 xQuery->getPropertyValue(PROPERTY_UPDATE_CATALOGNAME) >>= aCatalog; 2389 xQuery->getPropertyValue(PROPERTY_UPDATE_SCHEMANAME) >>= aSchema; 2390 xQuery->getPropertyValue(PROPERTY_UPDATE_TABLENAME) >>= aTable; 2391 if(!aTable.isEmpty()) 2392 m_aUpdateTableName = composeTableName( m_xActiveConnection->getMetaData(), aCatalog, aSchema, aTable, false, ::dbtools::EComposeRule::InDataManipulation ); 2393 } 2394 } 2395 else 2396 { 2397 OUString sMessage( DBA_RES( RID_STR_QUERY_DOES_NOT_EXIST ) ); 2398 throwGenericSQLException(sMessage.replaceAll( "$table$", m_aCommand ),*this); 2399 } 2400 } 2401 break; 2402 2403 default: 2404 sCommand = m_aCommand; 2405 break; 2406 } 2407 2408 m_aActiveCommand = sCommand; 2409 2410 if ( m_aActiveCommand.isEmpty() && !bDoEscapeProcessing ) 2411 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_SQL_COMMAND ), StandardSQLState::FUNCTION_SEQUENCE_ERROR, *this ); 2412 2413 return bDoEscapeProcessing; 2414 } 2415 2416 void ORowSet::impl_initParametersContainer_nothrow() 2417 { 2418 OSL_PRECOND( !m_pParameters.is(), "ORowSet::impl_initParametersContainer_nothrow: already initialized the parameters!" ); 2419 2420 m_pParameters = new param::ParameterWrapperContainer( m_xComposer.get() ); 2421 // copy the premature parameters into the final ones 2422 size_t nParamCount( std::min( m_pParameters->size(), m_aPrematureParamValues->get().size() ) ); 2423 for ( size_t i=0; i<nParamCount; ++i ) 2424 { 2425 (*m_pParameters)[i] = m_aPrematureParamValues->get()[i]; 2426 } 2427 } 2428 2429 void ORowSet::impl_disposeParametersContainer_nothrow() 2430 { 2431 if ( !m_pParameters.is() ) 2432 return; 2433 2434 // copy the actual values to our "premature" ones, to preserve them for later use 2435 size_t nParamCount( m_pParameters->size() ); 2436 m_aPrematureParamValues->get().resize( nParamCount ); 2437 for ( size_t i=0; i<nParamCount; ++i ) 2438 { 2439 m_aPrematureParamValues->get()[i] = (*m_pParameters)[i]; 2440 } 2441 2442 m_pParameters->dispose(); 2443 m_pParameters = nullptr; 2444 } 2445 2446 ORowSetValue& ORowSet::getParameterStorage(sal_Int32 parameterIndex) 2447 { 2448 ::connectivity::checkDisposed( ORowSet_BASE1::rBHelper.bDisposed ); 2449 if ( parameterIndex < 1 ) 2450 throwInvalidIndexException( *this ); 2451 2452 if ( m_aParametersSet.size() < static_cast<size_t>(parameterIndex) ) 2453 m_aParametersSet.resize( parameterIndex ,false); 2454 m_aParametersSet[parameterIndex - 1] = true; 2455 2456 if ( m_pParameters.is() ) 2457 { 2458 if ( m_bCommandFacetsDirty ) 2459 // need to rebuild the parameters, since some property which contributes to the 2460 // complete command, and thus the parameters, changed 2461 impl_disposeParametersContainer_nothrow(); 2462 if ( m_pParameters.is() ) 2463 { 2464 if ( static_cast<size_t>(parameterIndex) > m_pParameters->size() ) 2465 throwInvalidIndexException( *this ); 2466 return (*m_pParameters)[ parameterIndex - 1 ]; 2467 } 2468 } 2469 2470 if ( m_aPrematureParamValues->get().size() < static_cast<size_t>(parameterIndex) ) 2471 m_aPrematureParamValues->get().resize( parameterIndex ); 2472 return m_aPrematureParamValues->get()[ parameterIndex - 1 ]; 2473 } 2474 2475 // XParameters 2476 void SAL_CALL ORowSet::setNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/ ) 2477 { 2478 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2479 2480 getParameterStorage( parameterIndex ).setNull(); 2481 m_bParametersDirty = true; 2482 } 2483 2484 void SAL_CALL ORowSet::setObjectNull( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& /*typeName*/ ) 2485 { 2486 setNull( parameterIndex, sqlType ); 2487 } 2488 2489 void ORowSet::setParameter(sal_Int32 parameterIndex, const ORowSetValue& x) 2490 { 2491 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2492 2493 getParameterStorage( parameterIndex ) = x; 2494 m_bParametersDirty = true; 2495 } 2496 2497 void SAL_CALL ORowSet::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) 2498 { 2499 setParameter(parameterIndex, static_cast<bool>(x)); 2500 } 2501 2502 void SAL_CALL ORowSet::setByte( sal_Int32 parameterIndex, sal_Int8 x ) 2503 { 2504 setParameter(parameterIndex,x); 2505 } 2506 2507 void SAL_CALL ORowSet::setShort( sal_Int32 parameterIndex, sal_Int16 x ) 2508 { 2509 setParameter(parameterIndex,x); 2510 } 2511 2512 void SAL_CALL ORowSet::setInt( sal_Int32 parameterIndex, sal_Int32 x ) 2513 { 2514 setParameter(parameterIndex,x); 2515 } 2516 2517 void SAL_CALL ORowSet::setLong( sal_Int32 parameterIndex, sal_Int64 x ) 2518 { 2519 setParameter(parameterIndex,x); 2520 } 2521 2522 void SAL_CALL ORowSet::setFloat( sal_Int32 parameterIndex, float x ) 2523 { 2524 setParameter(parameterIndex,x); 2525 } 2526 2527 void SAL_CALL ORowSet::setDouble( sal_Int32 parameterIndex, double x ) 2528 { 2529 setParameter(parameterIndex,x); 2530 } 2531 2532 void SAL_CALL ORowSet::setString( sal_Int32 parameterIndex, const OUString& x ) 2533 { 2534 setParameter(parameterIndex,x); 2535 } 2536 2537 void SAL_CALL ORowSet::setBytes( sal_Int32 parameterIndex, const Sequence< sal_Int8 >& x ) 2538 { 2539 setParameter(parameterIndex,x); 2540 } 2541 2542 void SAL_CALL ORowSet::setDate( sal_Int32 parameterIndex, const css::util::Date& x ) 2543 { 2544 setParameter(parameterIndex,x); 2545 } 2546 2547 void SAL_CALL ORowSet::setTime( sal_Int32 parameterIndex, const css::util::Time& x ) 2548 { 2549 setParameter(parameterIndex,x); 2550 } 2551 2552 void SAL_CALL ORowSet::setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x ) 2553 { 2554 setParameter(parameterIndex,x); 2555 } 2556 2557 void SAL_CALL ORowSet::setBinaryStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) 2558 { 2559 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2560 ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); 2561 2562 try 2563 { 2564 Sequence <sal_Int8> aData; 2565 x->readBytes(aData, length); 2566 rParamValue = aData; 2567 m_bParametersDirty = true; 2568 x->closeInput(); 2569 } 2570 catch( Exception const & ) 2571 { 2572 css::uno::Any anyEx = cppu::getCaughtException(); 2573 throw SQLException("ORowSet::setBinaryStream", *this, "S1000", 0,anyEx); 2574 } 2575 } 2576 2577 void SAL_CALL ORowSet::setCharacterStream( sal_Int32 parameterIndex, const Reference< css::io::XInputStream >& x, sal_Int32 length ) 2578 { 2579 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2580 ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); 2581 try 2582 { 2583 Sequence <sal_Int8> aData; 2584 OUString aDataStr; 2585 // the data is given as character data and the length defines the character length 2586 sal_Int32 nSize = x->readBytes(aData, length * sizeof(sal_Unicode)); 2587 if (nSize / sizeof(sal_Unicode)) 2588 aDataStr = OUString(reinterpret_cast<sal_Unicode const *>(aData.getConstArray()), nSize / sizeof(sal_Unicode)); 2589 m_bParametersDirty = true; 2590 rParamValue = aDataStr; 2591 rParamValue.setTypeKind( DataType::LONGVARCHAR ); 2592 x->closeInput(); 2593 } 2594 catch( Exception const & ) 2595 { 2596 css::uno::Any anyEx = cppu::getCaughtException(); 2597 throw SQLException("ORowSet::setCharacterStream", *this, "S1000", 0, anyEx); 2598 } 2599 } 2600 2601 void SAL_CALL ORowSet::setObject( sal_Int32 parameterIndex, const Any& x ) 2602 { 2603 if ( !::dbtools::implSetObject( this, parameterIndex, x ) ) 2604 { // there is no other setXXX call which can handle the value in x 2605 throw SQLException(); 2606 } 2607 m_bParametersDirty = true; 2608 } 2609 2610 void SAL_CALL ORowSet::setObjectWithInfo( sal_Int32 parameterIndex, const Any& x, sal_Int32 targetSqlType, sal_Int32 /*scale*/ ) 2611 { 2612 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2613 ORowSetValue& rParamValue( getParameterStorage( parameterIndex ) ); 2614 setObject( parameterIndex, x ); 2615 rParamValue.setTypeKind( targetSqlType ); 2616 } 2617 2618 void SAL_CALL ORowSet::setRef( sal_Int32 /*parameterIndex*/, const Reference< XRef >& /*x*/ ) 2619 { 2620 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this ); 2621 } 2622 2623 void SAL_CALL ORowSet::setBlob( sal_Int32 /*parameterIndex*/, const Reference< XBlob >& /*x*/ ) 2624 { 2625 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this ); 2626 } 2627 2628 void SAL_CALL ORowSet::setClob( sal_Int32 /*parameterIndex*/, const Reference< XClob >& /*x*/ ) 2629 { 2630 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this ); 2631 } 2632 2633 void SAL_CALL ORowSet::setArray( sal_Int32 /*parameterIndex*/, const Reference< XArray >& /*x*/ ) 2634 { 2635 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this ); 2636 } 2637 2638 void SAL_CALL ORowSet::clearParameters( ) 2639 { 2640 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper.bDisposed); 2641 2642 ::osl::MutexGuard aGuard( m_aColumnsMutex ); 2643 2644 size_t nParamCount( m_pParameters.is() ? m_pParameters->size() : m_aPrematureParamValues->get().size() ); 2645 for ( size_t i=1; i<=nParamCount; ++i ) 2646 getParameterStorage( static_cast<sal_Int32>(i) ).setNull(); 2647 m_aParametersSet.clear(); 2648 } 2649 2650 Any SAL_CALL ORowSet::getWarnings( ) 2651 { 2652 return m_aWarnings.getWarnings(); 2653 } 2654 2655 void SAL_CALL ORowSet::clearWarnings( ) 2656 { 2657 m_aWarnings.clearWarnings(); 2658 } 2659 2660 void ORowSet::doCancelModification( ) 2661 { 2662 if ( isModification() ) 2663 { 2664 // read-only flag restored 2665 impl_restoreDataColumnsWriteable_throw(); 2666 m_pCache->cancelRowModification(); 2667 } 2668 m_bModified = false; 2669 m_bIsInsertRow = false; 2670 } 2671 2672 bool ORowSet::isModification( ) 2673 { 2674 return isNew(); 2675 } 2676 2677 bool ORowSet::isModified( ) 2678 { 2679 return m_bModified; 2680 } 2681 2682 bool ORowSet::isNew( ) 2683 { 2684 return m_bNew; 2685 } 2686 2687 bool ORowSet::isPropertyChangeNotificationEnabled() const 2688 { 2689 return m_bPropChangeNotifyEnabled; 2690 } 2691 2692 void ORowSet::checkUpdateIterator() 2693 { 2694 if(!m_bIsInsertRow) 2695 { 2696 m_pCache->setUpdateIterator(m_aCurrentRow); 2697 m_aCurrentRow = m_pCache->m_aInsertRow; 2698 m_bIsInsertRow = true; 2699 } 2700 } 2701 2702 void ORowSet::checkUpdateConditions(sal_Int32 columnIndex) 2703 { 2704 checkCache(); 2705 if ( m_nResultSetConcurrency == ResultSetConcurrency::READ_ONLY) 2706 ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY ), StandardSQLState::GENERAL_ERROR, *this ); 2707 2708 if ( rowDeleted() ) 2709 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED ), StandardSQLState::INVALID_CURSOR_POSITION, *this ); 2710 2711 if ( m_aCurrentRow.isNull() ) 2712 ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_CURSOR_STATE ), StandardSQLState::INVALID_CURSOR_STATE, *this ); 2713 2714 if ( columnIndex <= 0 || sal_Int32((*m_aCurrentRow)->get().size()) <= columnIndex ) 2715 ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_INDEX ), StandardSQLState::INVALID_DESCRIPTOR_INDEX, *this ); 2716 } 2717 2718 void SAL_CALL ORowSet::refreshRow( ) 2719 { 2720 2721 ORowSetNotifier aNotifier( this ); 2722 // this will call cancelRowModification on the cache if necessary 2723 2724 // notification order: 2725 if ( m_bModified && m_pCache ) 2726 implCancelRowUpdates( false ); // do _not_ notify the IsModify - will do this ourself below 2727 2728 // - column values 2729 ORowSetBase::refreshRow(); 2730 2731 // - IsModified 2732 // - IsNew 2733 aNotifier.fire( ); 2734 } 2735 2736 void ORowSet::impl_rebuild_throw(::osl::ResettableMutexGuard& _rGuard) 2737 { 2738 Reference< XResultSet > xResultSet(m_xStatement->executeQuery()); 2739 m_pCache->reset(xResultSet); 2740 m_aWarnings.setExternalWarnings( Reference< XWarningsSupplier >( xResultSet, UNO_QUERY ) ); 2741 notifyAllListeners(_rGuard); 2742 } 2743 2744 // *********************************************************** 2745 // ORowSetClone 2746 // *********************************************************** 2747 2748 ORowSetClone::ORowSetClone( const Reference<XComponentContext>& _rContext, ORowSet& rParent, ::osl::Mutex* _pMutex ) 2749 :OSubComponent(m_aMutex, rParent) 2750 ,ORowSetBase( _rContext, OComponentHelper::rBHelper, _pMutex ) 2751 ,m_pParent(&rParent) 2752 ,m_nFetchDirection(rParent.m_nFetchDirection) 2753 ,m_nFetchSize(rParent.m_nFetchSize) 2754 ,m_bIsBookmarkable(true) 2755 { 2756 2757 m_nResultSetType = rParent.m_nResultSetType; 2758 m_nResultSetConcurrency = ResultSetConcurrency::READ_ONLY; 2759 m_pMySelf = this; 2760 m_bClone = true; 2761 m_bBeforeFirst = rParent.m_bBeforeFirst; 2762 m_bAfterLast = rParent.m_bAfterLast; 2763 m_pCache = rParent.m_pCache; 2764 m_aBookmark = rParent.m_aBookmark; 2765 m_aCurrentRow = m_pCache->createIterator(this); 2766 m_xNumberFormatTypes = rParent.m_xNumberFormatTypes; 2767 2768 m_aOldRow = m_pCache->registerOldRow(); 2769 2770 ::rtl::Reference< ::connectivity::OSQLColumns> aColumns = new ::connectivity::OSQLColumns(); 2771 std::vector< OUString> aNames; 2772 2773 OUString aDescription; 2774 Locale aLocale = SvtSysLocale().GetLanguageTag().getLocale(); 2775 2776 if ( rParent.m_pColumns ) 2777 { 2778 Sequence< OUString> aSeq = rParent.m_pColumns->getElementNames(); 2779 const OUString* pIter = aSeq.getConstArray(); 2780 const OUString* pEnd = pIter + aSeq.getLength(); 2781 aColumns->get().reserve(aSeq.getLength()+1); 2782 for(sal_Int32 i=1;pIter != pEnd ;++pIter,++i) 2783 { 2784 Reference<XPropertySet> xColumn; 2785 rParent.m_pColumns->getByName(*pIter) >>= xColumn; 2786 if(xColumn->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION)) 2787 aDescription = comphelper::getString(xColumn->getPropertyValue(PROPERTY_DESCRIPTION)); 2788 2789 OUString sParseLabel; 2790 xColumn->getPropertyValue(PROPERTY_LABEL) >>= sParseLabel; 2791 ORowSetColumn* pColumn = new ORowSetColumn( rParent.getMetaData(), 2792 this, 2793 i, 2794 rParent.m_xActiveConnection->getMetaData(), 2795 aDescription, 2796 sParseLabel, 2797 [this] (sal_Int32 const column) -> ORowSetValue const& { 2798 return this->getValue(column); 2799 }); 2800 aColumns->get().emplace_back(pColumn); 2801 pColumn->setName(*pIter); 2802 aNames.push_back(*pIter); 2803 m_aDataColumns.push_back(pColumn); 2804 2805 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN,xColumn->getPropertyValue(PROPERTY_ALIGN)); 2806 sal_Int32 nFormatKey = 0; 2807 xColumn->getPropertyValue(PROPERTY_NUMBERFORMAT) >>= nFormatKey; 2808 if(!nFormatKey && xColumn.is() && m_xNumberFormatTypes.is()) 2809 nFormatKey = ::dbtools::getDefaultNumberFormat(xColumn,m_xNumberFormatTypes,aLocale); 2810 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT,makeAny(nFormatKey)); 2811 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION,xColumn->getPropertyValue(PROPERTY_RELATIVEPOSITION)); 2812 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH,xColumn->getPropertyValue(PROPERTY_WIDTH)); 2813 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN,xColumn->getPropertyValue(PROPERTY_HIDDEN)); 2814 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLMODEL,xColumn->getPropertyValue(PROPERTY_CONTROLMODEL)); 2815 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HELPTEXT,xColumn->getPropertyValue(PROPERTY_HELPTEXT)); 2816 pColumn->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLDEFAULT,xColumn->getPropertyValue(PROPERTY_CONTROLDEFAULT)); 2817 2818 } 2819 } 2820 Reference<XDatabaseMetaData> xMeta = rParent.m_xActiveConnection->getMetaData(); 2821 m_pColumns.reset( new ORowSetDataColumns(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers(), 2822 aColumns,*this,m_aMutex,aNames) ); 2823 2824 sal_Int32 const nRT = PropertyAttribute::READONLY | PropertyAttribute::TRANSIENT; 2825 2826 // sdb.RowSet Properties 2827 registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION,PROPERTY_ID_ACTIVE_CONNECTION, PropertyAttribute::MAYBEVOID|PropertyAttribute::READONLY, &rParent.m_aActiveConnection, cppu::UnoType<XConnection>::get()); 2828 registerProperty(PROPERTY_RESULTSETCONCURRENCY, PROPERTY_ID_RESULTSETCONCURRENCY, PropertyAttribute::READONLY, &m_nResultSetConcurrency,::cppu::UnoType<sal_Int32>::get()); 2829 registerProperty(PROPERTY_RESULTSETTYPE, PROPERTY_ID_RESULTSETTYPE, PropertyAttribute::READONLY, &m_nResultSetType, ::cppu::UnoType<sal_Int32>::get()); 2830 registerProperty(PROPERTY_FETCHDIRECTION, PROPERTY_ID_FETCHDIRECTION, PropertyAttribute::TRANSIENT, &m_nFetchDirection, ::cppu::UnoType<sal_Int32>::get()); 2831 registerProperty(PROPERTY_FETCHSIZE, PROPERTY_ID_FETCHSIZE, PropertyAttribute::TRANSIENT, &m_nFetchSize, ::cppu::UnoType<sal_Int32>::get()); 2832 registerProperty(PROPERTY_ISBOOKMARKABLE, PROPERTY_ID_ISBOOKMARKABLE, nRT, &m_bIsBookmarkable, cppu::UnoType<bool>::get()); 2833 } 2834 2835 ORowSetClone::~ORowSetClone() 2836 { 2837 } 2838 2839 // css::XTypeProvider 2840 Sequence< Type > ORowSetClone::getTypes() 2841 { 2842 return ::comphelper::concatSequences(OSubComponent::getTypes(),ORowSetBase::getTypes()); 2843 } 2844 2845 // css::XInterface 2846 Any ORowSetClone::queryInterface( const Type & rType ) 2847 { 2848 Any aRet = ORowSetBase::queryInterface(rType); 2849 if(!aRet.hasValue()) 2850 aRet = OSubComponent::queryInterface(rType); 2851 return aRet; 2852 } 2853 2854 void ORowSetClone::acquire() throw() 2855 { 2856 OSubComponent::acquire(); 2857 } 2858 2859 void ORowSetClone::release() throw() 2860 { 2861 OSubComponent::release(); 2862 } 2863 2864 // XServiceInfo 2865 OUString ORowSetClone::getImplementationName( ) 2866 { 2867 return OUString("com.sun.star.sdb.ORowSetClone"); 2868 } 2869 2870 sal_Bool ORowSetClone::supportsService( const OUString& _rServiceName ) 2871 { 2872 return cppu::supportsService(this, _rServiceName); 2873 } 2874 2875 Sequence< OUString > ORowSetClone::getSupportedServiceNames( ) 2876 { 2877 Sequence< OUString > aSNS( 2 ); 2878 aSNS[0] = SERVICE_SDBC_RESULTSET; 2879 aSNS[1] = SERVICE_SDB_RESULTSET; 2880 return aSNS; 2881 } 2882 2883 // OComponentHelper 2884 void ORowSetClone::disposing() 2885 { 2886 MutexGuard aGuard( m_aMutex ); 2887 ORowSetBase::disposing(); 2888 2889 m_pParent = nullptr; 2890 m_pMutex = &m_aMutex; // this must be done here because someone could hold a ref to us and try to do something 2891 OSubComponent::disposing(); 2892 } 2893 2894 // XCloseable 2895 void ORowSetClone::close() 2896 { 2897 { 2898 MutexGuard aGuard( m_aMutex ); 2899 if (OComponentHelper::rBHelper.bDisposed) 2900 throw DisposedException(); 2901 } 2902 dispose(); 2903 } 2904 2905 // comphelper::OPropertyArrayUsageHelper 2906 ::cppu::IPropertyArrayHelper* ORowSetClone::createArrayHelper( ) const 2907 { 2908 Sequence< Property > aProps; 2909 describeProperties(aProps); 2910 return new ::cppu::OPropertyArrayHelper(aProps); 2911 } 2912 2913 // cppu::OPropertySetHelper 2914 ::cppu::IPropertyArrayHelper& SAL_CALL ORowSetClone::getInfoHelper() 2915 { 2916 return *::comphelper::OPropertyArrayUsageHelper<ORowSetClone>::getArrayHelper(); 2917 } 2918 2919 Sequence< sal_Int8 > ORowSetClone::getUnoTunnelImplementationId() 2920 { 2921 static ::cppu::OImplementationId implId; 2922 2923 return implId.getImplementationId(); 2924 } 2925 2926 // css::XUnoTunnel 2927 sal_Int64 SAL_CALL ORowSetClone::getSomething( const Sequence< sal_Int8 >& rId ) 2928 { 2929 if (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 2930 return reinterpret_cast<sal_Int64>(this); 2931 2932 return 0; 2933 } 2934 2935 void SAL_CALL ORowSetClone::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) 2936 { 2937 if ( nHandle == PROPERTY_ID_FETCHSIZE ) 2938 { 2939 if ( m_pParent ) 2940 m_pParent->setFastPropertyValue_NoBroadcast( nHandle, rValue ); 2941 } 2942 2943 OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle,rValue); 2944 } 2945 2946 void ORowSetClone::doCancelModification( ) 2947 { 2948 } 2949 2950 bool ORowSetClone::isModification( ) 2951 { 2952 return false; 2953 } 2954 2955 bool ORowSetClone::isModified( ) 2956 { 2957 return false; 2958 } 2959 2960 bool ORowSetClone::isNew( ) 2961 { 2962 return false; 2963 } 2964 2965 void SAL_CALL ORowSetClone::execute( ) 2966 { 2967 throwFunctionNotSupportedSQLException( "RowSetClone::XRowSet::execute", *this ); 2968 } 2969 2970 void SAL_CALL ORowSetClone::addRowSetListener( const Reference< XRowSetListener >& ) 2971 { 2972 throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this ); 2973 } 2974 2975 void SAL_CALL ORowSetClone::removeRowSetListener( const Reference< XRowSetListener >& ) 2976 { 2977 throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this ); 2978 } 2979 2980 } // dbaccess 2981 2982 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2983
