xref: /core/dbaccess/source/core/api/RowSet.cxx (revision 435b64ec)
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