1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
27 #include <stringconstants.hxx>
28 #include <sdbcoretools.hxx>
29 #include <SingleSelectQueryComposer.hxx>
30 #include "CRowSetColumn.hxx"
31 #include "CRowSetDataColumn.hxx"
32 #include "RowSetCache.hxx"
33 #include <strings.hrc>
34 #include <core_resource.hxx>
35 #include <tablecontainer.hxx>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/sdb/CommandType.hpp>
40 #include <com/sun/star/sdb/DatabaseContext.hpp>
41 #include <com/sun/star/sdb/ErrorCondition.hpp>
42 #include <com/sun/star/sdb/RowChangeAction.hpp>
43 #include <com/sun/star/sdb/RowSetVetoException.hpp>
44 #include <com/sun/star/sdb/XCompletedConnection.hpp>
45 #include <com/sun/star/sdb/XParametersSupplier.hpp>
46 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
47 #include <com/sun/star/sdbc/FetchDirection.hpp>
48 #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
49 #include <com/sun/star/sdbc/ResultSetType.hpp>
50 #include <com/sun/star/sdbc/XDataSource.hpp>
51 #include <com/sun/star/sdbcx/Privilege.hpp>
52 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
54 #include <comphelper/extract.hxx>
55 #include <comphelper/seqstream.hxx>
56 #include <comphelper/sequence.hxx>
57 #include <comphelper/servicehelper.hxx>
58 #include <comphelper/types.hxx>
59 #include <comphelper/uno3.hxx>
60 #include <connectivity/BlobHelper.hxx>
61 #include <connectivity/dbconversion.hxx>
62 #include <connectivity/dbexception.hxx>
63 #include <connectivity/dbtools.hxx>
64 #include <cppuhelper/exc_hlp.hxx>
65 #include <cppuhelper/interfacecontainer.h>
66 #include <cppuhelper/supportsservice.hxx>
67 #include <cppuhelper/typeprovider.hxx>
68 #include <i18nlangtag/languagetag.hxx>
69 #include <o3tl/safeint.hxx>
70 #include <unotools/syslocale.hxx>
71 #include <tools/diagnose_ex.h>
74 using namespace dbaccess
;
75 using namespace connectivity
;
76 using namespace comphelper
;
77 using namespace dbtools
;
78 using namespace ::com::sun::star
;
79 using namespace ::com::sun::star::uno
;
80 using namespace ::com::sun::star::beans
;
81 using namespace ::com::sun::star::sdbc
;
82 using namespace ::com::sun::star::sdb
;
83 using namespace ::com::sun::star::sdbcx
;
84 using namespace ::com::sun::star::container
;
85 using namespace ::com::sun::star::lang
;
86 using namespace ::com::sun::star::task
;
87 using namespace ::com::sun::star::util
;
88 using namespace ::cppu
;
89 using namespace ::osl
;
91 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
92 com_sun_star_comp_dba_ORowSet_get_implementation(css::uno::XComponentContext
* context
,
93 css::uno::Sequence
<css::uno::Any
> const &)
95 return cppu::acquire(new ORowSet(context
));
100 ORowSet::ORowSet( const Reference
< css::uno::XComponentContext
>& _rxContext
)
101 :ORowSet_BASE1(m_aMutex
)
102 ,ORowSetBase( _rxContext
, ORowSet_BASE1::rBHelper
, &m_aMutex
)
103 ,m_aPrematureParamValues(new ORowSetValueVector
)
104 ,m_aParameterValueForCache(new ORowSetValueVector
)
105 ,m_aRowsetListeners(*m_pMutex
)
106 ,m_aApproveListeners(*m_pMutex
)
107 ,m_aRowsChangeListener(*m_pMutex
)
108 ,m_sErrorString(ResourceManager::loadString(RID_STR_COMMAND_LEADING_TO_ERROR
))
109 ,m_nFetchDirection(FetchDirection::FORWARD
)
114 ,m_nCommandType(CommandType::COMMAND
)
115 ,m_nTransactionIsolation(0)
117 ,m_nLastKnownRowCount(0)
119 ,m_bInsertingRow(false)
120 ,m_bLastKnownRowCountFinal(false)
121 ,m_bUseEscapeProcessing(true)
122 ,m_bApplyFilter(false)
123 ,m_bCommandFacetsDirty( true )
124 ,m_bParametersDirty( true )
126 ,m_bRebuildConnOnExecute(false)
127 ,m_bIsBookmarkable(true)
129 ,m_bCanUpdateInsertedRows(true)
130 ,m_bOwnConnection(false)
131 ,m_bPropChangeNotifyEnabled(true)
133 m_nResultSetType
= ResultSetType::SCROLL_SENSITIVE
;
134 m_nResultSetConcurrency
= ResultSetConcurrency::UPDATABLE
;
136 m_aActiveConnection
<<= m_xActiveConnection
;
138 sal_Int32
const nRBT
= PropertyAttribute::READONLY
| PropertyAttribute::BOUND
| PropertyAttribute::TRANSIENT
;
139 sal_Int32
const nRT
= PropertyAttribute::READONLY
| PropertyAttribute::TRANSIENT
;
140 sal_Int32
const nBT
= PropertyAttribute::BOUND
| PropertyAttribute::TRANSIENT
;
142 m_aPrematureParamValues
->resize( 0 );
144 // sdb.RowSet Properties
145 registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION
,PROPERTY_ID_ACTIVE_CONNECTION
, PropertyAttribute::MAYBEVOID
|PropertyAttribute::TRANSIENT
|PropertyAttribute::BOUND
, &m_aActiveConnection
, cppu::UnoType
<XConnection
>::get());
146 registerProperty(PROPERTY_DATASOURCENAME
, PROPERTY_ID_DATASOURCENAME
, PropertyAttribute::BOUND
, &m_aDataSourceName
, ::cppu::UnoType
<OUString
>::get());
147 registerProperty(PROPERTY_COMMAND
, PROPERTY_ID_COMMAND
, PropertyAttribute::BOUND
, &m_aCommand
, ::cppu::UnoType
<OUString
>::get());
148 registerProperty(PROPERTY_COMMAND_TYPE
, PROPERTY_ID_COMMAND_TYPE
, PropertyAttribute::BOUND
, &m_nCommandType
, ::cppu::UnoType
<sal_Int32
>::get());
149 registerProperty(PROPERTY_ACTIVECOMMAND
, PROPERTY_ID_ACTIVECOMMAND
, nRBT
, &m_aActiveCommand
, ::cppu::UnoType
<OUString
>::get());
150 registerProperty(PROPERTY_IGNORERESULT
, PROPERTY_ID_IGNORERESULT
, PropertyAttribute::BOUND
, &m_bIgnoreResult
, cppu::UnoType
<bool>::get());
151 registerProperty(PROPERTY_FILTER
, PROPERTY_ID_FILTER
, PropertyAttribute::BOUND
, &m_aFilter
, ::cppu::UnoType
<OUString
>::get());
152 registerProperty(PROPERTY_HAVING_CLAUSE
, PROPERTY_ID_HAVING_CLAUSE
, PropertyAttribute::BOUND
, &m_aHavingClause
, ::cppu::UnoType
<OUString
>::get());
153 registerProperty(PROPERTY_GROUP_BY
, PROPERTY_ID_GROUP_BY
, PropertyAttribute::BOUND
, &m_aGroupBy
, ::cppu::UnoType
<OUString
>::get());
154 registerProperty(PROPERTY_APPLYFILTER
, PROPERTY_ID_APPLYFILTER
, PropertyAttribute::BOUND
, &m_bApplyFilter
, cppu::UnoType
<bool>::get());
155 registerProperty(PROPERTY_ORDER
, PROPERTY_ID_ORDER
, PropertyAttribute::BOUND
, &m_aOrder
, ::cppu::UnoType
<OUString
>::get());
156 registerProperty(PROPERTY_PRIVILEGES
, PROPERTY_ID_PRIVILEGES
, nRT
, &m_nPrivileges
, ::cppu::UnoType
<sal_Int32
>::get());
157 registerProperty(PROPERTY_ISMODIFIED
, PROPERTY_ID_ISMODIFIED
, nBT
, &m_bModified
, cppu::UnoType
<bool>::get());
158 registerProperty(PROPERTY_ISNEW
, PROPERTY_ID_ISNEW
, nRBT
, &m_bNew
, cppu::UnoType
<bool>::get());
159 registerProperty(PROPERTY_SINGLESELECTQUERYCOMPOSER
,PROPERTY_ID_SINGLESELECTQUERYCOMPOSER
, nRT
, &m_xComposer
, cppu::UnoType
<XSingleSelectQueryComposer
>::get());
161 // sdbcx.ResultSet Properties
162 registerProperty(PROPERTY_ISBOOKMARKABLE
, PROPERTY_ID_ISBOOKMARKABLE
, nRT
, &m_bIsBookmarkable
, cppu::UnoType
<bool>::get());
163 registerProperty(PROPERTY_CANUPDATEINSERTEDROWS
,PROPERTY_ID_CANUPDATEINSERTEDROWS
, nRT
, &m_bCanUpdateInsertedRows
, cppu::UnoType
<bool>::get());
164 // sdbc.ResultSet Properties
165 registerProperty(PROPERTY_RESULTSETCONCURRENCY
, PROPERTY_ID_RESULTSETCONCURRENCY
, PropertyAttribute::TRANSIENT
, &m_nResultSetConcurrency
,::cppu::UnoType
<sal_Int32
>::get());
166 registerProperty(PROPERTY_RESULTSETTYPE
, PROPERTY_ID_RESULTSETTYPE
, PropertyAttribute::TRANSIENT
, &m_nResultSetType
, ::cppu::UnoType
<sal_Int32
>::get());
167 registerProperty(PROPERTY_FETCHDIRECTION
, PROPERTY_ID_FETCHDIRECTION
, PropertyAttribute::TRANSIENT
, &m_nFetchDirection
, ::cppu::UnoType
<sal_Int32
>::get());
168 registerProperty(PROPERTY_FETCHSIZE
, PROPERTY_ID_FETCHSIZE
, PropertyAttribute::TRANSIENT
, &m_nFetchSize
, ::cppu::UnoType
<sal_Int32
>::get());
170 // sdbc.RowSet Properties
171 registerProperty(PROPERTY_URL
, PROPERTY_ID_URL
, 0, &m_aURL
, ::cppu::UnoType
<OUString
>::get());
172 registerProperty(PROPERTY_TRANSACTIONISOLATION
, PROPERTY_ID_TRANSACTIONISOLATION
, PropertyAttribute::TRANSIENT
, &m_nTransactionIsolation
,::cppu::UnoType
<sal_Int32
>::get());
173 registerMayBeVoidProperty(PROPERTY_TYPEMAP
, PROPERTY_ID_TYPEMAP
, PropertyAttribute::MAYBEVOID
|PropertyAttribute::TRANSIENT
, &m_aTypeMap
, cppu::UnoType
<XNameAccess
>::get());
174 registerProperty(PROPERTY_ESCAPE_PROCESSING
,PROPERTY_ID_ESCAPE_PROCESSING
, PropertyAttribute::BOUND
, &m_bUseEscapeProcessing
,cppu::UnoType
<bool>::get() );
175 registerProperty(PROPERTY_QUERYTIMEOUT
, PROPERTY_ID_QUERYTIMEOUT
, PropertyAttribute::TRANSIENT
, &m_nQueryTimeOut
, ::cppu::UnoType
<sal_Int32
>::get());
176 registerProperty(PROPERTY_MAXFIELDSIZE
, PROPERTY_ID_MAXFIELDSIZE
, PropertyAttribute::TRANSIENT
, &m_nMaxFieldSize
, ::cppu::UnoType
<sal_Int32
>::get());
177 registerProperty(PROPERTY_MAXROWS
, PROPERTY_ID_MAXROWS
, 0, &m_nMaxRows
, ::cppu::UnoType
<sal_Int32
>::get() );
178 registerProperty(PROPERTY_USER
, PROPERTY_ID_USER
, PropertyAttribute::TRANSIENT
, &m_aUser
, ::cppu::UnoType
<OUString
>::get());
179 registerProperty(PROPERTY_PASSWORD
, PROPERTY_ID_PASSWORD
, PropertyAttribute::TRANSIENT
, &m_aPassword
, ::cppu::UnoType
<OUString
>::get());
181 registerProperty(PROPERTY_UPDATE_CATALOGNAME
, PROPERTY_ID_UPDATE_CATALOGNAME
, PropertyAttribute::BOUND
, &m_aUpdateCatalogName
, ::cppu::UnoType
<OUString
>::get());
182 registerProperty(PROPERTY_UPDATE_SCHEMANAME
, PROPERTY_ID_UPDATE_SCHEMANAME
, PropertyAttribute::BOUND
, &m_aUpdateSchemaName
, ::cppu::UnoType
<OUString
>::get());
183 registerProperty(PROPERTY_UPDATE_TABLENAME
, PROPERTY_ID_UPDATE_TABLENAME
, PropertyAttribute::BOUND
, &m_aUpdateTableName
, ::cppu::UnoType
<OUString
>::get());
186 registerProperty(PROPERTY_CHANGE_NOTIFICATION_ENABLED
, PROPERTY_ID_PROPCHANGE_NOTIFY
, PropertyAttribute::BOUND
, &m_bPropChangeNotifyEnabled
, cppu::UnoType
<bool>::get());
191 if ( !m_rBHelper
.bDisposed
&& !m_rBHelper
.bInDispose
)
193 SAL_WARN("dbaccess", "Please check who doesn't dispose this component!");
194 osl_atomic_increment( &m_refCount
);
199 void ORowSet::getPropertyDefaultByHandle( sal_Int32 _nHandle
, Any
& _rDefault
) const
203 case PROPERTY_ID_COMMAND_TYPE
:
204 _rDefault
<<= CommandType::COMMAND
;
206 case PROPERTY_ID_IGNORERESULT
:
209 case PROPERTY_ID_APPLYFILTER
:
212 case PROPERTY_ID_ISMODIFIED
:
215 case PROPERTY_ID_ISBOOKMARKABLE
:
218 case PROPERTY_ID_CANUPDATEINSERTEDROWS
:
221 case PROPERTY_ID_RESULTSETTYPE
:
222 _rDefault
<<= ResultSetType::SCROLL_INSENSITIVE
;
224 case PROPERTY_ID_RESULTSETCONCURRENCY
:
225 _rDefault
<<= ResultSetConcurrency::UPDATABLE
;
227 case PROPERTY_ID_FETCHDIRECTION
:
228 _rDefault
<<= FetchDirection::FORWARD
;
230 case PROPERTY_ID_FETCHSIZE
:
231 _rDefault
<<= static_cast<sal_Int32
>(1);
233 case PROPERTY_ID_ESCAPE_PROCESSING
:
236 case PROPERTY_ID_MAXROWS
:
237 _rDefault
<<= sal_Int32( 0 );
239 case PROPERTY_ID_FILTER
:
240 case PROPERTY_ID_HAVING_CLAUSE
:
241 case PROPERTY_ID_GROUP_BY
:
242 case PROPERTY_ID_ORDER
:
243 case PROPERTY_ID_UPDATE_CATALOGNAME
:
244 case PROPERTY_ID_UPDATE_SCHEMANAME
:
245 case PROPERTY_ID_UPDATE_TABLENAME
:
246 _rDefault
<<= OUString();
251 void SAL_CALL
ORowSet::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
)
255 case PROPERTY_ID_ISMODIFIED
:
256 m_bModified
= cppu::any2bool(rValue
);
258 case PROPERTY_ID_FETCHDIRECTION
:
259 if( m_nResultSetType
== ResultSetType::FORWARD_ONLY
)
260 throw Exception("resultsettype is FORWARD_ONLY", nullptr);
263 OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
266 if ( ( nHandle
== PROPERTY_ID_ACTIVE_CONNECTION
)
267 || ( nHandle
== PROPERTY_ID_DATASOURCENAME
)
268 || ( nHandle
== PROPERTY_ID_COMMAND
)
269 || ( nHandle
== PROPERTY_ID_COMMAND_TYPE
)
270 || ( nHandle
== PROPERTY_ID_IGNORERESULT
)
271 || ( nHandle
== PROPERTY_ID_FILTER
)
272 || ( nHandle
== PROPERTY_ID_HAVING_CLAUSE
)
273 || ( nHandle
== PROPERTY_ID_GROUP_BY
)
274 || ( nHandle
== PROPERTY_ID_APPLYFILTER
)
275 || ( nHandle
== PROPERTY_ID_ORDER
)
276 || ( nHandle
== PROPERTY_ID_URL
)
277 || ( nHandle
== PROPERTY_ID_USER
)
280 m_bCommandFacetsDirty
= true;
286 case PROPERTY_ID_ACTIVE_CONNECTION
:
287 // the new connection
289 assert(m_aActiveConnection
== rValue
);
290 Reference
< XConnection
> xNewConnection(m_aActiveConnection
,UNO_QUERY
);
291 setActiveConnection(xNewConnection
, false);
294 m_bOwnConnection
= false;
295 m_bRebuildConnOnExecute
= false;
298 case PROPERTY_ID_DATASOURCENAME
:
299 if(!m_xStatement
.is())
301 Reference
< XConnection
> xNewConn
;
303 aNewConn
<<= xNewConn
;
304 setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION
, aNewConn
);
307 m_bRebuildConnOnExecute
= true;
309 case PROPERTY_ID_FETCHSIZE
:
312 m_pCache
->setFetchSize(m_nFetchSize
);
316 case PROPERTY_ID_URL
:
317 // is the connection-to-be-built determined by the url (which is the case if m_aDataSourceName is empty) ?
318 if (m_aDataSourceName
.isEmpty())
320 // are we active at the moment ?
321 if (m_xStatement
.is())
322 // yes -> the next execute needs to rebuild our connection because of this new property
323 m_bRebuildConnOnExecute
= true;
325 { // no -> drop our active connection (if we have one) as it doesn't correspond to this new property value anymore
326 Reference
< XConnection
> xNewConn
;
328 aNewConn
<<= xNewConn
;
329 setFastPropertyValue(PROPERTY_ID_ACTIVE_CONNECTION
, aNewConn
);
332 m_bOwnConnection
= true;
334 case PROPERTY_ID_TYPEMAP
:
335 m_xTypeMap
.set(m_aTypeMap
, css::uno::UNO_QUERY
);
337 case PROPERTY_ID_PROPCHANGE_NOTIFY
:
338 m_bPropChangeNotifyEnabled
= ::cppu::any2bool(rValue
);
345 void SAL_CALL
ORowSet::getFastPropertyValue(Any
& rValue
,sal_Int32 nHandle
) const
351 case PROPERTY_ID_ISMODIFIED
:
352 rValue
<<= m_bModified
;
354 case PROPERTY_ID_ISNEW
:
357 case PROPERTY_ID_PRIVILEGES
:
358 rValue
<<= m_pCache
->m_nPrivileges
;
360 case PROPERTY_ID_ACTIVE_CONNECTION
:
361 rValue
<<= m_xActiveConnection
;
363 case PROPERTY_ID_TYPEMAP
:
364 rValue
<<= m_xTypeMap
;
367 ORowSetBase::getFastPropertyValue(rValue
,nHandle
);
374 case PROPERTY_ID_ACTIVE_CONNECTION
:
375 rValue
<<= m_xActiveConnection
;
377 case PROPERTY_ID_TYPEMAP
:
378 rValue
<<= m_xTypeMap
;
380 case PROPERTY_ID_PROPCHANGE_NOTIFY
:
381 rValue
<<= m_bPropChangeNotifyEnabled
;
384 ORowSetBase::getFastPropertyValue(rValue
,nHandle
);
389 // css::XTypeProvider
390 Sequence
< Type
> SAL_CALL
ORowSet::getTypes()
392 OTypeCollection
aTypes(cppu::UnoType
<XPropertySet
>::get(),
393 cppu::UnoType
<XFastPropertySet
>::get(),
394 cppu::UnoType
<XMultiPropertySet
>::get(),
395 ::comphelper::concatSequences(ORowSet_BASE1::getTypes(),ORowSetBase::getTypes()));
396 return aTypes
.getTypes();
399 Sequence
< sal_Int8
> SAL_CALL
ORowSet::getImplementationId()
401 return css::uno::Sequence
<sal_Int8
>();
405 Any SAL_CALL
ORowSet::queryInterface( const Type
& rType
)
407 return ORowSet_BASE1::queryInterface( rType
);
410 void SAL_CALL
ORowSet::acquire() noexcept
412 ORowSet_BASE1::acquire();
415 void SAL_CALL
ORowSet::release() noexcept
417 ORowSet_BASE1::release();
421 sal_Int64 SAL_CALL
ORowSet::getSomething( const Sequence
< sal_Int8
>& rId
)
423 return comphelper::getSomethingImpl(rId
, this);
426 Sequence
< sal_Int8
> ORowSet::getUnoTunnelId()
428 static const comphelper::UnoIdInit s_Id
;
429 return s_Id
.getSeq();
433 Any SAL_CALL
ORowSet::queryAggregation( const Type
& rType
)
435 Any
aRet(ORowSetBase::queryInterface(rType
));
436 if (!aRet
.hasValue())
437 aRet
= ORowSet_BASE1::queryAggregation(rType
);
442 OUString SAL_CALL
ORowSet::getImplementationName()
444 return "com.sun.star.comp.dba.ORowSet";
447 sal_Bool SAL_CALL
ORowSet::supportsService( const OUString
& _rServiceName
)
449 return cppu::supportsService(this, _rServiceName
);
452 Sequence
< OUString
> SAL_CALL
ORowSet::getSupportedServiceNames()
454 return { SERVICE_SDBC_RESULTSET
, SERVICE_SDBC_ROWSET
, SERVICE_SDBCX_RESULTSET
,
455 SERVICE_SDB_RESULTSET
, SERVICE_SDB_ROWSET
};
459 void SAL_CALL
ORowSet::disposing()
461 OPropertyStateContainer::disposing();
463 MutexGuard
aGuard(m_aMutex
);
464 EventObject aDisposeEvent
;
465 aDisposeEvent
.Source
= static_cast< XComponent
* >(this);
466 m_aRowsetListeners
.disposeAndClear( aDisposeEvent
);
467 m_aApproveListeners
.disposeAndClear( aDisposeEvent
);
468 m_aRowsChangeListener
.disposeAndClear( aDisposeEvent
);
470 freeResources( true );
472 // remove myself as dispose listener
473 Reference
< XComponent
> xComponent(m_xActiveConnection
, UNO_QUERY
);
476 Reference
<XEventListener
> xEvt
;
477 query_aggregation(this,xEvt
);
478 xComponent
->removeEventListener(xEvt
);
481 m_aActiveConnection
= Any(); // the any contains a reference too
483 ::comphelper::disposeComponent(m_xActiveConnection
);
484 m_xActiveConnection
= nullptr;
487 ORowSetBase::disposing();
490 void ORowSet::freeResources( bool _bComplete
)
492 MutexGuard
aGuard(m_aMutex
);
495 for (auto const& clone
: m_aClones
)
497 Reference
< XComponent
> xComp(clone
.get(), UNO_QUERY
);
503 doCancelModification();
506 m_bBeforeFirst
= true;
507 m_bAfterLast
= false;
510 m_bIsInsertRow
= false;
511 m_bLastKnownRowCountFinal
= false;
512 m_nLastKnownRowCount
= 0;
517 // the columns must be disposed before the querycomposer is disposed because
518 // their owner can be the composer
519 TDataColumns().swap(m_aDataColumns
);// clear and resize capacity
520 std::vector
<bool>().swap(m_aReadOnlyDataColumns
);
522 m_xColumns
= nullptr;
524 m_pColumns
->disposing();
525 // dispose the composer to avoid that everybody knows that the querycomposer is eol
526 try { ::comphelper::disposeComponent( m_xComposer
); }
529 DBG_UNHANDLED_EXCEPTION("dbaccess");
530 m_xComposer
= nullptr;
533 // let our warnings container forget the reference to the (possibly disposed) old result set
534 m_aWarnings
.setExternalWarnings( nullptr );
538 impl_resetTables_nothrow();
540 m_xStatement
= nullptr;
541 m_xTypeMap
= nullptr;
543 if ( m_aOldRow
.is() )
544 m_aOldRow
->clearRow();
546 impl_disposeParametersContainer_nothrow();
548 m_bCommandFacetsDirty
= true;
551 void ORowSet::setActiveConnection( Reference
< XConnection
> const & _rxNewConn
, bool _bFireEvent
)
553 if (_rxNewConn
.get() == m_xActiveConnection
.get())
557 // remove the event listener for the old connection
558 Reference
< XComponent
> xComponent(m_xActiveConnection
, UNO_QUERY
);
561 Reference
<XEventListener
> xListener
;
562 query_aggregation(this, xListener
);
563 xComponent
->removeEventListener(xListener
);
566 // if we owned the connection, remember it for later disposing
568 m_xOldConnection
= m_xActiveConnection
;
570 // for firing the PropertyChangeEvent
571 sal_Int32 nHandle
= PROPERTY_ID_ACTIVE_CONNECTION
;
572 Any aOldConnection
; aOldConnection
<<= m_xActiveConnection
;
573 Any aNewConnection
; aNewConnection
<<= _rxNewConn
;
575 // set the new connection
576 m_xActiveConnection
= _rxNewConn
;
577 if (m_xActiveConnection
.is())
578 m_aActiveConnection
<<= m_xActiveConnection
;
580 m_aActiveConnection
.clear();
584 fire(&nHandle
, &aNewConnection
, &aOldConnection
, 1, false);
586 // register as event listener for the new connection
587 xComponent
.set(m_xActiveConnection
,UNO_QUERY
);
590 Reference
<XEventListener
> xListener
;
591 query_aggregation(this, xListener
);
592 xComponent
->addEventListener(xListener
);
596 // css::XEventListener
597 void SAL_CALL
ORowSet::disposing( const css::lang::EventObject
& Source
)
599 // close rowset because the connection is going to be deleted (someone told me :-)
600 Reference
<XConnection
> xCon(Source
.Source
,UNO_QUERY
);
601 if(m_xActiveConnection
== xCon
)
605 MutexGuard
aGuard( m_aMutex
);
606 Reference
< XConnection
> xXConnection
;
607 setActiveConnection( xXConnection
);
613 void SAL_CALL
ORowSet::close( )
616 MutexGuard
aGuard( m_aMutex
);
617 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
619 // additionals things to set
620 freeResources( true );
623 // comphelper::OPropertyArrayUsageHelper
624 ::cppu::IPropertyArrayHelper
* ORowSet::createArrayHelper( ) const
626 Sequence
< Property
> aProps
;
627 describeProperties(aProps
);
628 return new ::cppu::OPropertyArrayHelper(aProps
);
631 // cppu::OPropertySetHelper
632 ::cppu::IPropertyArrayHelper
& SAL_CALL
ORowSet::getInfoHelper()
634 return *::comphelper::OPropertyArrayUsageHelper
<ORowSet
>::getArrayHelper();
637 void ORowSet::updateValue(sal_Int32 columnIndex
,const ORowSetValue
& x
)
639 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
641 ::osl::MutexGuard
aGuard( *m_pMutex
);
642 checkUpdateConditions(columnIndex
);
643 checkUpdateIterator();
645 ORowSetValueVector::Vector
& rRow
= **m_aCurrentRow
;
646 ORowSetNotifier
aNotify(this, std::vector(rRow
));
647 m_pCache
->updateValue(columnIndex
,x
,rRow
,aNotify
.getChangedColumns());
648 m_bModified
= m_bModified
|| !aNotify
.getChangedColumns().empty();
649 aNotify
.firePropertyChange();
653 void SAL_CALL
ORowSet::updateNull( sal_Int32 columnIndex
)
655 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
657 ::osl::MutexGuard
aGuard( *m_pMutex
);
658 checkUpdateConditions(columnIndex
);
659 checkUpdateIterator();
661 ORowSetValueVector::Vector
& rRow
= **m_aCurrentRow
;
662 ORowSetNotifier
aNotify(this, std::vector(rRow
));
663 m_pCache
->updateNull(columnIndex
,rRow
,aNotify
.getChangedColumns());
664 m_bModified
= m_bModified
|| !aNotify
.getChangedColumns().empty();
665 aNotify
.firePropertyChange();
668 void SAL_CALL
ORowSet::updateBoolean( sal_Int32 columnIndex
, sal_Bool x
)
670 updateValue(columnIndex
, static_cast<bool>(x
));
673 void SAL_CALL
ORowSet::updateByte( sal_Int32 columnIndex
, sal_Int8 x
)
675 updateValue(columnIndex
,x
);
678 void SAL_CALL
ORowSet::updateShort( sal_Int32 columnIndex
, sal_Int16 x
)
680 updateValue(columnIndex
,x
);
683 void SAL_CALL
ORowSet::updateInt( sal_Int32 columnIndex
, sal_Int32 x
)
685 updateValue(columnIndex
,x
);
688 void SAL_CALL
ORowSet::updateLong( sal_Int32 columnIndex
, sal_Int64 x
)
690 updateValue(columnIndex
,x
);
693 void SAL_CALL
ORowSet::updateFloat( sal_Int32 columnIndex
, float x
)
695 updateValue(columnIndex
,x
);
698 void SAL_CALL
ORowSet::updateDouble( sal_Int32 columnIndex
, double x
)
700 updateValue(columnIndex
,x
);
703 void SAL_CALL
ORowSet::updateString( sal_Int32 columnIndex
, const OUString
& x
)
705 updateValue(columnIndex
,x
);
708 void SAL_CALL
ORowSet::updateBytes( sal_Int32 columnIndex
, const Sequence
< sal_Int8
>& x
)
710 updateValue(columnIndex
,x
);
713 void SAL_CALL
ORowSet::updateDate( sal_Int32 columnIndex
, const css::util::Date
& x
)
715 updateValue(columnIndex
,x
);
718 void SAL_CALL
ORowSet::updateTime( sal_Int32 columnIndex
, const css::util::Time
& x
)
720 updateValue(columnIndex
,x
);
723 void SAL_CALL
ORowSet::updateTimestamp( sal_Int32 columnIndex
, const css::util::DateTime
& x
)
725 updateValue(columnIndex
,x
);
728 void SAL_CALL
ORowSet::updateBinaryStream( sal_Int32 columnIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
730 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
731 ::osl::MutexGuard
aGuard( *m_pMutex
);
732 checkUpdateConditions(columnIndex
);
733 checkUpdateIterator();
736 Sequence
<sal_Int8
> aSeq
;
738 x
->readBytes(aSeq
,length
);
739 updateValue(columnIndex
,aSeq
);
743 void SAL_CALL
ORowSet::updateCharacterStream( sal_Int32 columnIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
745 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
746 ::osl::MutexGuard
aGuard( *m_pMutex
);
747 checkUpdateConditions(columnIndex
);
748 checkUpdateIterator();
749 ORowSetValueVector::Vector
& rRow
= **m_aCurrentRow
;
750 ORowSetNotifier
aNotify(this, std::vector(rRow
));
751 m_pCache
->updateCharacterStream(columnIndex
,x
,length
,rRow
,aNotify
.getChangedColumns());
752 m_bModified
= m_bModified
|| !aNotify
.getChangedColumns().empty();
753 aNotify
.firePropertyChange();
756 void SAL_CALL
ORowSet::updateObject( sal_Int32 columnIndex
, const Any
& x
)
758 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
759 ::osl::MutexGuard
aGuard( *m_pMutex
);
760 checkUpdateConditions(columnIndex
);
761 checkUpdateIterator();
767 Reference
<XPropertySet
> xColumn(m_pColumns
->getByIndex(columnIndex
-1),UNO_QUERY
);
768 sal_Int32 nColType
= 0;
769 xColumn
->getPropertyValue(PROPERTY_TYPE
) >>= nColType
;
774 case DataType::TIMESTAMP
:
779 if ( DataType::TIMESTAMP
== nColType
)
780 aNewValue
<<= dbtools::DBTypeConversion::toDateTime( nValue
);
781 else if ( DataType::DATE
== nColType
)
782 aNewValue
<<= dbtools::DBTypeConversion::toDate( nValue
);
784 aNewValue
<<= dbtools::DBTypeConversion::toTime( nValue
);
791 if (!::dbtools::implUpdateObject(this, columnIndex
, aNewValue
))
792 { // there is no other updateXXX call which can handle the value in x
793 ORowSetValueVector::Vector
& rRow
= **m_aCurrentRow
;
794 ORowSetNotifier
aNotify(this, std::vector(rRow
));
795 m_pCache
->updateObject(columnIndex
,aNewValue
,rRow
,aNotify
.getChangedColumns());
796 m_bModified
= m_bModified
|| !aNotify
.getChangedColumns().empty();
797 aNotify
.firePropertyChange();
801 void SAL_CALL
ORowSet::updateNumericObject( sal_Int32 columnIndex
, const Any
& x
, sal_Int32
/*scale*/ )
803 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
804 ::osl::MutexGuard
aGuard( *m_pMutex
);
805 checkUpdateConditions(columnIndex
);
806 checkUpdateIterator();
807 ORowSetValueVector::Vector
& rRow
= **m_aCurrentRow
;
808 ORowSetNotifier
aNotify(this, std::vector(rRow
));
809 m_pCache
->updateNumericObject(columnIndex
,x
,rRow
,aNotify
.getChangedColumns());
810 m_bModified
= m_bModified
|| !aNotify
.getChangedColumns().empty();
811 aNotify
.firePropertyChange();
818 bool& m_rInsertingRow
;
820 explicit ProtectFlag(bool& rInsertingRow
)
821 : m_rInsertingRow(rInsertingRow
)
825 throw std::runtime_error("recursion in insertRow");
827 m_rInsertingRow
= true;
831 m_rInsertingRow
= false;
837 void SAL_CALL
ORowSet::insertRow()
839 ProtectFlag
aFlagControl(m_bInsertingRow
);
841 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
842 // insertRow is not allowed when
843 // standing not on the insert row nor
844 // when the row isn't modified
845 // or the concurrency is read only
846 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
848 if(!m_pCache
|| !m_bNew
|| !m_bModified
|| m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
849 throwFunctionSequenceException(*this);
851 // remember old value for fire
854 ORowSetRow aOldValues
;
855 if ( !m_aCurrentRow
.isNull() )
856 aOldValues
= new ORowSetValueVector( *(*m_aCurrentRow
));
857 Sequence
<Any
> aChangedBookmarks
;
858 RowsChangeEvent
aEvt(*this,RowChangeAction::INSERT
,1,aChangedBookmarks
);
859 notifyAllListenersRowBeforeChange(aGuard
,aEvt
);
861 std::vector
< Any
> aBookmarks
;
862 bool bInserted
= m_pCache
->insertRow(aBookmarks
);
864 // make sure that our row is set to the new inserted row before clearing the insert flags in the cache
865 m_pCache
->resetInsertRow(bInserted
);
867 // notification order
869 setCurrentRow( false, true, aOldValues
, aGuard
); // we don't move here
871 // read-only flag restored
872 impl_restoreDataColumnsWriteable_throw();
875 notifyAllListenersRowChanged(aGuard
,aEvt
);
877 if ( !aBookmarks
.empty() )
879 RowsChangeEvent
aUpEvt(*this,RowChangeAction::UPDATE
,aBookmarks
.size(),comphelper::containerToSequence(aBookmarks
));
880 notifyAllListenersRowChanged(aGuard
,aUpEvt
);
885 fireProperty(PROPERTY_ID_ISMODIFIED
,false,true);
886 OSL_ENSURE( !m_bModified
, "ORowSet::insertRow: just updated, but _still_ modified?" );
890 fireProperty(PROPERTY_ID_ISNEW
,m_bNew
,bOld
);
892 // - RowCount/IsRowCountFinal
896 void SAL_CALL
ORowSet::updateRow( )
898 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
899 // not allowed when standing on insert row
900 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
901 if ( !m_pCache
|| m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
|| m_bNew
|| ((m_pCache
->m_nPrivileges
& Privilege::UPDATE
) != Privilege::UPDATE
) )
902 throwFunctionSequenceException(*this);
908 ORowSetRow aOldValues
;
909 if ( !m_aCurrentRow
.isNull() )
910 aOldValues
= new ORowSetValueVector( *(*m_aCurrentRow
) );
912 Sequence
<Any
> aChangedBookmarks
;
913 RowsChangeEvent
aEvt(*this,RowChangeAction::UPDATE
,1,aChangedBookmarks
);
914 notifyAllListenersRowBeforeChange(aGuard
,aEvt
);
916 std::vector
< Any
> aBookmarks
;
917 m_pCache
->updateRow(m_aCurrentRow
.operator ->(),aBookmarks
);
918 if ( !aBookmarks
.empty() )
919 aEvt
.Bookmarks
= comphelper::containerToSequence(aBookmarks
);
920 aEvt
.Rows
+= aBookmarks
.size();
921 m_aBookmark
= m_pCache
->getBookmark();
922 m_aCurrentRow
= m_pCache
->m_aMatrixIter
;
923 m_bIsInsertRow
= false;
924 if ( m_pCache
->m_aMatrixIter
!= m_pCache
->getEnd() && (*m_pCache
->m_aMatrixIter
).is() )
926 if ( m_pCache
->isResultSetChanged() )
928 impl_rebuild_throw(aGuard
);
932 m_aOldRow
->setRow(new ORowSetValueVector(*(*m_aCurrentRow
)));
934 // notification order
936 ORowSetBase::firePropertyChange(aOldValues
);
939 notifyAllListenersRowChanged(aGuard
,aEvt
);
943 fireProperty(PROPERTY_ID_ISMODIFIED
,false,true);
944 OSL_ENSURE( !m_bModified
, "ORowSet::updateRow: just updated, but _still_ modified?" );
946 // - RowCount/IsRowCountFinal
949 else if ( !m_bAfterLast
) // the update went wrong
951 ::dbtools::throwSQLException( DBA_RES( RID_STR_UPDATE_FAILED
), StandardSQLState::INVALID_CURSOR_POSITION
, *this );
955 void SAL_CALL
ORowSet::deleteRow( )
957 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
959 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
962 if ( m_bBeforeFirst
|| m_bAfterLast
)
963 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_BEFORE_AFTER
), StandardSQLState::INVALID_CURSOR_POSITION
, *this );
965 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_INSERT_ROW
), StandardSQLState::INVALID_CURSOR_POSITION
, *this );
966 if ( m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
967 ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY
), StandardSQLState::FUNCTION_SEQUENCE_ERROR
, *this );
968 if ( ( m_pCache
->m_nPrivileges
& Privilege::DELETE
) != Privilege::DELETE
)
969 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_DELETE_PRIVILEGE
), StandardSQLState::FUNCTION_SEQUENCE_ERROR
, *this );
971 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED
), StandardSQLState::FUNCTION_SEQUENCE_ERROR
, *this );
973 // this call position the cache indirect
974 Any
aBookmarkToDelete( m_aBookmark
);
975 positionCache( MOVE_NONE
);
976 sal_Int32 nDeletePosition
= m_pCache
->getRow();
978 notifyRowSetAndClonesRowDelete( aBookmarkToDelete
);
980 ORowSetRow aOldValues
;
981 if ( m_pCache
->m_aMatrixIter
!= m_pCache
->getEnd() && m_pCache
->m_aMatrixIter
->is() )
982 aOldValues
= new ORowSetValueVector( *(*(m_pCache
->m_aMatrixIter
)) );
984 Sequence
<Any
> aChangedBookmarks
;
985 RowsChangeEvent
aEvt(*this,RowChangeAction::DELETE
,1,aChangedBookmarks
);
986 notifyAllListenersRowBeforeChange(aGuard
,aEvt
);
988 m_pCache
->deleteRow();
989 notifyRowSetAndClonesRowDeleted( aBookmarkToDelete
, nDeletePosition
);
991 ORowSetNotifier
aNotifier( this );
992 // this will call cancelRowModification on the cache if necessary
994 // notification order
996 notifyAllListenersRowChanged(aGuard
,aEvt
);
1002 // - RowCount/IsRowCountFinal
1006 void ORowSet::implCancelRowUpdates( bool _bNotifyModified
)
1008 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1010 ::osl::MutexGuard
aGuard( *m_pMutex
);
1011 if ( m_bBeforeFirst
|| m_bAfterLast
|| rowDeleted() )
1012 return; // nothing to do so return
1015 // cancelRowUpdates is not allowed when:
1016 // - standing on the insert row
1017 // - the concurrency is read only
1018 // - the current row is deleted
1019 if ( m_bNew
|| m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
1020 throwFunctionSequenceException(*this);
1022 positionCache( MOVE_NONE
);
1024 ORowSetRow aOldValues
;
1025 if ( !m_bModified
&& _bNotifyModified
&& !m_aCurrentRow
.isNull() )
1026 aOldValues
= new ORowSetValueVector( *(*m_aCurrentRow
) );
1028 m_pCache
->cancelRowUpdates();
1030 m_aBookmark
= m_pCache
->getBookmark();
1031 m_aCurrentRow
= m_pCache
->m_aMatrixIter
;
1032 m_bIsInsertRow
= false;
1034 // notification order
1036 if( !m_bModified
&& _bNotifyModified
)
1039 ORowSetBase::firePropertyChange(aOldValues
);
1040 fireProperty(PROPERTY_ID_ISMODIFIED
,false,true);
1044 void SAL_CALL
ORowSet::cancelRowUpdates( )
1046 implCancelRowUpdates( true );
1049 void SAL_CALL
ORowSet::addRowSetListener( const Reference
< XRowSetListener
>& listener
)
1051 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1053 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
1055 m_aRowsetListeners
.addInterface(listener
);
1058 void SAL_CALL
ORowSet::removeRowSetListener( const Reference
< XRowSetListener
>& listener
)
1060 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1062 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
1064 m_aRowsetListeners
.removeInterface(listener
);
1067 void ORowSet::notifyAllListeners(::osl::ResettableMutexGuard
& _rGuard
)
1069 EventObject
aEvt(*m_pMySelf
);
1071 m_aRowsetListeners
.notifyEach( &XRowSetListener::rowSetChanged
, aEvt
);
1075 void ORowSet::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard
& _rGuard
)
1077 EventObject
aEvt(*m_pMySelf
);
1079 m_aRowsetListeners
.notifyEach( &XRowSetListener::cursorMoved
, aEvt
);
1083 void ORowSet::notifyAllListenersRowChanged(::osl::ResettableMutexGuard
& _rGuard
, const RowsChangeEvent
& aEvt
)
1086 m_aRowsetListeners
.notifyEach( &XRowSetListener::rowChanged
, static_cast<EventObject
>(aEvt
) );
1087 m_aRowsChangeListener
.notifyEach( &XRowsChangeListener::rowsChanged
, aEvt
);
1091 bool ORowSet::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard
& _rGuard
)
1093 EventObject
aEvt(*m_pMySelf
);
1094 std::vector
< Reference
< XInterface
> > aListenerSeq
= m_aApproveListeners
.getElements();
1096 bool bCheck
= std::all_of(aListenerSeq
.rbegin(), aListenerSeq
.rend(),
1097 [&aEvt
](Reference
<XInterface
>& rxItem
) {
1100 return static_cast<bool>(static_cast<XRowSetApproveListener
*>(rxItem
.get())->approveCursorMove(aEvt
));
1102 catch( RuntimeException
& )
1111 void ORowSet::notifyAllListenersRowBeforeChange(::osl::ResettableMutexGuard
& _rGuard
,const RowChangeEvent
&aEvt
)
1113 std::vector
< Reference
< XInterface
> > aListenerSeq
= m_aApproveListeners
.getElements();
1115 bool bCheck
= std::all_of(aListenerSeq
.rbegin(), aListenerSeq
.rend(),
1116 [&aEvt
](Reference
<XInterface
>& rxItem
) {
1119 return static_cast<bool>(static_cast<XRowSetApproveListener
*>(rxItem
.get())->approveRowChange(aEvt
));
1121 catch( RuntimeException
& )
1129 m_aErrors
.raiseTypedException( sdb::ErrorCondition::ROW_SET_OPERATION_VETOED
, *this, ::cppu::UnoType
< RowSetVetoException
>::get() );
1132 void ORowSet::fireRowcount()
1134 sal_Int32
nCurrentRowCount( impl_getRowCount() );
1135 bool bCurrentRowCountFinal( m_pCache
->m_bRowCountFinal
);
1137 if ( m_nLastKnownRowCount
!= nCurrentRowCount
)
1139 sal_Int32 nHandle
= PROPERTY_ID_ROWCOUNT
;
1141 aNew
<<= nCurrentRowCount
; aOld
<<= m_nLastKnownRowCount
;
1142 fire(&nHandle
,&aNew
,&aOld
,1,false);
1143 m_nLastKnownRowCount
= nCurrentRowCount
;
1145 if ( !m_bLastKnownRowCountFinal
&& ( m_bLastKnownRowCountFinal
!= bCurrentRowCountFinal
) )
1147 sal_Int32 nHandle
= PROPERTY_ID_ISROWCOUNTFINAL
;
1149 aNew
<<= bCurrentRowCountFinal
;
1150 aOld
<<= m_bLastKnownRowCountFinal
;
1151 fire(&nHandle
,&aNew
,&aOld
,1,false);
1152 m_bLastKnownRowCountFinal
= bCurrentRowCountFinal
;
1156 void SAL_CALL
ORowSet::moveToInsertRow( )
1158 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1160 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
1161 checkPositioningAllowed();
1162 if ( ( m_pCache
->m_nPrivileges
& Privilege::INSERT
) != Privilege::INSERT
)
1163 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_INSERT_PRIVILEGE
), StandardSQLState::GENERAL_ERROR
, *this );
1165 if ( !notifyAllListenersCursorBeforeMove( aGuard
) )
1168 // remember old value for fire
1169 ORowSetRow aOldValues
;
1172 positionCache( MOVE_FORWARD
);
1174 setCurrentRow( true, false, aOldValues
, aGuard
);
1177 positionCache( MOVE_NONE
);
1179 // check before because the resultset could be empty
1180 if ( !m_bBeforeFirst
1182 && m_pCache
->m_aMatrixIter
!= m_pCache
->getEnd()
1183 && m_pCache
->m_aMatrixIter
->is()
1185 aOldValues
= new ORowSetValueVector( *(*(m_pCache
->m_aMatrixIter
)) );
1187 const bool bNewState
= m_bNew
;
1188 const bool bModState
= m_bModified
;
1190 m_pCache
->moveToInsertRow();
1191 m_aCurrentRow
= m_pCache
->m_aInsertRow
;
1192 m_bIsInsertRow
= true;
1194 // set read-only flag to false
1195 impl_setDataColumnsWriteable_throw();
1197 // notification order
1199 ORowSetBase::firePropertyChange(aOldValues
);
1202 notifyAllListenersCursorMoved(aGuard
);
1205 if ( bModState
!= m_bModified
)
1206 fireProperty( PROPERTY_ID_ISMODIFIED
, m_bModified
, bModState
);
1209 if ( bNewState
!= m_bNew
)
1210 fireProperty( PROPERTY_ID_ISNEW
, m_bNew
, bNewState
);
1212 // - RowCount/IsRowCountFinal
1216 void ORowSet::impl_setDataColumnsWriteable_throw()
1218 impl_restoreDataColumnsWriteable_throw();
1219 m_aReadOnlyDataColumns
.resize(m_aDataColumns
.size(),false);
1220 std::vector
<bool, std::allocator
<bool> >::iterator aReadIter
= m_aReadOnlyDataColumns
.begin();
1221 for (auto const& dataColumn
: m_aDataColumns
)
1223 bool bReadOnly
= false;
1224 dataColumn
->getPropertyValue(PROPERTY_ISREADONLY
) >>= bReadOnly
;
1225 *aReadIter
= bReadOnly
;
1227 dataColumn
->setPropertyValue(PROPERTY_ISREADONLY
,makeAny(false));
1232 void ORowSet::impl_restoreDataColumnsWriteable_throw()
1234 assert(m_aDataColumns
.size() == m_aReadOnlyDataColumns
.size() || m_aReadOnlyDataColumns
.size() == 0 );
1235 TDataColumns::const_iterator aIter
= m_aDataColumns
.begin();
1236 for (bool readOnlyDataColumn
: m_aReadOnlyDataColumns
)
1238 (*aIter
)->setPropertyValue(PROPERTY_ISREADONLY
, makeAny(readOnlyDataColumn
) );
1241 m_aReadOnlyDataColumns
.clear();
1244 void SAL_CALL
ORowSet::moveToCurrentRow( )
1246 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1248 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
1249 checkPositioningAllowed();
1251 if ( !m_pCache
->m_bNew
&& !m_bModified
)
1252 // nothing to do if we're not on the insertion row, and not modified otherwise
1256 // this would perhaps even justify a RuntimeException...
1257 // if the current row is deleted, then no write access to this row should be possible. So,
1258 // m_bModified should be true. Also, as soon as somebody calls moveToInsertRow,
1259 // our current row should not be deleted anymore. So, we should not have survived the above
1260 // check "if ( !m_pCache->m_bNew && !m_bModified )"
1261 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED
), StandardSQLState::FUNCTION_SEQUENCE_ERROR
, *this );
1263 if ( !notifyAllListenersCursorBeforeMove( aGuard
) )
1266 positionCache( MOVE_NONE_REFRESH
);
1268 ORowSetNotifier
aNotifier( this );
1270 // notification order
1272 notifyAllListenersCursorMoved(aGuard
);
1280 sal_Bool SAL_CALL
ORowSet::wasNull( )
1282 ::osl::MutexGuard
aGuard( *m_pMutex
);
1285 return ( m_pCache
&& isInsertRow() ) ? (**m_pCache
->m_aInsertRow
)[m_nLastColumnIndex
].isNull() : ORowSetBase::wasNull();
1288 const ORowSetValue
& ORowSet::getInsertValue(sal_Int32 columnIndex
)
1292 if ( m_pCache
&& isInsertRow() )
1294 m_nLastColumnIndex
= columnIndex
;
1295 return (**m_pCache
->m_aInsertRow
)[m_nLastColumnIndex
];
1297 return getValue(columnIndex
);
1300 OUString SAL_CALL
ORowSet::getString( sal_Int32 columnIndex
)
1302 ::osl::MutexGuard
aGuard( *m_pMutex
);
1303 return getInsertValue(columnIndex
).getString();
1306 sal_Bool SAL_CALL
ORowSet::getBoolean( sal_Int32 columnIndex
)
1308 ::osl::MutexGuard
aGuard( *m_pMutex
);
1309 return getInsertValue(columnIndex
).getBool();
1312 sal_Int8 SAL_CALL
ORowSet::getByte( sal_Int32 columnIndex
)
1314 ::osl::MutexGuard
aGuard( *m_pMutex
);
1315 return getInsertValue(columnIndex
).getInt8();
1318 sal_Int16 SAL_CALL
ORowSet::getShort( sal_Int32 columnIndex
)
1320 ::osl::MutexGuard
aGuard( *m_pMutex
);
1321 return getInsertValue(columnIndex
).getInt16();
1324 sal_Int32 SAL_CALL
ORowSet::getInt( sal_Int32 columnIndex
)
1326 ::osl::MutexGuard
aGuard( *m_pMutex
);
1327 return getInsertValue(columnIndex
).getInt32();
1330 sal_Int64 SAL_CALL
ORowSet::getLong( sal_Int32 columnIndex
)
1332 ::osl::MutexGuard
aGuard( *m_pMutex
);
1333 return getInsertValue(columnIndex
).getLong();
1336 float SAL_CALL
ORowSet::getFloat( sal_Int32 columnIndex
)
1338 ::osl::MutexGuard
aGuard( *m_pMutex
);
1339 return getInsertValue(columnIndex
).getFloat();
1342 double SAL_CALL
ORowSet::getDouble( sal_Int32 columnIndex
)
1344 ::osl::MutexGuard
aGuard( *m_pMutex
);
1345 return getInsertValue(columnIndex
).getDouble();
1348 Sequence
< sal_Int8
> SAL_CALL
ORowSet::getBytes( sal_Int32 columnIndex
)
1350 ::osl::MutexGuard
aGuard( *m_pMutex
);
1351 return getInsertValue(columnIndex
).getSequence();
1354 css::util::Date SAL_CALL
ORowSet::getDate( sal_Int32 columnIndex
)
1356 ::osl::MutexGuard
aGuard( *m_pMutex
);
1357 return getInsertValue(columnIndex
).getDate();
1360 css::util::Time SAL_CALL
ORowSet::getTime( sal_Int32 columnIndex
)
1362 ::osl::MutexGuard
aGuard( *m_pMutex
);
1363 return getInsertValue(columnIndex
).getTime();
1366 css::util::DateTime SAL_CALL
ORowSet::getTimestamp( sal_Int32 columnIndex
)
1368 ::osl::MutexGuard
aGuard( *m_pMutex
);
1369 return getInsertValue(columnIndex
).getDateTime();
1372 Reference
< css::io::XInputStream
> SAL_CALL
ORowSet::getBinaryStream( sal_Int32 columnIndex
)
1374 ::osl::MutexGuard
aGuard( *m_pMutex
);
1375 if ( m_pCache
&& isInsertRow() )
1378 m_nLastColumnIndex
= columnIndex
;
1379 return new ::comphelper::SequenceInputStream((**m_pCache
->m_aInsertRow
)[m_nLastColumnIndex
].getSequence());
1382 return ORowSetBase::getBinaryStream(columnIndex
);
1385 Reference
< css::io::XInputStream
> SAL_CALL
ORowSet::getCharacterStream( sal_Int32 columnIndex
)
1387 ::osl::MutexGuard
aGuard( *m_pMutex
);
1388 if(m_pCache
&& isInsertRow() )
1391 m_nLastColumnIndex
= columnIndex
;
1392 return new ::comphelper::SequenceInputStream((**m_pCache
->m_aInsertRow
)[m_nLastColumnIndex
].getSequence());
1395 return ORowSetBase::getCharacterStream(columnIndex
);
1398 Any SAL_CALL
ORowSet::getObject( sal_Int32 columnIndex
, const Reference
< XNameAccess
>& /*typeMap*/ )
1400 ::osl::MutexGuard
aGuard( *m_pMutex
);
1401 return getInsertValue(columnIndex
).makeAny();
1404 Reference
< XRef
> SAL_CALL
ORowSet::getRef( sal_Int32
/*columnIndex*/ )
1406 return Reference
< XRef
>();
1409 Reference
< XBlob
> SAL_CALL
ORowSet::getBlob( sal_Int32 columnIndex
)
1411 if ( m_pCache
&& isInsertRow() )
1414 m_nLastColumnIndex
= columnIndex
;
1415 return new ::connectivity::BlobHelper((**m_pCache
->m_aInsertRow
)[m_nLastColumnIndex
].getSequence());
1417 return ORowSetBase::getBlob(columnIndex
);
1420 Reference
< XClob
> SAL_CALL
ORowSet::getClob( sal_Int32 columnIndex
)
1422 return Reference
< XClob
>(getInsertValue(columnIndex
).makeAny(),UNO_QUERY
);
1425 Reference
< XArray
> SAL_CALL
ORowSet::getArray( sal_Int32
/*columnIndex*/ )
1427 return Reference
< XArray
>();
1430 void SAL_CALL
ORowSet::executeWithCompletion( const Reference
< XInteractionHandler
>& _rxHandler
)
1432 if (!_rxHandler
.is())
1435 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1437 // tell everybody that we will change the result set
1440 ResettableMutexGuard
aGuard( m_aMutex
);
1444 freeResources( m_bCommandFacetsDirty
);
1446 // calc the connection to be used
1447 if (m_xActiveConnection
.is() && m_bRebuildConnOnExecute
)
1449 // there was a setProperty(ActiveConnection), but a setProperty(DataSource) _after_ that, too
1450 Reference
< XConnection
> xXConnection
;
1451 setActiveConnection( xXConnection
);
1453 calcConnection( _rxHandler
);
1454 m_bRebuildConnOnExecute
= false;
1456 Reference
< XSingleSelectQueryComposer
> xComposer
= getCurrentSettingsComposer( this, m_aContext
, nullptr );
1457 Reference
<XParametersSupplier
> xParameters(xComposer
, UNO_QUERY
);
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() < o3tl::make_unsigned(nParamCount
) )
1462 m_aParametersSet
.resize( nParamCount
,false);
1464 ::dbtools::askForParameters( xComposer
, this, m_xActiveConnection
, _rxHandler
,m_aParametersSet
);
1466 // ensure that only the allowed exceptions leave this block
1467 catch(SQLException
&)
1471 catch(RuntimeException
&)
1475 catch(Exception
const &)
1477 TOOLS_WARN_EXCEPTION("dbaccess", "ORowSet::executeWithCompletion: caught an unexpected exception type while filling in the parameters");
1480 // we're done with the parameters, now for the real execution
1482 // do the real execute
1483 execute_NoApprove_NoNewConn(aGuard
);
1486 Reference
< XIndexAccess
> SAL_CALL
ORowSet::getParameters( )
1488 ::osl::MutexGuard
aGuard( *m_pMutex
);
1489 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
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();
1496 if ( !m_pParameters
&& !m_aCommand
.isEmpty() )
1500 OUString sNotInterestedIn
;
1501 impl_initComposer_throw( sNotInterestedIn
);
1503 catch( const Exception
& )
1505 DBG_UNHANDLED_EXCEPTION("dbaccess");
1509 // our caller could change our parameters at any time
1510 m_bParametersDirty
= true;
1512 return m_pParameters
;
1515 void ORowSet::approveExecution()
1517 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
1518 EventObject
aEvt(*this);
1520 OInterfaceIteratorHelper2
aApproveIter( m_aApproveListeners
);
1521 while ( aApproveIter
.hasMoreElements() )
1523 Reference
< XRowSetApproveListener
> xListener( static_cast< XRowSetApproveListener
* >( aApproveIter
.next() ) );
1526 if ( xListener
.is() && !xListener
->approveRowSetChange( aEvt
) )
1527 throw RowSetVetoException();
1529 catch ( const DisposedException
& e
)
1531 if ( e
.Context
== xListener
)
1532 aApproveIter
.remove();
1534 catch ( const RuntimeException
& ) { throw; }
1535 catch ( const RowSetVetoException
& ) { throw; }
1536 catch ( const Exception
& )
1538 DBG_UNHANDLED_EXCEPTION("dbaccess");
1544 void SAL_CALL
ORowSet::execute( )
1546 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
1548 // tell everybody that we will change the result set
1551 ResettableMutexGuard
aGuard( m_aMutex
);
1552 freeResources( m_bCommandFacetsDirty
);
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
);
1561 calcConnection(nullptr);
1562 m_bRebuildConnOnExecute
= false;
1564 // do the real execute
1565 execute_NoApprove_NoNewConn(aGuard
);
1568 void ORowSet::setStatementResultSetType( const Reference
< XPropertySet
>& _rxStatement
, sal_Int32 _nDesiredResultSetType
, sal_Int32 _nDesiredResultSetConcurrency
)
1570 OSL_ENSURE( _rxStatement
.is(), "ORowSet::setStatementResultSetType: invalid statement - this will crash!" );
1572 sal_Int32
nResultSetType( _nDesiredResultSetType
);
1573 sal_Int32
nResultSetConcurrency( _nDesiredResultSetConcurrency
);
1575 // there *might* be a data source setting which tells use to be more defensive with those settings
1577 bool bRespectDriverRST
= false;
1579 if ( getDataSourceSetting( ::dbaccess::getDataSource( m_xActiveConnection
), "RespectDriverResultSetType", aSetting
) )
1581 OSL_VERIFY( aSetting
>>= bRespectDriverRST
);
1584 if ( bRespectDriverRST
)
1586 // try type/concurrency settings with decreasing usefulness, and rely on what the connection claims
1588 Reference
< XDatabaseMetaData
> xMeta( m_xActiveConnection
->getMetaData() );
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
}
1598 if ( m_xActiveConnection
->getMetaData()->isReadOnly() )
1599 i
= 2; // if the database is read-only we only should use read-only concurrency
1603 nResultSetType
= nCharacteristics
[i
][0];
1604 nResultSetConcurrency
= nCharacteristics
[i
][1];
1606 // don't try type/concurrency pairs which are more featured than what our caller requested
1607 if ( nResultSetType
> _nDesiredResultSetType
)
1609 if ( nResultSetConcurrency
> _nDesiredResultSetConcurrency
)
1612 if ( xMeta
.is() && xMeta
->supportsResultSetConcurrency( nResultSetType
, nResultSetConcurrency
) )
1617 _rxStatement
->setPropertyValue( PROPERTY_RESULTSETTYPE
, makeAny( nResultSetType
) );
1618 _rxStatement
->setPropertyValue( PROPERTY_RESULTSETCONCURRENCY
, makeAny( nResultSetConcurrency
) );
1621 void ORowSet::impl_ensureStatement_throw()
1623 OUString sCommandToExecute
;
1624 if(m_bCommandFacetsDirty
)
1626 impl_initComposer_throw( sCommandToExecute
);
1630 sCommandToExecute
= m_bUseEscapeProcessing
? m_xComposer
->getQueryWithSubstitution() : m_aActiveCommand
;
1635 m_xStatement
= m_xActiveConnection
->prepareStatement( sCommandToExecute
);
1636 if ( !m_xStatement
.is() )
1638 ::dbtools::throwSQLException( DBA_RES( RID_STR_INTERNAL_ERROR
), StandardSQLState::GENERAL_ERROR
, *this );
1641 Reference
< XPropertySet
> xStatementProps( m_xStatement
, UNO_QUERY_THROW
);
1642 // set the result set type and concurrency
1645 xStatementProps
->setPropertyValue( PROPERTY_USEBOOKMARKS
, makeAny( true ) );
1646 xStatementProps
->setPropertyValue( PROPERTY_MAXROWS
, makeAny( m_nMaxRows
) );
1648 setStatementResultSetType( xStatementProps
, m_nResultSetType
, m_nResultSetConcurrency
);
1650 catch ( const Exception
& )
1652 // this exception doesn't matter here because when we catch an exception
1653 // then the driver doesn't support this feature
1656 catch (SQLException
& rException
)
1658 css::sdbc::SQLException
* pLastExceptionInChain
= SQLExceptionInfo::getLastException(&rException
);
1659 assert(pLastExceptionInChain
&& "will at least be &rException");
1661 // append information about what we were actually going to execute
1662 OUString
sInfo(m_sErrorString
.replaceFirst("$command$", sCommandToExecute
));
1663 css::uno::Any aAppend
= SQLExceptionInfo::createException(SQLExceptionInfo::TYPE::SQLContext
, sInfo
, OUString(), 0);
1664 pLastExceptionInChain
->NextException
= aAppend
;
1671 Reference
< XResultSet
> ORowSet::impl_prepareAndExecute_throw()
1673 impl_ensureStatement_throw();
1675 m_aParameterValueForCache
->resize(1);
1676 Reference
< XParameters
> xParam( m_xStatement
, UNO_QUERY_THROW
);
1677 size_t nParamCount( m_pParameters
.is() ? m_pParameters
->size() : m_aPrematureParamValues
->size() );
1678 for ( size_t i
=1; i
<=nParamCount
; ++i
)
1680 ORowSetValue
& rParamValue( getParameterStorage( static_cast<sal_Int32
>(i
) ) );
1681 ::dbtools::setObjectWithInfo( xParam
, i
, rParamValue
.makeAny(), rParamValue
.getTypeKind() );
1682 m_aParameterValueForCache
->push_back(rParamValue
);
1684 m_bParametersDirty
= false;
1686 Reference
< XResultSet
> xResultSet(m_xStatement
->executeQuery());
1688 OUString aComposedUpdateTableName
;
1689 if ( !m_aUpdateTableName
.isEmpty() )
1690 aComposedUpdateTableName
= composeTableName( m_xActiveConnection
->getMetaData(), m_aUpdateCatalogName
, m_aUpdateSchemaName
, m_aUpdateTableName
, false, ::dbtools::EComposeRule::InDataManipulation
);
1692 SAL_INFO("dbaccess", "ORowSet::impl_prepareAndExecute_throw: creating cache" );
1694 std::make_shared
<ORowSetCache
>(xResultSet
, m_xComposer
.get(), m_aContext
, aComposedUpdateTableName
,
1695 m_bModified
, m_bNew
, *m_aParameterValueForCache
, m_aFilter
, m_nMaxRows
);
1696 if ( m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
1698 m_nPrivileges
= Privilege::SELECT
;
1699 m_pCache
->m_nPrivileges
= Privilege::SELECT
;
1701 m_pCache
->setFetchSize(m_nFetchSize
);
1702 m_aCurrentRow
= m_pCache
->createIterator(this);
1703 m_bIsInsertRow
= false;
1704 m_aOldRow
= m_pCache
->registerOldRow();
1709 void ORowSet::impl_initializeColumnSettings_nothrow( const Reference
< XPropertySet
>& _rxTemplateColumn
, const Reference
< XPropertySet
>& _rxRowSetColumn
)
1711 OSL_ENSURE( _rxTemplateColumn
.is() && _rxRowSetColumn
.is(),
1712 "ORowSet::impl_initializeColumnSettings_nothrow: this will crash!" );
1714 bool bHaveAnyColumnSetting
= false;
1717 Reference
< XPropertySetInfo
> xInfo( _rxTemplateColumn
->getPropertySetInfo(), UNO_SET_THROW
);
1719 // a number of properties is plain copied
1720 const OUString aPropertyNames
[] = {
1721 OUString(PROPERTY_ALIGN
), OUString(PROPERTY_RELATIVEPOSITION
), OUString(PROPERTY_WIDTH
), OUString(PROPERTY_HIDDEN
), OUString(PROPERTY_CONTROLMODEL
),
1722 OUString(PROPERTY_HELPTEXT
), OUString(PROPERTY_CONTROLDEFAULT
)
1724 for (const auto & aPropertyName
: aPropertyNames
)
1726 if ( xInfo
->hasPropertyByName( aPropertyName
) )
1728 _rxRowSetColumn
->setPropertyValue( aPropertyName
, _rxTemplateColumn
->getPropertyValue( aPropertyName
) );
1729 bHaveAnyColumnSetting
= true;
1733 // the format key is slightly more complex
1734 sal_Int32 nFormatKey
= 0;
1735 if( xInfo
->hasPropertyByName( PROPERTY_NUMBERFORMAT
) )
1737 _rxTemplateColumn
->getPropertyValue( PROPERTY_NUMBERFORMAT
) >>= nFormatKey
;
1738 bHaveAnyColumnSetting
= true;
1740 if ( !nFormatKey
&& m_xNumberFormatTypes
.is() )
1741 nFormatKey
= ::dbtools::getDefaultNumberFormat( _rxTemplateColumn
, m_xNumberFormatTypes
, SvtSysLocale().GetLanguageTag().getLocale() );
1742 _rxRowSetColumn
->setPropertyValue( PROPERTY_NUMBERFORMAT
, makeAny( nFormatKey
) );
1746 DBG_UNHANDLED_EXCEPTION("dbaccess");
1750 if ( bHaveAnyColumnSetting
)
1753 // the template column could not provide *any* setting. Okay, probably it's a parser column, which
1754 // does not offer those. However, perhaps the template column refers to a table column, which we
1755 // can use as new template column
1758 Reference
< XPropertySetInfo
> xInfo( _rxTemplateColumn
->getPropertySetInfo(), UNO_SET_THROW
);
1759 if ( !xInfo
->hasPropertyByName( PROPERTY_TABLENAME
) )
1763 OUString sTableName
;
1764 OSL_VERIFY( _rxTemplateColumn
->getPropertyValue( PROPERTY_TABLENAME
) >>= sTableName
);
1766 Reference
< XNameAccess
> xTables( impl_getTables_throw(), UNO_SET_THROW
);
1767 if ( !xTables
->hasByName( sTableName
) )
1771 Reference
< XColumnsSupplier
> xTableColSup( xTables
->getByName( sTableName
), UNO_QUERY_THROW
);
1772 Reference
< XNameAccess
> xTableCols( xTableColSup
->getColumns(), UNO_SET_THROW
);
1774 OUString sTableColumnName
;
1776 // get the "Name" or (preferred) "RealName" property of the column
1777 OUString
sNamePropertyName( PROPERTY_NAME
);
1778 if ( xInfo
->hasPropertyByName( PROPERTY_REALNAME
) )
1779 sNamePropertyName
= PROPERTY_REALNAME
;
1780 OSL_VERIFY( _rxTemplateColumn
->getPropertyValue( sNamePropertyName
) >>= sTableColumnName
);
1782 if ( !xTableCols
->hasByName( sTableColumnName
) )
1785 Reference
< XPropertySet
> xTableColumn( xTableCols
->getByName( sTableColumnName
), UNO_QUERY_THROW
);
1786 impl_initializeColumnSettings_nothrow( xTableColumn
, _rxRowSetColumn
);
1788 catch( const Exception
& )
1790 DBG_UNHANDLED_EXCEPTION("dbaccess");
1794 void ORowSet::execute_NoApprove_NoNewConn(ResettableMutexGuard
& _rClearForNotification
)
1796 // now we can dispose our old connection
1797 ::comphelper::disposeComponent(m_xOldConnection
);
1798 m_xOldConnection
= nullptr;
1800 // do we need a new statement
1801 if ( m_bCommandFacetsDirty
)
1803 m_xStatement
= nullptr;
1804 m_xComposer
= nullptr;
1806 Reference
< XResultSet
> xResultSet( impl_prepareAndExecute_throw() );
1808 // let our warnings container forget the reference to the (possibly disposed) old result set
1809 m_aWarnings
.setExternalWarnings( nullptr );
1810 // clear all current warnings
1811 m_aWarnings
.clearWarnings();
1812 // let the warnings container know about the new "external warnings"
1813 m_aWarnings
.setExternalWarnings( Reference
< XWarningsSupplier
>( xResultSet
, UNO_QUERY
) );
1816 Locale aLocale
= SvtSysLocale().GetLanguageTag().getLocale();
1818 // get the numberformatTypes
1819 OSL_ENSURE(m_xActiveConnection
.is(),"No ActiveConnection");
1820 Reference
< XNumberFormatsSupplier
> xNumberFormat
= ::dbtools::getNumberFormats(m_xActiveConnection
);
1821 if ( xNumberFormat
.is() )
1822 m_xNumberFormatTypes
.set(xNumberFormat
->getNumberFormats(),UNO_QUERY
);
1824 ::rtl::Reference
< ::connectivity::OSQLColumns
> aColumns
= new ::connectivity::OSQLColumns();
1825 std::vector
< OUString
> aNames
;
1826 OUString aDescription
;
1828 const std::map
<sal_Int32
,sal_Int32
>& rKeyColumns
= m_pCache
->getKeyColumns();
1829 if(!m_xColumns
.is())
1831 SAL_INFO("dbaccess", "ORowSet::execute_NoApprove_NoNewConn::creating columns" );
1832 // use the meta data
1833 Reference
<XResultSetMetaDataSupplier
> xMetaSup(m_xStatement
,UNO_QUERY
);
1836 Reference
<XResultSetMetaData
> xMetaData
= xMetaSup
->getMetaData();
1837 if ( xMetaData
.is() )
1839 sal_Int32 nCount
= xMetaData
->getColumnCount();
1840 m_aDataColumns
.reserve(nCount
+1);
1841 aColumns
->reserve(nCount
+1);
1842 std::map
< OUString
, int > aColumnMap
;
1843 for (sal_Int32 i
= 0 ; i
< nCount
; ++i
)
1845 // retrieve the name of the column
1846 OUString sName
= xMetaData
->getColumnName(i
+ 1);
1847 // check for duplicate entries
1848 if(aColumnMap
.find(sName
) != aColumnMap
.end())
1850 OUString
sAlias(sName
);
1851 sal_Int32 searchIndex
=1;
1852 while(aColumnMap
.find(sAlias
) != aColumnMap
.end())
1854 sAlias
= sName
+ OUString::number(searchIndex
++);
1858 rtl::Reference
<ORowSetDataColumn
> pColumn
= new ORowSetDataColumn( getMetaData(),
1862 m_xActiveConnection
->getMetaData(),
1865 [this] (sal_Int32
const column
) -> ORowSetValue
const& {
1866 return this->getInsertValue(column
);
1868 aColumnMap
.insert(std::make_pair(sName
,0));
1869 aColumns
->emplace_back(pColumn
);
1870 pColumn
->setName(sName
);
1871 aNames
.push_back(sName
);
1872 m_aDataColumns
.push_back(pColumn
.get());
1874 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY
,makeAny(rKeyColumns
.find(i
+1) != rKeyColumns
.end()));
1878 sal_Int32 nFormatKey
= 0;
1879 if(m_xNumberFormatTypes
.is())
1880 nFormatKey
= ::dbtools::getDefaultNumberFormat(pColumn
,m_xNumberFormatTypes
,aLocale
);
1883 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT
,makeAny(nFormatKey
));
1884 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION
,makeAny(sal_Int32(i
+1)));
1885 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH
,makeAny(sal_Int32(227)));
1886 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN
,makeAny(sal_Int32(0)));
1887 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN
, css::uno::Any(false));
1895 catch (SQLException
&)
1901 // create the rowset columns
1902 Reference
< XResultSetMetaData
> xMeta( getMetaData(), UNO_SET_THROW
);
1903 sal_Int32 nCount
= xMeta
->getColumnCount();
1904 m_aDataColumns
.reserve(nCount
+1);
1905 aColumns
->reserve(nCount
+1);
1906 std::set
< Reference
< XPropertySet
> > aAllColumns
;
1908 for(sal_Int32 i
=1; i
<= nCount
;++i
)
1910 OUString sName
= xMeta
->getColumnName(i
);
1911 OUString sColumnLabel
= xMeta
->getColumnLabel(i
);
1913 // retrieve the column number |i|
1914 Reference
<XPropertySet
> xColumn
;
1916 bool bReFetchName
= false;
1917 if (m_xColumns
->hasByName(sColumnLabel
))
1918 m_xColumns
->getByName(sColumnLabel
) >>= xColumn
;
1919 if (!xColumn
.is() && m_xColumns
->hasByName(sName
))
1920 m_xColumns
->getByName(sName
) >>= xColumn
;
1922 // check if column already in the list we need another
1923 if ( aAllColumns
.find( xColumn
) != aAllColumns
.end() )
1926 bReFetchName
= true;
1927 sColumnLabel
.clear();
1931 // no column found so we could look at the position i
1932 Reference
<XIndexAccess
> xIndexAccess(m_xColumns
,UNO_QUERY
);
1933 if(xIndexAccess
.is() && i
<= xIndexAccess
->getCount())
1935 xIndexAccess
->getByIndex(i
-1) >>= xColumn
;
1939 Sequence
< OUString
> aSeq
= m_xColumns
->getElementNames();
1940 if( i
<= aSeq
.getLength())
1942 m_xColumns
->getByName(aSeq
.getConstArray()[i
-1]) >>= xColumn
;
1946 if(bReFetchName
&& xColumn
.is())
1947 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sName
;
1948 aAllColumns
.insert( xColumn
);
1951 // create a RowSetDataColumn
1953 Reference
<XPropertySetInfo
> xInfo
= xColumn
.is() ? xColumn
->getPropertySetInfo() : Reference
<XPropertySetInfo
>();
1954 if(xInfo
.is() && xInfo
->hasPropertyByName(PROPERTY_DESCRIPTION
))
1955 aDescription
= comphelper::getString(xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
));
1957 OUString sParseLabel
;
1960 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sParseLabel
;
1962 rtl::Reference
<ORowSetDataColumn
> pColumn
= new ORowSetDataColumn( getMetaData(),
1966 m_xActiveConnection
->getMetaData(),
1969 [this] (sal_Int32
const column
) -> ORowSetValue
const& {
1970 return this->getInsertValue(column
);
1972 aColumns
->emplace_back(pColumn
);
1974 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ISREADONLY
,makeAny(rKeyColumns
.find(i
) != rKeyColumns
.end()));
1976 if(sColumnLabel
.isEmpty())
1979 xColumn
->getPropertyValue(PROPERTY_NAME
) >>= sColumnLabel
;
1981 sColumnLabel
= DBA_RES( RID_STR_EXPRESSION1
);
1983 pColumn
->setName(sColumnLabel
);
1984 aNames
.push_back(sColumnLabel
);
1985 m_aDataColumns
.push_back(pColumn
.get());
1988 impl_initializeColumnSettings_nothrow( xColumn
, pColumn
);
1992 // now create the columns we need
1994 m_pColumns
->assign(aColumns
,aNames
);
1997 Reference
<XDatabaseMetaData
> xMeta
= m_xActiveConnection
->getMetaData();
1998 m_pColumns
.reset( new ORowSetDataColumns(xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers(),
1999 aColumns
,*this,m_aColumnsMutex
,aNames
) );
2002 else // !m_bCommandFacetsDirty
2004 Reference
< XResultSet
> xResultSet
;
2005 if(m_bParametersDirty
)
2007 xResultSet
= impl_prepareAndExecute_throw();
2011 xResultSet
= m_xStatement
->executeQuery();
2012 m_pCache
->reset(xResultSet
);
2014 // let our warnings container forget the reference to the (possibly disposed) old result set
2015 m_aWarnings
.setExternalWarnings( nullptr );
2016 // clear all current warnings
2017 m_aWarnings
.clearWarnings();
2018 // let the warnings container know about the new "external warnings"
2019 m_aWarnings
.setExternalWarnings( Reference
< XWarningsSupplier
>( xResultSet
, UNO_QUERY
) );
2022 // notify the rowset listeners
2023 notifyAllListeners(_rClearForNotification
);
2026 // XRowSetApproveBroadcaster
2027 void SAL_CALL
ORowSet::addRowSetApproveListener( const Reference
< XRowSetApproveListener
>& listener
)
2029 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2031 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2033 m_aApproveListeners
.addInterface(listener
);
2036 void SAL_CALL
ORowSet::removeRowSetApproveListener( const Reference
< XRowSetApproveListener
>& listener
)
2038 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2040 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2042 m_aApproveListeners
.removeInterface(listener
);
2045 // XRowsChangeBroadcaster
2046 void SAL_CALL
ORowSet::addRowsChangeListener( const Reference
< XRowsChangeListener
>& listener
)
2048 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2050 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2052 m_aRowsChangeListener
.addInterface(listener
);
2055 void SAL_CALL
ORowSet::removeRowsChangeListener( const Reference
< XRowsChangeListener
>& listener
)
2057 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2059 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2061 m_aRowsChangeListener
.removeInterface(listener
);
2065 Reference
< XResultSet
> SAL_CALL
ORowSet::createResultSet( )
2067 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2069 if(m_xStatement
.is())
2071 rtl::Reference
<ORowSetClone
> pClone
= new ORowSetClone( m_aContext
, *this, m_pMutex
);
2072 m_aClones
.emplace_back(static_cast<cppu::OWeakObject
*>(pClone
.get()));
2075 return Reference
< XResultSet
>();
2078 // css::util::XCancellable
2079 void SAL_CALL
ORowSet::cancel( )
2081 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2084 // css::sdbcx::XDeleteRows
2085 Sequence
< sal_Int32
> SAL_CALL
ORowSet::deleteRows( const Sequence
< Any
>& rows
)
2087 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2089 if(!m_pCache
|| m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
2090 throwFunctionSequenceException(*this);
2092 ::osl::ResettableMutexGuard
aGuard( *m_pMutex
);
2094 Sequence
<Any
> aChangedBookmarks
;
2095 RowsChangeEvent
aEvt(*this,RowChangeAction::DELETE
,rows
.getLength(),aChangedBookmarks
);
2096 // notify the rowset listeners
2097 notifyAllListenersRowBeforeChange(aGuard
,aEvt
);
2099 Sequence
< sal_Int32
> aResults( rows
.getLength() );
2100 const Any
* row
= rows
.getConstArray();
2101 const Any
* rowEnd
= rows
.getConstArray() + rows
.getLength();
2102 sal_Int32
* result
= aResults
.getArray();
2103 for ( ; row
!= rowEnd
; ++row
, ++result
)
2106 if ( !m_pCache
->moveToBookmark( *row
) )
2108 sal_Int32 nDeletePosition
= m_pCache
->getRow();
2110 // first notify the clones so that they can save their position
2111 notifyRowSetAndClonesRowDelete( *row
);
2113 // now delete the row
2114 if ( !m_pCache
->deleteRow() )
2117 // now notify that we have deleted
2118 notifyRowSetAndClonesRowDeleted( *row
, nDeletePosition
);
2120 aEvt
.Rows
= aResults
.getLength();
2122 // we have to check if we stand on the insert row and if so we have to reset it
2123 ORowSetNotifier
aNotifier( this );
2124 // this will call cancelRowModification on the cache if necessary
2125 // notification order
2127 notifyAllListenersRowChanged(aGuard
,aEvt
);
2133 // - RowCount/IsRowCountFinal
2139 void ORowSet::notifyRowSetAndClonesRowDelete( const Any
& _rBookmark
)
2142 onDeleteRow( _rBookmark
);
2143 // notify the clones
2144 for (auto const& elem
: m_aClones
)
2146 auto pClone
= comphelper::getFromUnoTunnel
<ORowSetClone
>(elem
.get());
2148 pClone
->onDeleteRow( _rBookmark
);
2152 void ORowSet::notifyRowSetAndClonesRowDeleted( const Any
& _rBookmark
, sal_Int32 _nPos
)
2155 onDeletedRow( _rBookmark
, _nPos
);
2156 // notify the clones
2157 for (auto const& clone
: m_aClones
)
2159 auto pClone
= comphelper::getFromUnoTunnel
<ORowSetClone
>(clone
.get());
2161 pClone
->onDeletedRow( _rBookmark
, _nPos
);
2165 Reference
< XConnection
> ORowSet::calcConnection(const Reference
< XInteractionHandler
>& _rxHandler
)
2167 MutexGuard
aGuard(m_aMutex
);
2168 if (!m_xActiveConnection
.is())
2170 Reference
< XConnection
> xNewConn
;
2171 if ( !m_aDataSourceName
.isEmpty() )
2173 Reference
< XDatabaseContext
> xDatabaseContext( DatabaseContext::create(m_aContext
) );
2176 Reference
< XDataSource
> xDataSource( xDatabaseContext
->getByName( m_aDataSourceName
), UNO_QUERY_THROW
);
2178 // try connecting with the interaction handler
2179 Reference
< XCompletedConnection
> xComplConn( xDataSource
, UNO_QUERY
);
2180 if ( _rxHandler
.is() && xComplConn
.is() )
2182 xNewConn
= xComplConn
->connectWithCompletion( _rxHandler
);
2186 xNewConn
= xDataSource
->getConnection( m_aUser
, m_aPassword
);
2189 catch ( const SQLException
& )
2193 catch ( const Exception
& )
2195 Any aError
= ::cppu::getCaughtException();
2196 OUString sMessage
= ResourceManager::loadString( RID_NO_SUCH_DATA_SOURCE
,
2197 "$name$", m_aDataSourceName
, "$error$", extractExceptionMessage( m_aContext
, aError
) );
2198 ::dbtools::throwGenericSQLException( sMessage
, *this, aError
);
2201 setActiveConnection(xNewConn
);
2202 m_bOwnConnection
= true;
2204 return m_xActiveConnection
;
2207 Reference
< XNameAccess
> ORowSet::impl_getTables_throw()
2209 Reference
< XNameAccess
> xTables
;
2211 Reference
< XTablesSupplier
> xTablesAccess( m_xActiveConnection
, UNO_QUERY
);
2212 if ( xTablesAccess
.is() )
2214 xTables
.set( xTablesAccess
->getTables(), UNO_SET_THROW
);
2216 else if ( m_xTables
)
2218 xTables
= m_xTables
.get();
2222 if ( !m_xActiveConnection
.is() )
2223 throw SQLException(DBA_RES(RID_STR_CONNECTION_INVALID
),*this,SQLSTATE_GENERAL
,1000,Any() );
2228 Reference
<XDatabaseMetaData
> xMeta
= m_xActiveConnection
->getMetaData();
2229 bCase
= xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers();
2231 catch(SQLException
&)
2233 DBG_UNHANDLED_EXCEPTION("dbaccess");
2236 m_xTables
.reset(new OTableContainer(*this,m_aMutex
,m_xActiveConnection
,bCase
,nullptr,nullptr,m_nInAppend
));
2237 xTables
= m_xTables
.get();
2238 Sequence
<OUString
> aTableFilter
{ "%" };
2239 m_xTables
->construct(aTableFilter
,Sequence
< OUString
>());
2245 void ORowSet::impl_resetTables_nothrow()
2252 m_xTables
->dispose();
2254 catch( const Exception
& )
2256 DBG_UNHANDLED_EXCEPTION("dbaccess");
2262 void ORowSet::impl_initComposer_throw( OUString
& _out_rCommandToExecute
)
2264 bool bUseEscapeProcessing
= impl_buildActiveCommand_throw( );
2265 _out_rCommandToExecute
= m_aActiveCommand
;
2266 if ( !bUseEscapeProcessing
)
2269 if (m_bCommandFacetsDirty
)
2270 m_xComposer
= nullptr;
2272 Reference
< XMultiServiceFactory
> xFactory( m_xActiveConnection
, UNO_QUERY
);
2273 if ( !m_xComposer
.is() && xFactory
.is() )
2277 m_xComposer
.set( xFactory
->createInstance( SERVICE_NAME_SINGLESELECTQUERYCOMPOSER
), UNO_QUERY_THROW
);
2279 catch (const Exception
& ) { m_xComposer
= nullptr; }
2281 if ( !m_xComposer
.is() )
2282 m_xComposer
= new OSingleSelectQueryComposer( impl_getTables_throw(), m_xActiveConnection
, m_aContext
);
2284 m_xComposer
->setCommand( m_aCommand
,m_nCommandType
);
2285 m_aActiveCommand
= m_xComposer
->getQuery();
2287 m_xComposer
->setFilter( m_bApplyFilter
? m_aFilter
: OUString() );
2288 m_xComposer
->setHavingClause( m_bApplyFilter
? m_aHavingClause
: OUString() );
2290 if ( m_bIgnoreResult
)
2291 { // append a "0=1" filter
2292 // don't simply overwrite an existent filter, this would lead to problems if this existent
2293 // filter contains parameters (since a keyset may add parameters itself)
2294 m_xComposer
->setElementaryQuery( m_xComposer
->getQuery( ) );
2295 m_xComposer
->setFilter( "0 = 1" );
2298 m_xComposer
->setOrder( m_aOrder
);
2299 m_xComposer
->setGroup( m_aGroupBy
);
2301 if ( !m_xColumns
.is() )
2303 Reference
< XColumnsSupplier
> xCols( m_xComposer
, UNO_QUERY_THROW
);
2304 m_xColumns
= xCols
->getColumns();
2307 impl_initParametersContainer_nothrow();
2309 _out_rCommandToExecute
= m_xComposer
->getQueryWithSubstitution();
2311 m_bCommandFacetsDirty
= false;
2314 bool ORowSet::impl_buildActiveCommand_throw()
2316 // create the sql command
2317 // from a table name or get the command out of a query (not a view)
2318 // the last use the command as it is
2319 bool bDoEscapeProcessing
= m_bUseEscapeProcessing
;
2321 m_aActiveCommand
.clear();
2324 if ( m_aCommand
.isEmpty() )
2325 return bDoEscapeProcessing
;
2327 switch (m_nCommandType
)
2329 case CommandType::TABLE
:
2331 impl_resetTables_nothrow();
2332 if ( bDoEscapeProcessing
)
2334 Reference
< XNameAccess
> xTables( impl_getTables_throw() );
2335 if ( xTables
->hasByName(m_aCommand
) )
2340 OUString
sMessage( DBA_RES( RID_STR_TABLE_DOES_NOT_EXIST
) );
2341 throwGenericSQLException(sMessage
.replaceAll( "$table$", m_aCommand
),*this);
2346 sCommand
= "SELECT * FROM ";
2347 OUString sCatalog
, sSchema
, sTable
;
2348 ::dbtools::qualifiedNameComponents( m_xActiveConnection
->getMetaData(), m_aCommand
, sCatalog
, sSchema
, sTable
, ::dbtools::EComposeRule::InDataManipulation
);
2349 sCommand
+= ::dbtools::composeTableNameForSelect( m_xActiveConnection
, sCatalog
, sSchema
, sTable
);
2354 case CommandType::QUERY
:
2356 Reference
< XQueriesSupplier
> xQueriesAccess(m_xActiveConnection
, UNO_QUERY
);
2357 if (!xQueriesAccess
.is())
2358 throw SQLException(DBA_RES(RID_STR_NO_XQUERIESSUPPLIER
),*this,OUString(),0,Any());
2359 Reference
< css::container::XNameAccess
> xQueries(xQueriesAccess
->getQueries());
2360 if (xQueries
->hasByName(m_aCommand
))
2362 Reference
< XPropertySet
> xQuery(xQueries
->getByName(m_aCommand
),UNO_QUERY
);
2363 OSL_ENSURE(xQuery
.is(),"ORowSet::impl_buildActiveCommand_throw: Query is NULL!");
2366 xQuery
->getPropertyValue(PROPERTY_COMMAND
) >>= sCommand
;
2367 xQuery
->getPropertyValue(PROPERTY_ESCAPE_PROCESSING
) >>= bDoEscapeProcessing
;
2368 if ( bDoEscapeProcessing
!= m_bUseEscapeProcessing
)
2370 bool bOldValue
= m_bUseEscapeProcessing
;
2371 m_bUseEscapeProcessing
= bDoEscapeProcessing
;
2372 fireProperty(PROPERTY_ID_ESCAPE_PROCESSING
,bOldValue
,bDoEscapeProcessing
);
2375 OUString aCatalog
,aSchema
,aTable
;
2376 xQuery
->getPropertyValue(PROPERTY_UPDATE_CATALOGNAME
) >>= aCatalog
;
2377 xQuery
->getPropertyValue(PROPERTY_UPDATE_SCHEMANAME
) >>= aSchema
;
2378 xQuery
->getPropertyValue(PROPERTY_UPDATE_TABLENAME
) >>= aTable
;
2379 if(!aTable
.isEmpty())
2380 m_aUpdateTableName
= composeTableName( m_xActiveConnection
->getMetaData(), aCatalog
, aSchema
, aTable
, false, ::dbtools::EComposeRule::InDataManipulation
);
2385 OUString
sMessage( DBA_RES( RID_STR_QUERY_DOES_NOT_EXIST
) );
2386 throwGenericSQLException(sMessage
.replaceAll( "$table$", m_aCommand
),*this);
2392 sCommand
= m_aCommand
;
2396 m_aActiveCommand
= sCommand
;
2398 if ( m_aActiveCommand
.isEmpty() && !bDoEscapeProcessing
)
2399 ::dbtools::throwSQLException( DBA_RES( RID_STR_NO_SQL_COMMAND
), StandardSQLState::FUNCTION_SEQUENCE_ERROR
, *this );
2401 return bDoEscapeProcessing
;
2404 void ORowSet::impl_initParametersContainer_nothrow()
2406 OSL_PRECOND( !m_pParameters
.is(), "ORowSet::impl_initParametersContainer_nothrow: already initialized the parameters!" );
2408 m_pParameters
= new param::ParameterWrapperContainer( m_xComposer
);
2409 // copy the premature parameters into the final ones
2410 size_t nParamCount( std::min( m_pParameters
->size(), m_aPrematureParamValues
->size() ) );
2411 for ( size_t i
=0; i
<nParamCount
; ++i
)
2413 (*m_pParameters
)[i
] = (*m_aPrematureParamValues
)[i
];
2417 void ORowSet::impl_disposeParametersContainer_nothrow()
2419 if ( !m_pParameters
.is() )
2422 // copy the actual values to our "premature" ones, to preserve them for later use
2423 size_t nParamCount( m_pParameters
->size() );
2424 m_aPrematureParamValues
->resize( nParamCount
);
2425 for ( size_t i
=0; i
<nParamCount
; ++i
)
2427 (*m_aPrematureParamValues
)[i
] = (*m_pParameters
)[i
];
2430 m_pParameters
->dispose();
2431 m_pParameters
= nullptr;
2434 ORowSetValue
& ORowSet::getParameterStorage(sal_Int32 parameterIndex
)
2436 ::connectivity::checkDisposed( ORowSet_BASE1::rBHelper
.bDisposed
);
2437 if ( parameterIndex
< 1 )
2438 throwInvalidIndexException( *this );
2440 if ( m_aParametersSet
.size() < o3tl::make_unsigned(parameterIndex
) )
2441 m_aParametersSet
.resize( parameterIndex
,false);
2442 m_aParametersSet
[parameterIndex
- 1] = true;
2444 if ( m_pParameters
.is() )
2446 if ( m_bCommandFacetsDirty
)
2447 // need to rebuild the parameters, since some property which contributes to the
2448 // complete command, and thus the parameters, changed
2449 impl_disposeParametersContainer_nothrow();
2450 if ( m_pParameters
.is() )
2452 if ( o3tl::make_unsigned(parameterIndex
) > m_pParameters
->size() )
2453 throwInvalidIndexException( *this );
2454 return (*m_pParameters
)[ parameterIndex
- 1 ];
2458 if ( m_aPrematureParamValues
->size() < o3tl::make_unsigned(parameterIndex
) )
2459 m_aPrematureParamValues
->resize( parameterIndex
);
2460 return (*m_aPrematureParamValues
)[ parameterIndex
- 1 ];
2464 void SAL_CALL
ORowSet::setNull( sal_Int32 parameterIndex
, sal_Int32
/*sqlType*/ )
2466 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2468 getParameterStorage( parameterIndex
).setNull();
2469 m_bParametersDirty
= true;
2472 void SAL_CALL
ORowSet::setObjectNull( sal_Int32 parameterIndex
, sal_Int32 sqlType
, const OUString
& /*typeName*/ )
2474 setNull( parameterIndex
, sqlType
);
2477 void ORowSet::setParameter(sal_Int32 parameterIndex
, const ORowSetValue
& x
)
2479 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2481 getParameterStorage( parameterIndex
) = x
;
2482 m_bParametersDirty
= true;
2485 void SAL_CALL
ORowSet::setBoolean( sal_Int32 parameterIndex
, sal_Bool x
)
2487 setParameter(parameterIndex
, static_cast<bool>(x
));
2490 void SAL_CALL
ORowSet::setByte( sal_Int32 parameterIndex
, sal_Int8 x
)
2492 setParameter(parameterIndex
,x
);
2495 void SAL_CALL
ORowSet::setShort( sal_Int32 parameterIndex
, sal_Int16 x
)
2497 setParameter(parameterIndex
,x
);
2500 void SAL_CALL
ORowSet::setInt( sal_Int32 parameterIndex
, sal_Int32 x
)
2502 setParameter(parameterIndex
,x
);
2505 void SAL_CALL
ORowSet::setLong( sal_Int32 parameterIndex
, sal_Int64 x
)
2507 setParameter(parameterIndex
,x
);
2510 void SAL_CALL
ORowSet::setFloat( sal_Int32 parameterIndex
, float x
)
2512 setParameter(parameterIndex
,x
);
2515 void SAL_CALL
ORowSet::setDouble( sal_Int32 parameterIndex
, double x
)
2517 setParameter(parameterIndex
,x
);
2520 void SAL_CALL
ORowSet::setString( sal_Int32 parameterIndex
, const OUString
& x
)
2522 setParameter(parameterIndex
,x
);
2525 void SAL_CALL
ORowSet::setBytes( sal_Int32 parameterIndex
, const Sequence
< sal_Int8
>& x
)
2527 setParameter(parameterIndex
,x
);
2530 void SAL_CALL
ORowSet::setDate( sal_Int32 parameterIndex
, const css::util::Date
& x
)
2532 setParameter(parameterIndex
,x
);
2535 void SAL_CALL
ORowSet::setTime( sal_Int32 parameterIndex
, const css::util::Time
& x
)
2537 setParameter(parameterIndex
,x
);
2540 void SAL_CALL
ORowSet::setTimestamp( sal_Int32 parameterIndex
, const css::util::DateTime
& x
)
2542 setParameter(parameterIndex
,x
);
2545 void SAL_CALL
ORowSet::setBinaryStream( sal_Int32 parameterIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
2547 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2548 ORowSetValue
& rParamValue( getParameterStorage( parameterIndex
) );
2552 Sequence
<sal_Int8
> aData
;
2553 x
->readBytes(aData
, length
);
2554 rParamValue
= aData
;
2555 m_bParametersDirty
= true;
2558 catch( Exception
const & )
2560 css::uno::Any anyEx
= cppu::getCaughtException();
2561 throw SQLException("ORowSet::setBinaryStream", *this, "S1000", 0,anyEx
);
2565 void SAL_CALL
ORowSet::setCharacterStream( sal_Int32 parameterIndex
, const Reference
< css::io::XInputStream
>& x
, sal_Int32 length
)
2567 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2568 ORowSetValue
& rParamValue( getParameterStorage( parameterIndex
) );
2571 Sequence
<sal_Int8
> aData
;
2573 // the data is given as character data and the length defines the character length
2574 sal_Int32 nSize
= x
->readBytes(aData
, length
* sizeof(sal_Unicode
));
2575 if (nSize
/ sizeof(sal_Unicode
))
2576 aDataStr
= OUString(reinterpret_cast<sal_Unicode
const *>(aData
.getConstArray()), nSize
/ sizeof(sal_Unicode
));
2577 m_bParametersDirty
= true;
2578 rParamValue
= aDataStr
;
2579 rParamValue
.setTypeKind( DataType::LONGVARCHAR
);
2582 catch( Exception
const & )
2584 css::uno::Any anyEx
= cppu::getCaughtException();
2585 throw SQLException("ORowSet::setCharacterStream", *this, "S1000", 0, anyEx
);
2589 void SAL_CALL
ORowSet::setObject( sal_Int32 parameterIndex
, const Any
& x
)
2591 if ( !::dbtools::implSetObject( this, parameterIndex
, x
) )
2592 { // there is no other setXXX call which can handle the value in x
2593 throw SQLException();
2595 m_bParametersDirty
= true;
2598 void SAL_CALL
ORowSet::setObjectWithInfo( sal_Int32 parameterIndex
, const Any
& x
, sal_Int32 targetSqlType
, sal_Int32
/*scale*/ )
2600 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2601 ORowSetValue
& rParamValue( getParameterStorage( parameterIndex
) );
2602 setObject( parameterIndex
, x
);
2603 rParamValue
.setTypeKind( targetSqlType
);
2606 void SAL_CALL
ORowSet::setRef( sal_Int32
/*parameterIndex*/, const Reference
< XRef
>& /*x*/ )
2608 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this );
2611 void SAL_CALL
ORowSet::setBlob( sal_Int32
/*parameterIndex*/, const Reference
< XBlob
>& /*x*/ )
2613 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this );
2616 void SAL_CALL
ORowSet::setClob( sal_Int32
/*parameterIndex*/, const Reference
< XClob
>& /*x*/ )
2618 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this );
2621 void SAL_CALL
ORowSet::setArray( sal_Int32
/*parameterIndex*/, const Reference
< XArray
>& /*x*/ )
2623 ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this );
2626 void SAL_CALL
ORowSet::clearParameters( )
2628 ::connectivity::checkDisposed(ORowSet_BASE1::rBHelper
.bDisposed
);
2630 ::osl::MutexGuard
aGuard( m_aColumnsMutex
);
2632 size_t nParamCount( m_pParameters
.is() ? m_pParameters
->size() : m_aPrematureParamValues
->size() );
2633 for ( size_t i
=1; i
<=nParamCount
; ++i
)
2634 getParameterStorage( static_cast<sal_Int32
>(i
) ).setNull();
2635 m_aParametersSet
.clear();
2638 Any SAL_CALL
ORowSet::getWarnings( )
2640 return m_aWarnings
.getWarnings();
2643 void SAL_CALL
ORowSet::clearWarnings( )
2645 m_aWarnings
.clearWarnings();
2648 void ORowSet::doCancelModification( )
2650 if ( isModification() )
2652 // read-only flag restored
2653 impl_restoreDataColumnsWriteable_throw();
2654 m_pCache
->cancelRowModification();
2656 m_bModified
= false;
2657 m_bIsInsertRow
= false;
2660 bool ORowSet::isModification( )
2665 bool ORowSet::isModified( )
2670 bool ORowSet::isNew( )
2675 bool ORowSet::isPropertyChangeNotificationEnabled() const
2677 return m_bPropChangeNotifyEnabled
;
2680 void ORowSet::checkUpdateIterator()
2684 m_pCache
->setUpdateIterator(m_aCurrentRow
);
2685 m_aCurrentRow
= m_pCache
->m_aInsertRow
;
2686 m_bIsInsertRow
= true;
2690 void ORowSet::checkUpdateConditions(sal_Int32 columnIndex
)
2693 if ( m_nResultSetConcurrency
== ResultSetConcurrency::READ_ONLY
)
2694 ::dbtools::throwSQLException( DBA_RES( RID_STR_RESULT_IS_READONLY
), StandardSQLState::GENERAL_ERROR
, *this );
2697 ::dbtools::throwSQLException( DBA_RES( RID_STR_ROW_ALREADY_DELETED
), StandardSQLState::INVALID_CURSOR_POSITION
, *this );
2699 if ( m_aCurrentRow
.isNull() )
2700 ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_CURSOR_STATE
), StandardSQLState::INVALID_CURSOR_STATE
, *this );
2702 if ( columnIndex
<= 0 || sal_Int32((*m_aCurrentRow
)->size()) <= columnIndex
)
2703 ::dbtools::throwSQLException( DBA_RES( RID_STR_INVALID_INDEX
), StandardSQLState::INVALID_DESCRIPTOR_INDEX
, *this );
2706 void SAL_CALL
ORowSet::refreshRow( )
2709 ORowSetNotifier
aNotifier( this );
2710 // this will call cancelRowModification on the cache if necessary
2712 // notification order:
2713 if ( m_bModified
&& m_pCache
)
2714 implCancelRowUpdates( false ); // do _not_ notify the IsModify - will do this ourself below
2717 ORowSetBase::refreshRow();
2724 void ORowSet::impl_rebuild_throw(::osl::ResettableMutexGuard
& _rGuard
)
2726 Reference
< XResultSet
> xResultSet(m_xStatement
->executeQuery());
2727 m_pCache
->reset(xResultSet
);
2728 m_aWarnings
.setExternalWarnings( Reference
< XWarningsSupplier
>( xResultSet
, UNO_QUERY
) );
2729 notifyAllListeners(_rGuard
);
2732 // ***********************************************************
2734 // ***********************************************************
2736 ORowSetClone::ORowSetClone( const Reference
<XComponentContext
>& _rContext
, ORowSet
& rParent
, ::osl::Mutex
* _pMutex
)
2737 :OSubComponent(m_aMutex
, rParent
)
2738 ,ORowSetBase( _rContext
, OComponentHelper::rBHelper
, _pMutex
)
2739 ,m_pParent(&rParent
)
2740 ,m_nFetchDirection(rParent
.m_nFetchDirection
)
2741 ,m_nFetchSize(rParent
.m_nFetchSize
)
2742 ,m_bIsBookmarkable(true)
2745 m_nResultSetType
= rParent
.m_nResultSetType
;
2746 m_nResultSetConcurrency
= ResultSetConcurrency::READ_ONLY
;
2749 m_bBeforeFirst
= rParent
.m_bBeforeFirst
;
2750 m_bAfterLast
= rParent
.m_bAfterLast
;
2751 m_pCache
= rParent
.m_pCache
;
2752 m_aBookmark
= rParent
.m_aBookmark
;
2753 m_aCurrentRow
= m_pCache
->createIterator(this);
2754 m_xNumberFormatTypes
= rParent
.m_xNumberFormatTypes
;
2756 m_aOldRow
= m_pCache
->registerOldRow();
2758 ::rtl::Reference
< ::connectivity::OSQLColumns
> aColumns
= new ::connectivity::OSQLColumns();
2759 std::vector
< OUString
> aNames
;
2761 OUString aDescription
;
2762 Locale aLocale
= SvtSysLocale().GetLanguageTag().getLocale();
2764 if ( rParent
.m_pColumns
)
2766 Sequence
< OUString
> aSeq
= rParent
.m_pColumns
->getElementNames();
2767 const OUString
* pIter
= aSeq
.getConstArray();
2768 const OUString
* pEnd
= pIter
+ aSeq
.getLength();
2769 aColumns
->reserve(aSeq
.getLength()+1);
2770 for(sal_Int32 i
=1;pIter
!= pEnd
;++pIter
,++i
)
2772 Reference
<XPropertySet
> xColumn
;
2773 rParent
.m_pColumns
->getByName(*pIter
) >>= xColumn
;
2774 if(xColumn
->getPropertySetInfo()->hasPropertyByName(PROPERTY_DESCRIPTION
))
2775 aDescription
= comphelper::getString(xColumn
->getPropertyValue(PROPERTY_DESCRIPTION
));
2777 OUString sParseLabel
;
2778 xColumn
->getPropertyValue(PROPERTY_LABEL
) >>= sParseLabel
;
2779 rtl::Reference
<ORowSetColumn
> pColumn
= new ORowSetColumn( rParent
.getMetaData(),
2782 rParent
.m_xActiveConnection
->getMetaData(),
2785 [this] (sal_Int32
const column
) -> ORowSetValue
const& {
2786 return this->getValue(column
);
2788 aColumns
->emplace_back(pColumn
);
2789 pColumn
->setName(*pIter
);
2790 aNames
.push_back(*pIter
);
2791 m_aDataColumns
.push_back(pColumn
.get());
2793 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_ALIGN
,xColumn
->getPropertyValue(PROPERTY_ALIGN
));
2794 sal_Int32 nFormatKey
= 0;
2795 xColumn
->getPropertyValue(PROPERTY_NUMBERFORMAT
) >>= nFormatKey
;
2796 if(!nFormatKey
&& xColumn
.is() && m_xNumberFormatTypes
.is())
2797 nFormatKey
= ::dbtools::getDefaultNumberFormat(xColumn
,m_xNumberFormatTypes
,aLocale
);
2798 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_NUMBERFORMAT
,makeAny(nFormatKey
));
2799 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_RELATIVEPOSITION
,xColumn
->getPropertyValue(PROPERTY_RELATIVEPOSITION
));
2800 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_WIDTH
,xColumn
->getPropertyValue(PROPERTY_WIDTH
));
2801 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HIDDEN
,xColumn
->getPropertyValue(PROPERTY_HIDDEN
));
2802 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLMODEL
,xColumn
->getPropertyValue(PROPERTY_CONTROLMODEL
));
2803 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_HELPTEXT
,xColumn
->getPropertyValue(PROPERTY_HELPTEXT
));
2804 pColumn
->setFastPropertyValue_NoBroadcast(PROPERTY_ID_CONTROLDEFAULT
,xColumn
->getPropertyValue(PROPERTY_CONTROLDEFAULT
));
2808 Reference
<XDatabaseMetaData
> xMeta
= rParent
.m_xActiveConnection
->getMetaData();
2809 m_pColumns
.reset( new ORowSetDataColumns(xMeta
.is() && xMeta
->supportsMixedCaseQuotedIdentifiers(),
2810 aColumns
,*this,m_aMutex
,aNames
) );
2812 sal_Int32
const nRT
= PropertyAttribute::READONLY
| PropertyAttribute::TRANSIENT
;
2814 // sdb.RowSet Properties
2815 registerMayBeVoidProperty(PROPERTY_ACTIVE_CONNECTION
,PROPERTY_ID_ACTIVE_CONNECTION
, PropertyAttribute::MAYBEVOID
|PropertyAttribute::READONLY
, &rParent
.m_aActiveConnection
, cppu::UnoType
<XConnection
>::get());
2816 registerProperty(PROPERTY_RESULTSETCONCURRENCY
, PROPERTY_ID_RESULTSETCONCURRENCY
, PropertyAttribute::READONLY
, &m_nResultSetConcurrency
,::cppu::UnoType
<sal_Int32
>::get());
2817 registerProperty(PROPERTY_RESULTSETTYPE
, PROPERTY_ID_RESULTSETTYPE
, PropertyAttribute::READONLY
, &m_nResultSetType
, ::cppu::UnoType
<sal_Int32
>::get());
2818 registerProperty(PROPERTY_FETCHDIRECTION
, PROPERTY_ID_FETCHDIRECTION
, PropertyAttribute::TRANSIENT
, &m_nFetchDirection
, ::cppu::UnoType
<sal_Int32
>::get());
2819 registerProperty(PROPERTY_FETCHSIZE
, PROPERTY_ID_FETCHSIZE
, PropertyAttribute::TRANSIENT
, &m_nFetchSize
, ::cppu::UnoType
<sal_Int32
>::get());
2820 registerProperty(PROPERTY_ISBOOKMARKABLE
, PROPERTY_ID_ISBOOKMARKABLE
, nRT
, &m_bIsBookmarkable
, cppu::UnoType
<bool>::get());
2823 ORowSetClone::~ORowSetClone()
2827 // css::XTypeProvider
2828 Sequence
< Type
> ORowSetClone::getTypes()
2830 return ::comphelper::concatSequences(OSubComponent::getTypes(),ORowSetBase::getTypes());
2834 Any
ORowSetClone::queryInterface( const Type
& rType
)
2836 Any aRet
= ORowSetBase::queryInterface(rType
);
2837 if(!aRet
.hasValue())
2838 aRet
= OSubComponent::queryInterface(rType
);
2842 void ORowSetClone::acquire() noexcept
2844 OSubComponent::acquire();
2847 void ORowSetClone::release() noexcept
2849 OSubComponent::release();
2853 OUString
ORowSetClone::getImplementationName( )
2855 return "com.sun.star.sdb.ORowSetClone";
2858 sal_Bool
ORowSetClone::supportsService( const OUString
& _rServiceName
)
2860 return cppu::supportsService(this, _rServiceName
);
2863 Sequence
< OUString
> ORowSetClone::getSupportedServiceNames( )
2865 return { SERVICE_SDBC_RESULTSET
, SERVICE_SDB_RESULTSET
};
2869 void ORowSetClone::disposing()
2871 MutexGuard
aGuard( m_aMutex
);
2872 ORowSetBase::disposing();
2874 m_pParent
= nullptr;
2875 m_pMutex
= &m_aMutex
; // this must be done here because someone could hold a ref to us and try to do something
2876 OSubComponent::disposing();
2880 void ORowSetClone::close()
2883 MutexGuard
aGuard( m_aMutex
);
2884 if (OComponentHelper::rBHelper
.bDisposed
)
2885 throw DisposedException();
2890 // comphelper::OPropertyArrayUsageHelper
2891 ::cppu::IPropertyArrayHelper
* ORowSetClone::createArrayHelper( ) const
2893 Sequence
< Property
> aProps
;
2894 describeProperties(aProps
);
2895 return new ::cppu::OPropertyArrayHelper(aProps
);
2898 // cppu::OPropertySetHelper
2899 ::cppu::IPropertyArrayHelper
& SAL_CALL
ORowSetClone::getInfoHelper()
2901 return *::comphelper::OPropertyArrayUsageHelper
<ORowSetClone
>::getArrayHelper();
2904 Sequence
< sal_Int8
> ORowSetClone::getUnoTunnelId()
2906 static const comphelper::UnoIdInit implId
;
2907 return implId
.getSeq();
2911 sal_Int64 SAL_CALL
ORowSetClone::getSomething( const Sequence
< sal_Int8
>& rId
)
2913 return comphelper::getSomethingImpl(rId
, this);
2916 void SAL_CALL
ORowSetClone::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle
,const Any
& rValue
)
2918 if ( nHandle
== PROPERTY_ID_FETCHSIZE
)
2921 m_pParent
->setFastPropertyValue_NoBroadcast( nHandle
, rValue
);
2924 OPropertyStateContainer::setFastPropertyValue_NoBroadcast(nHandle
,rValue
);
2927 void ORowSetClone::doCancelModification( )
2931 bool ORowSetClone::isModification( )
2936 bool ORowSetClone::isModified( )
2941 bool ORowSetClone::isNew( )
2946 void SAL_CALL
ORowSetClone::execute( )
2948 throwFunctionNotSupportedSQLException( "RowSetClone::XRowSet::execute", *this );
2951 void SAL_CALL
ORowSetClone::addRowSetListener( const Reference
< XRowSetListener
>& )
2953 throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this );
2956 void SAL_CALL
ORowSetClone::removeRowSetListener( const Reference
< XRowSetListener
>& )
2958 throwFunctionNotSupportedRuntimeException( "RowSetClone::XRowSet", *this );
2963 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */