Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "RowSetBase.hxx"
21 : #include "CRowSetDataColumn.hxx"
22 : #include <connectivity/sdbcx/VCollection.hxx>
23 : #include "RowSetCache.hxx"
24 : #include "dbastrings.hrc"
25 : #include "core_resource.hrc"
26 : #include <com/sun/star/lang/DisposedException.hpp>
27 : #include <com/sun/star/beans/PropertyAttribute.hpp>
28 : #include <com/sun/star/sdbcx/CompareBookmark.hpp>
29 : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
30 : #include <com/sun/star/lang/Locale.hpp>
31 : #include <com/sun/star/util/NumberFormat.hpp>
32 : #include <comphelper/sequence.hxx>
33 : #include <comphelper/seqstream.hxx>
34 : #include <connectivity/dbexception.hxx>
35 : #include <tools/debug.hxx>
36 :
37 : using namespace dbaccess;
38 : using namespace connectivity;
39 : using namespace connectivity::sdbcx;
40 : using namespace comphelper;
41 : using namespace dbtools;
42 : using namespace ::com::sun::star::uno;
43 : using namespace ::com::sun::star::beans;
44 : using namespace ::com::sun::star::sdbc;
45 : using namespace ::com::sun::star::sdb;
46 : using namespace ::com::sun::star::sdbcx;
47 : using namespace ::com::sun::star::container;
48 : using namespace ::com::sun::star::lang;
49 : using namespace ::com::sun::star::util;
50 : using namespace ::cppu;
51 : using namespace ::osl;
52 :
53 : namespace dbaccess
54 : {
55 :
56 : // OEmptyCollection
57 0 : class OEmptyCollection : public sdbcx::OCollection
58 : {
59 : protected:
60 : virtual void impl_refresh() throw(RuntimeException) SAL_OVERRIDE;
61 : virtual connectivity::sdbcx::ObjectType createObject(const OUString& _rName) SAL_OVERRIDE;
62 : public:
63 0 : OEmptyCollection(::cppu::OWeakObject& _rParent,::osl::Mutex& _rMutex) : OCollection(_rParent, true, _rMutex, ::std::vector< OUString>()){}
64 : };
65 :
66 0 : void OEmptyCollection::impl_refresh() throw(RuntimeException)
67 : {
68 0 : }
69 :
70 0 : connectivity::sdbcx::ObjectType OEmptyCollection::createObject(const OUString& /*_rName*/)
71 : {
72 0 : return connectivity::sdbcx::ObjectType();
73 : }
74 :
75 : // ORowSetBase
76 :
77 334 : ORowSetBase::ORowSetBase( const Reference<XComponentContext>& _rContext, ::cppu::OBroadcastHelper& _rBHelper, ::osl::Mutex* _pMutex )
78 : :OPropertyStateContainer(_rBHelper)
79 : ,m_pMutex(_pMutex)
80 : ,m_pMySelf(NULL)
81 : ,m_pCache(NULL)
82 : ,m_pColumns(NULL)
83 : ,m_rBHelper(_rBHelper)
84 : ,m_pEmptyCollection( NULL )
85 : ,m_aContext( _rContext )
86 : ,m_aErrors( _rContext )
87 : ,m_nLastColumnIndex(-1)
88 : ,m_nDeletedPosition(-1)
89 : ,m_nResultSetType( ResultSetType::FORWARD_ONLY )
90 : ,m_nResultSetConcurrency( ResultSetConcurrency::READ_ONLY )
91 : ,m_bClone(false)
92 : ,m_bIgnoreResult(false)
93 : ,m_bBeforeFirst(true) // changed from sal_False
94 : ,m_bAfterLast(false)
95 334 : ,m_bIsInsertRow(false)
96 : {
97 334 : sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
98 :
99 334 : sal_Int32 nInitialRowCountValue = 0;
100 334 : sal_Bool bInitialRowCountFinalValue( sal_False );
101 334 : registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, cppu::UnoType<decltype(nInitialRowCountValue)>::get(), &nInitialRowCountValue );
102 334 : registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, cppu::UnoType<bool>::get(), &bInitialRowCountFinalValue );
103 334 : }
104 :
105 664 : ORowSetBase::~ORowSetBase()
106 : {
107 332 : if(m_pColumns)
108 : {
109 146 : TDataColumns().swap(m_aDataColumns);
110 146 : m_pColumns->acquire();
111 146 : m_pColumns->disposing();
112 146 : delete m_pColumns;
113 146 : m_pColumns = NULL;
114 : }
115 :
116 332 : if ( m_pEmptyCollection )
117 0 : delete m_pEmptyCollection;
118 :
119 332 : }
120 :
121 : // com::sun::star::lang::XTypeProvider
122 2 : Sequence< Type > ORowSetBase::getTypes() throw (RuntimeException, std::exception)
123 : {
124 2 : return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
125 : }
126 :
127 : // com::sun::star::uno::XInterface
128 5667 : Any ORowSetBase::queryInterface( const Type & rType ) throw (RuntimeException, std::exception)
129 : {
130 5667 : Any aRet = ORowSetBase_BASE::queryInterface(rType);
131 5667 : if(!aRet.hasValue())
132 3377 : aRet = OPropertyStateContainer::queryInterface(rType);
133 5667 : return aRet;
134 : }
135 :
136 690 : void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
137 : {
138 690 : if(m_pCache)
139 : {
140 386 : switch(nHandle)
141 : {
142 : case PROPERTY_ID_ROWCOUNT:
143 67 : rValue <<= impl_getRowCount();
144 67 : break;
145 : case PROPERTY_ID_ISROWCOUNTFINAL:
146 4 : rValue.setValue(&m_pCache->m_bRowCountFinal,cppu::UnoType<bool>::get());
147 4 : break;
148 : default:
149 315 : OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
150 : }
151 : }
152 : else
153 304 : OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
154 690 : }
155 :
156 : // OComponentHelper
157 333 : void SAL_CALL ORowSetBase::disposing()
158 : {
159 333 : MutexGuard aGuard(*m_pMutex);
160 :
161 333 : if ( m_pColumns )
162 : {
163 146 : TDataColumns().swap(m_aDataColumns);
164 146 : m_pColumns->disposing();
165 : }
166 333 : if ( m_pCache )
167 : {
168 116 : m_pCache->deregisterOldRow(m_aOldRow);
169 116 : m_pCache->deleteIterator(this);
170 : }
171 333 : m_pCache = NULL;
172 333 : }
173 :
174 : // comphelper::OPropertyArrayUsageHelper
175 0 : ::cppu::IPropertyArrayHelper* ORowSetBase::createArrayHelper( ) const
176 : {
177 0 : Sequence< Property > aProps;
178 0 : describeProperties(aProps);
179 0 : return new ::cppu::OPropertyArrayHelper(aProps);
180 : }
181 :
182 : // cppu::OPropertySetHelper
183 0 : ::cppu::IPropertyArrayHelper& SAL_CALL ORowSetBase::getInfoHelper()
184 : {
185 0 : return *getArrayHelper();
186 : }
187 :
188 : // XRow
189 523 : sal_Bool SAL_CALL ORowSetBase::wasNull( ) throw(SQLException, RuntimeException, std::exception)
190 : {
191 523 : ::osl::MutexGuard aGuard( *m_pMutex );
192 523 : checkCache();
193 523 : return impl_wasNull();
194 : }
195 :
196 523 : bool ORowSetBase::impl_wasNull()
197 : {
198 523 : return !((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is()) || ((*m_aCurrentRow)->get())[m_nLastColumnIndex].isNull();
199 : }
200 :
201 9069 : const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
202 : {
203 9069 : checkCache();
204 9069 : return impl_getValue(columnIndex);
205 : }
206 :
207 9069 : const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
208 : {
209 9069 : if ( m_bBeforeFirst || m_bAfterLast )
210 : {
211 : SAL_WARN("dbaccess", "ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
212 4 : ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
213 : }
214 :
215 9067 : if ( impl_rowDeleted() )
216 : {
217 0 : return m_aEmptyValue;
218 : }
219 :
220 9067 : bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
221 9067 : if ( !bValidCurrentRow )
222 : {
223 : // currentrow is null when the clone moves the window
224 952 : positionCache( MOVE_NONE );
225 952 : m_aCurrentRow = m_pCache->m_aMatrixIter;
226 952 : m_bIsInsertRow = false;
227 : OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");
228 :
229 952 : bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
230 : }
231 :
232 9067 : if ( bValidCurrentRow )
233 : {
234 : #if OSL_DEBUG_LEVEL > 0
235 : ORowSetMatrix::iterator aCacheEnd;
236 : ORowSetMatrix::iterator aCurrentRow;
237 : aCacheEnd = m_pCache->getEnd();
238 : aCurrentRow = m_aCurrentRow;
239 : ORowSetCacheMap::iterator aCacheIter = m_aCurrentRow.getIter();
240 : ORowSetCacheIterator_Helper aHelper = aCacheIter->second;
241 : ORowSetMatrix::iterator k = aHelper.aIterator;
242 : for (; k != m_pCache->getEnd(); ++k)
243 : {
244 : ORowSetValueVector* pTemp = k->get();
245 : OSL_ENSURE( pTemp != reinterpret_cast<void*>(0xfeeefeee),"HALT!" );
246 : }
247 : #endif
248 : OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow < m_pCache->getEnd() && aCacheIter != m_pCache->m_aCacheIterators.end(),"Invalid iterator set for currentrow!");
249 : #if OSL_DEBUG_LEVEL > 0
250 : ORowSetRow rRow = (*m_aCurrentRow);
251 : OSL_ENSURE(rRow.is() && static_cast<sal_uInt16>(columnIndex) < (rRow->get()).size(),"Invalid size of vector!");
252 : #endif
253 9067 : return ((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex];
254 : }
255 :
256 : // we should normally never reach this
257 0 : return m_aEmptyValue;
258 : }
259 :
260 126 : OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
261 : {
262 126 : ::osl::MutexGuard aGuard( *m_pMutex );
263 126 : return getValue(columnIndex);
264 : }
265 :
266 0 : sal_Bool SAL_CALL ORowSetBase::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
267 : {
268 0 : ::osl::MutexGuard aGuard( *m_pMutex );
269 0 : return getValue(columnIndex);
270 : }
271 :
272 0 : sal_Int8 SAL_CALL ORowSetBase::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
273 : {
274 0 : ::osl::MutexGuard aGuard( *m_pMutex );
275 0 : return getValue(columnIndex);
276 : }
277 :
278 0 : sal_Int16 SAL_CALL ORowSetBase::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
279 : {
280 0 : ::osl::MutexGuard aGuard( *m_pMutex );
281 0 : return getValue(columnIndex);
282 : }
283 :
284 1216 : sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
285 : {
286 1216 : ::osl::MutexGuard aGuard( *m_pMutex );
287 1216 : return getValue(columnIndex);
288 : }
289 :
290 0 : sal_Int64 SAL_CALL ORowSetBase::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
291 : {
292 0 : ::osl::MutexGuard aGuard( *m_pMutex );
293 0 : return getValue(columnIndex);
294 : }
295 :
296 0 : float SAL_CALL ORowSetBase::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
297 : {
298 0 : ::osl::MutexGuard aGuard( *m_pMutex );
299 0 : return getValue(columnIndex);
300 : }
301 :
302 0 : double SAL_CALL ORowSetBase::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
303 : {
304 0 : ::osl::MutexGuard aGuard( *m_pMutex );
305 0 : return getValue(columnIndex);
306 : }
307 :
308 0 : Sequence< sal_Int8 > SAL_CALL ORowSetBase::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
309 : {
310 0 : ::osl::MutexGuard aGuard( *m_pMutex );
311 0 : return getValue(columnIndex);
312 : }
313 :
314 0 : ::com::sun::star::util::Date SAL_CALL ORowSetBase::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
315 : {
316 0 : ::osl::MutexGuard aGuard( *m_pMutex );
317 0 : return getValue(columnIndex);
318 : }
319 :
320 0 : ::com::sun::star::util::Time SAL_CALL ORowSetBase::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
321 : {
322 0 : ::osl::MutexGuard aGuard( *m_pMutex );
323 0 : return getValue(columnIndex);
324 : }
325 :
326 0 : ::com::sun::star::util::DateTime SAL_CALL ORowSetBase::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
327 : {
328 0 : ::osl::MutexGuard aGuard( *m_pMutex );
329 0 : return getValue(columnIndex);
330 : }
331 :
332 0 : Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
333 : {
334 0 : ::osl::MutexGuard aGuard( *m_pMutex );
335 0 : checkCache();
336 :
337 0 : if ( m_bBeforeFirst || m_bAfterLast )
338 : {
339 : SAL_WARN("dbaccess", "ORowSetBase::getBinaryStream: Illegal call here (we're before first or after last)!");
340 0 : ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
341 : }
342 :
343 0 : if ( impl_rowDeleted() )
344 : {
345 0 : return NULL;
346 : }
347 :
348 0 : bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
349 0 : if ( !bValidCurrentRow )
350 : {
351 0 : positionCache( MOVE_NONE );
352 0 : m_aCurrentRow = m_pCache->m_aMatrixIter;
353 0 : m_bIsInsertRow = false;
354 : OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getBinaryStream: we don't stand on a valid row! Row is null.");
355 :
356 0 : bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
357 : }
358 :
359 0 : if ( bValidCurrentRow )
360 0 : return new ::comphelper::SequenceInputStream(((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex].getSequence());
361 :
362 : // we should normally never reach this
363 0 : return Reference< ::com::sun::star::io::XInputStream >();
364 : }
365 :
366 0 : Reference< ::com::sun::star::io::XInputStream > SAL_CALL ORowSetBase::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
367 : {
368 0 : return getBinaryStream(columnIndex);
369 : }
370 :
371 0 : Any SAL_CALL ORowSetBase::getObject( sal_Int32 columnIndex, const Reference< XNameAccess >& /*typeMap*/ ) throw(SQLException, RuntimeException, std::exception)
372 : {
373 0 : ::osl::MutexGuard aGuard( *m_pMutex );
374 0 : checkCache();
375 :
376 0 : return getValue(columnIndex).makeAny();
377 : }
378 :
379 0 : Reference< XRef > SAL_CALL ORowSetBase::getRef( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException, std::exception)
380 : {
381 0 : ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getRef", *m_pMySelf );
382 0 : return NULL;
383 : }
384 :
385 0 : Reference< XBlob > SAL_CALL ORowSetBase::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
386 : {
387 0 : return Reference< XBlob >(getValue(columnIndex).makeAny(),UNO_QUERY);
388 : }
389 :
390 0 : Reference< XClob > SAL_CALL ORowSetBase::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
391 : {
392 0 : return Reference< XClob >(getValue(columnIndex).makeAny(),UNO_QUERY);
393 : }
394 :
395 0 : Reference< XArray > SAL_CALL ORowSetBase::getArray( sal_Int32 /*columnIndex*/ ) throw(SQLException, RuntimeException, std::exception)
396 : {
397 0 : ::dbtools::throwFeatureNotImplementedSQLException( "XRow::getArray", *m_pMySelf );
398 0 : return NULL;
399 : }
400 :
401 : // ::com::sun::star::sdbcx::XRowLocate
402 33 : Any SAL_CALL ORowSetBase::getBookmark( ) throw(SQLException, RuntimeException, std::exception)
403 : {
404 : SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
405 33 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
406 33 : ::osl::MutexGuard aGuard( *m_pMutex );
407 33 : checkCache();
408 :
409 33 : if ( m_bBeforeFirst || m_bAfterLast )
410 0 : ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
411 :
412 33 : if ( impl_rowDeleted() )
413 2 : ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_BOOKMARK_DELETED ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
414 :
415 : OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::getBookmark: bookmark has no value!" );
416 33 : return m_aBookmark;
417 : }
418 :
419 6 : sal_Bool SAL_CALL ORowSetBase::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException, std::exception)
420 : {
421 : SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) Clone = " << m_bClone);
422 : OSL_ENSURE(bookmark.hasValue(),"ORowSetBase::moveToBookmark bookmark has no value!");
423 6 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
424 :
425 6 : if(!bookmark.hasValue() || m_nResultSetType == ResultSetType::FORWARD_ONLY)
426 : {
427 0 : if(bookmark.hasValue())
428 : SAL_WARN("dbaccess", "MoveToBookmark is not possible when we are only forward");
429 : else
430 : SAL_WARN("dbaccess", "Bookmark is not valid");
431 0 : throwFunctionSequenceException(*m_pMySelf);
432 : }
433 :
434 6 : checkCache();
435 :
436 6 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
437 6 : if ( bRet )
438 : {
439 : // check if we are inserting a row
440 6 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
441 :
442 6 : ORowSetNotifier aNotifier( this );
443 : // this will call cancelRowModification on the cache if necessary
444 :
445 12 : ORowSetRow aOldValues = getOldRow(bWasNew);
446 :
447 6 : bRet = m_pCache->moveToBookmark(bookmark);
448 6 : doCancelModification( );
449 6 : if(bRet)
450 : {
451 : // notification order
452 : // - column values
453 : // - cursorMoved
454 6 : setCurrentRow( true, true, aOldValues, aGuard );
455 : }
456 : else
457 : {
458 0 : movementFailed();
459 : }
460 :
461 : // - IsModified
462 : // - IsNew
463 12 : aNotifier.fire( );
464 : }
465 : SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
466 6 : return bRet;
467 : }
468 :
469 2 : sal_Bool SAL_CALL ORowSetBase::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException, std::exception)
470 : {
471 : SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") Clone = " << m_bClone);
472 2 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
473 :
474 2 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
475 :
476 2 : checkPositioningAllowed();
477 :
478 2 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
479 2 : if ( bRet )
480 : {
481 : // check if we are inserting a row
482 2 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
483 :
484 2 : ORowSetNotifier aNotifier( this );
485 : // this will call cancelRowModification on the cache if necessary
486 :
487 4 : ORowSetRow aOldValues = getOldRow(bWasNew);
488 :
489 2 : bRet = m_pCache->moveRelativeToBookmark(bookmark,rows);
490 2 : doCancelModification( );
491 2 : if(bRet)
492 : {
493 : // notification order
494 : // - column values
495 : // - cursorMoved
496 2 : setCurrentRow( true, true, aOldValues, aGuard );
497 : }
498 : else
499 0 : movementFailed();
500 :
501 : // - IsModified
502 : // - IsNew
503 2 : aNotifier.fire( );
504 :
505 : // RowCount/IsRowCountFinal
506 4 : fireRowcount();
507 : }
508 : SAL_INFO("dbaccess", "ORowSetBase::moveRelativeToBookmark(Any," << rows << ") = " << bRet << " Clone = " << m_bClone);
509 2 : return bRet;
510 : }
511 :
512 51 : sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException, std::exception)
513 : {
514 51 : ::osl::MutexGuard aGuard( *m_pMutex );
515 51 : checkCache();
516 51 : return m_pCache->compareBookmarks(_first,_second);
517 : }
518 :
519 1 : sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( ) throw(SQLException, RuntimeException, std::exception)
520 : {
521 1 : ::osl::MutexGuard aGuard( *m_pMutex );
522 1 : checkCache();
523 1 : return m_pCache->hasOrderedBookmarks();
524 : }
525 :
526 2 : sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException, std::exception)
527 : {
528 2 : ::osl::MutexGuard aGuard( *m_pMutex );
529 2 : checkCache();
530 2 : return m_pCache->hashBookmark(bookmark);
531 : }
532 :
533 : // XResultSetMetaDataSupplier
534 704 : Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( ) throw(SQLException, RuntimeException, std::exception)
535 : {
536 704 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
537 :
538 704 : Reference< XResultSetMetaData > xMeta;
539 704 : if(m_pCache)
540 704 : xMeta = m_pCache->getMetaData();
541 :
542 704 : return xMeta;
543 : }
544 :
545 : // XColumnLocate
546 1 : sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName ) throw(SQLException, RuntimeException, std::exception)
547 : {
548 1 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
549 :
550 1 : ::osl::MutexGuard aGuard( m_aColumnsMutex );
551 : // it is possible to save some time here when we remember the names - position relation in a map
552 1 : return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
553 : }
554 :
555 : // ::com::sun::star::sdbcx::XColumnsSupplier
556 1008 : Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( ) throw(RuntimeException, std::exception)
557 : {
558 1008 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
559 :
560 1008 : ::osl::MutexGuard aGuard( m_aColumnsMutex );
561 1008 : if(!m_pColumns)
562 : {
563 0 : if (!m_pEmptyCollection)
564 0 : m_pEmptyCollection = new OEmptyCollection(*m_pMySelf,m_aColumnsMutex);
565 0 : return m_pEmptyCollection;
566 : }
567 :
568 1008 : return m_pColumns;
569 : }
570 :
571 : // XResultSet
572 1480 : sal_Bool SAL_CALL ORowSetBase::next( ) throw(SQLException, RuntimeException, std::exception)
573 : {
574 : SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
575 1480 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
576 1480 : checkCache();
577 :
578 1480 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
579 1480 : if ( bRet )
580 : {
581 : // check if we are inserting a row
582 1480 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
583 :
584 1480 : ORowSetNotifier aNotifier( this );
585 : // this will call cancelRowModification on the cache if necessary
586 :
587 2960 : ORowSetRow aOldValues = getOldRow(bWasNew);
588 :
589 1480 : positionCache( MOVE_FORWARD );
590 1480 : bool bAfterLast = m_pCache->isAfterLast();
591 1480 : bRet = m_pCache->next();
592 1480 : doCancelModification( );
593 :
594 : // if we were afterLast before next() then we still are,
595 : // i.e. bAfterLast implies m_pCache->isAfterLast()
596 : if (bAfterLast)
597 : assert(m_pCache->isAfterLast());
598 : // so the only way bAfterLast != m_pCache->isAfterLast()
599 : // would be that we just arrived there,
600 1480 : if (bAfterLast != m_pCache->isAfterLast())
601 : {
602 : assert(!bAfterLast);
603 : assert(m_pCache->isAfterLast());
604 : }
605 : // in which case we *did* move the cursor
606 1480 : if ( bRet || bAfterLast != m_pCache->isAfterLast() )
607 : {
608 : // notification order
609 : // - column values
610 : // - cursorMoved
611 1477 : setCurrentRow( true, true, aOldValues, aGuard );
612 : OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
613 : }
614 : else
615 : {
616 : // moved after the last row
617 3 : movementFailed();
618 : OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
619 : }
620 :
621 : // - IsModified
622 : // - IsNew
623 1480 : aNotifier.fire();
624 :
625 : // - RowCount/IsRowCountFinal
626 2960 : fireRowcount();
627 : }
628 : SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
629 1480 : return bRet;
630 : }
631 :
632 6706 : sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( ) throw(SQLException, RuntimeException, std::exception)
633 : {
634 6706 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
635 6706 : ::osl::MutexGuard aGuard( *m_pMutex );
636 6706 : checkCache();
637 :
638 : SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
639 :
640 6706 : return m_bBeforeFirst;
641 : }
642 :
643 6716 : sal_Bool SAL_CALL ORowSetBase::isAfterLast( ) throw(SQLException, RuntimeException, std::exception)
644 : {
645 6716 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
646 6716 : ::osl::MutexGuard aGuard( *m_pMutex );
647 6716 : checkCache();
648 : SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
649 :
650 6716 : return m_bAfterLast;
651 : }
652 :
653 45 : bool ORowSetBase::isOnFirst()
654 : {
655 45 : return isFirst();
656 : }
657 :
658 55 : sal_Bool SAL_CALL ORowSetBase::isFirst( ) throw(SQLException, RuntimeException, std::exception)
659 : {
660 : SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
661 :
662 55 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
663 55 : ::osl::MutexGuard aGuard( *m_pMutex );
664 55 : checkCache();
665 :
666 55 : if ( m_bBeforeFirst || m_bAfterLast )
667 29 : return sal_False;
668 :
669 26 : if ( impl_rowDeleted() )
670 1 : return ( m_nDeletedPosition == 1 );
671 :
672 25 : positionCache( MOVE_NONE );
673 25 : bool bIsFirst = m_pCache->isFirst();
674 :
675 : SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
676 25 : return bIsFirst;
677 : }
678 :
679 10 : bool ORowSetBase::isOnLast()
680 : {
681 10 : return isLast();
682 : }
683 :
684 15 : sal_Bool SAL_CALL ORowSetBase::isLast( ) throw(SQLException, RuntimeException, std::exception)
685 : {
686 : SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
687 15 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
688 15 : ::osl::MutexGuard aGuard( *m_pMutex );
689 15 : checkCache();
690 :
691 15 : if ( m_bBeforeFirst || m_bAfterLast )
692 5 : return sal_False;
693 :
694 10 : if ( impl_rowDeleted() )
695 : {
696 1 : if ( !m_pCache->m_bRowCountFinal )
697 0 : return sal_False;
698 : else
699 1 : return ( m_nDeletedPosition == impl_getRowCount() );
700 : }
701 :
702 9 : positionCache( MOVE_NONE );
703 9 : bool bIsLast = m_pCache->isLast();
704 :
705 : SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
706 9 : return bIsLast;
707 : }
708 :
709 27 : void SAL_CALL ORowSetBase::beforeFirst( ) throw(SQLException, RuntimeException, std::exception)
710 : {
711 : SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
712 27 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
713 27 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
714 :
715 27 : checkPositioningAllowed();
716 :
717 : // check if we are inserting a row
718 27 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
719 :
720 27 : if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
721 : {
722 9 : ORowSetNotifier aNotifier( this );
723 : // this will call cancelRowModification on the cache if necessary
724 :
725 9 : if ( !m_bBeforeFirst )
726 : {
727 9 : ORowSetRow aOldValues = getOldRow(bWasNew);
728 9 : m_pCache->beforeFirst();
729 9 : doCancelModification( );
730 :
731 : // notification order
732 : // - column values
733 : // - cursorMoved
734 9 : setCurrentRow( true, true, aOldValues, aGuard );
735 :
736 : // - IsModified
737 : // - Isnew
738 9 : aNotifier.fire();
739 :
740 : // - RowCount/IsRowCountFinal
741 9 : fireRowcount();
742 : }
743 :
744 : // to be done _after_ the notifications!
745 9 : m_aOldRow->clearRow();
746 : }
747 27 : SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
748 27 : }
749 :
750 6 : void SAL_CALL ORowSetBase::afterLast( ) throw(SQLException, RuntimeException, std::exception)
751 : {
752 : SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
753 6 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
754 :
755 6 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
756 6 : checkPositioningAllowed();
757 :
758 6 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
759 :
760 6 : if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
761 : {
762 : // check if we are inserting a row
763 6 : ORowSetNotifier aNotifier( this );
764 : // this will call cancelRowModification on the cache if necessary
765 :
766 6 : if(!m_bAfterLast)
767 : {
768 6 : ORowSetRow aOldValues = getOldRow(bWasNew);
769 :
770 6 : m_pCache->afterLast();
771 6 : doCancelModification( );
772 :
773 : // notification order
774 : // - column values
775 : // - cursorMoved
776 6 : setCurrentRow( true, true, aOldValues, aGuard );
777 :
778 : // - IsModified
779 : // - Isnew
780 6 : aNotifier.fire();
781 :
782 : // - RowCount/IsRowCountFinal
783 6 : fireRowcount();
784 6 : }
785 : }
786 6 : SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
787 6 : }
788 :
789 61 : bool SAL_CALL ORowSetBase::move( ::std::mem_fun_t<bool,ORowSetBase>& _aCheckFunctor,
790 : ::std::mem_fun_t<bool,ORowSetCache>& _aMovementFunctor)
791 : {
792 : SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
793 61 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
794 61 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
795 61 : checkPositioningAllowed();
796 :
797 60 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
798 60 : if( bRet )
799 : {
800 : // check if we are inserting a row
801 60 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
802 :
803 60 : ORowSetNotifier aNotifier( this );
804 : // this will call cancelRowModification on the cache if necessary
805 :
806 120 : ORowSetRow aOldValues = getOldRow(bWasNew);
807 :
808 60 : bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
809 :
810 60 : bRet = _aMovementFunctor(m_pCache);
811 60 : doCancelModification( );
812 :
813 60 : if ( bRet )
814 : {
815 : // notification order
816 : // - column values
817 : // - cursorMoved
818 57 : setCurrentRow( bMoved, true, aOldValues, aGuard );
819 : }
820 : else
821 : { // first goes wrong so there is no row
822 3 : movementFailed();
823 : }
824 :
825 : // - IsModified
826 : // - IsNew
827 60 : aNotifier.fire();
828 :
829 : // - RowCount/IsRowCountFinal
830 120 : fireRowcount();
831 : }
832 : SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
833 61 : return bRet;
834 : }
835 :
836 50 : sal_Bool SAL_CALL ORowSetBase::first( ) throw(SQLException, RuntimeException, std::exception)
837 : {
838 : SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
839 50 : ::std::mem_fun_t<bool,ORowSetBase> ioF_tmp(&ORowSetBase::isOnFirst);
840 50 : ::std::mem_fun_t<bool,ORowSetCache> F_tmp(&ORowSetCache::first);
841 50 : return move(ioF_tmp,F_tmp);
842 : }
843 :
844 11 : sal_Bool SAL_CALL ORowSetBase::last( ) throw(SQLException, RuntimeException, std::exception)
845 : {
846 : SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
847 11 : ::std::mem_fun_t<bool,ORowSetBase> ioL_tmp(&ORowSetBase::isOnLast);
848 11 : ::std::mem_fun_t<bool,ORowSetCache> L_tmp(&ORowSetCache::last);
849 11 : return move(ioL_tmp,L_tmp);
850 : }
851 :
852 3912 : sal_Int32 SAL_CALL ORowSetBase::getRow( ) throw(SQLException, RuntimeException, std::exception)
853 : {
854 : SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
855 3912 : ::osl::MutexGuard aGuard( *m_pMutex );
856 :
857 3912 : checkCache();
858 3912 : return impl_getRow();
859 : }
860 :
861 3912 : sal_Int32 ORowSetBase::impl_getRow()
862 : {
863 3912 : sal_Int32 nPos = 0;
864 3912 : if ( m_bBeforeFirst )
865 2 : nPos = 0;
866 3910 : else if ( m_bAfterLast )
867 0 : nPos = impl_getRowCount() + 1;
868 3910 : else if ( impl_rowDeleted() )
869 9 : nPos = m_nDeletedPosition;
870 3901 : else if ( !m_bClone && m_pCache->m_bNew )
871 0 : nPos = 0;
872 : else
873 : {
874 3901 : positionCache( MOVE_NONE );
875 3901 : nPos = m_pCache->getRow();
876 : }
877 : SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
878 3912 : return nPos;
879 : }
880 :
881 335 : sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row ) throw(SQLException, RuntimeException, std::exception)
882 : {
883 : SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
884 335 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
885 335 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
886 335 : checkPositioningAllowed();
887 :
888 335 : bool bRet = ( row > 0 )
889 335 : && notifyAllListenersCursorBeforeMove( aGuard );
890 335 : if ( bRet )
891 : {
892 : // check if we are inserting a row
893 335 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
894 :
895 335 : ORowSetNotifier aNotifier( this );
896 : // this will call cancelRowModification on the cache if necessary
897 :
898 670 : ORowSetRow aOldValues = getOldRow(bWasNew);
899 :
900 335 : bRet = m_pCache->absolute(row);
901 335 : doCancelModification( );
902 :
903 335 : if(bRet)
904 : {
905 : // notification order
906 : // - column values
907 : // - cursorMoved
908 335 : setCurrentRow( true, true, aOldValues, aGuard );
909 : }
910 : else
911 : { // absolute movement goes wrong we stand left or right side of the rows
912 0 : movementFailed();
913 : }
914 :
915 : // - IsModified
916 : // - IsNew
917 335 : aNotifier.fire();
918 :
919 : // - RowCount/IsRowCountFinal
920 670 : fireRowcount();
921 : }
922 : SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
923 335 : return bRet;
924 : }
925 :
926 16 : sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows ) throw(SQLException, RuntimeException, std::exception)
927 : {
928 : SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
929 16 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
930 :
931 16 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
932 :
933 16 : if(!rows)
934 0 : return sal_True; // in this case do nothing
935 :
936 16 : checkPositioningAllowed();
937 :
938 : bool bRet =
939 16 : ( ( !m_bAfterLast || rows <= 0 )
940 16 : && ( !m_bBeforeFirst || rows >= 0 )
941 32 : && notifyAllListenersCursorBeforeMove( aGuard )
942 16 : );
943 :
944 16 : if ( bRet )
945 : {
946 : // check if we are inserting a row
947 16 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
948 :
949 16 : ORowSetNotifier aNotifier( this );
950 : // this will call cancelRowModification on the cache if necessary
951 :
952 32 : ORowSetRow aOldValues = getOldRow(bWasNew);
953 :
954 16 : positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD );
955 16 : bRet = m_pCache->relative(rows);
956 16 : doCancelModification( );
957 :
958 16 : if(bRet)
959 : {
960 : // notification order
961 : // - column values
962 : // - cursorMoved
963 16 : setCurrentRow( true, true, aOldValues, aGuard );
964 : }
965 : else
966 : {
967 0 : movementFailed();
968 : }
969 :
970 : // - IsModified
971 : // - IsNew
972 16 : aNotifier.fire();
973 :
974 : // - RowCount/IsRowCountFinal
975 32 : fireRowcount();
976 : }
977 : SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
978 16 : return bRet;
979 : }
980 :
981 6 : sal_Bool SAL_CALL ORowSetBase::previous( ) throw(SQLException, RuntimeException, std::exception)
982 : {
983 : SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
984 6 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
985 6 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
986 :
987 6 : checkPositioningAllowed();
988 :
989 6 : bool bRet = !m_bBeforeFirst
990 6 : && notifyAllListenersCursorBeforeMove(aGuard);
991 :
992 6 : if ( bRet )
993 : {
994 : // check if we are inserting a row
995 6 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
996 :
997 6 : ORowSetNotifier aNotifier( this );
998 : // this will call cancelRowModification on the cache if necessary
999 :
1000 12 : ORowSetRow aOldValues = getOldRow(bWasNew);
1001 :
1002 6 : positionCache( MOVE_BACKWARD );
1003 6 : bRet = m_pCache->previous();
1004 6 : doCancelModification( );
1005 :
1006 : // if m_bBeforeFirst is false and bRet is false than we stood on the first row
1007 6 : if(!m_bBeforeFirst || bRet)
1008 : {
1009 : // notification order
1010 : // - column values
1011 : // - cursorMoved
1012 6 : setCurrentRow( true, true, aOldValues, aGuard );
1013 : }
1014 : else
1015 : {
1016 : SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
1017 : // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
1018 : // was |true| from the beginning
1019 0 : movementFailed();
1020 : }
1021 :
1022 : // - IsModified
1023 : // - IsNew
1024 6 : aNotifier.fire();
1025 :
1026 : // - RowCount/IsRowCountFinal
1027 12 : fireRowcount();
1028 : }
1029 : SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
1030 6 : return bRet;
1031 : }
1032 :
1033 1918 : void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
1034 : {
1035 : SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1036 1918 : m_bBeforeFirst = m_pCache->isBeforeFirst();
1037 1918 : m_bAfterLast = m_pCache->isAfterLast();
1038 :
1039 1918 : if(!(m_bBeforeFirst || m_bAfterLast))
1040 : {
1041 1874 : m_aBookmark = m_pCache->getBookmark();
1042 : OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1043 1874 : m_aCurrentRow = m_pCache->m_aMatrixIter;
1044 1874 : m_bIsInsertRow = false;
1045 : OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
1046 1874 : m_aCurrentRow.setBookmark(m_aBookmark);
1047 : OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
1048 : OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
1049 : OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1050 :
1051 1874 : m_aCurrentRow = m_pCache->m_aMatrixIter;
1052 1874 : m_bIsInsertRow = false;
1053 : OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
1054 : #if OSL_DEBUG_LEVEL > 0
1055 : ORowSetRow rRow = (*m_aCurrentRow);
1056 : OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
1057 : #endif
1058 :
1059 : // notification order
1060 : // - column values
1061 3748 : if ( _bDoNotify )
1062 1873 : firePropertyChange(_rOldValues);
1063 :
1064 : }
1065 : else
1066 : {
1067 44 : m_aOldRow->clearRow();
1068 44 : m_aCurrentRow = m_pCache->getEnd();
1069 44 : m_aBookmark = Any();
1070 44 : m_aCurrentRow.setBookmark(m_aBookmark);
1071 : }
1072 :
1073 : // TODO: can this be done before the notifications?
1074 1918 : if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
1075 1874 : m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
1076 :
1077 1918 : if ( _bMoved && _bDoNotify )
1078 : // - cursorMoved
1079 1905 : notifyAllListenersCursorMoved( _rGuard );
1080 :
1081 : SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1082 1918 : }
1083 :
1084 462 : void ORowSetBase::checkPositioningAllowed() throw( SQLException, RuntimeException )
1085 : {
1086 462 : if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
1087 2 : throwFunctionSequenceException(*m_pMySelf);
1088 461 : }
1089 :
1090 1 : Reference< XInterface > ORowSetBase::getStatement() throw( SQLException, RuntimeException, std::exception )
1091 : {
1092 1 : return NULL;
1093 : }
1094 :
1095 3 : void SAL_CALL ORowSetBase::refreshRow( ) throw(SQLException, RuntimeException, std::exception)
1096 : {
1097 3 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1098 3 : ::osl::MutexGuard aGuard( *m_pMutex );
1099 3 : checkCache();
1100 3 : if ( impl_rowDeleted() )
1101 2 : throwSQLException( "The current row is deleted", SQL_INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
1102 :
1103 2 : if(!(m_bBeforeFirst || m_bAfterLast))
1104 : {
1105 2 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
1106 2 : ORowSetRow aOldValues = getOldRow(bWasNew);
1107 2 : positionCache( MOVE_NONE );
1108 2 : m_pCache->refreshRow();
1109 2 : firePropertyChange(aOldValues);
1110 3 : }
1111 2 : }
1112 :
1113 2 : sal_Bool SAL_CALL ORowSetBase::rowUpdated( ) throw(SQLException, RuntimeException, std::exception)
1114 : {
1115 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1116 2 : checkCache();
1117 :
1118 2 : if ( impl_rowDeleted() )
1119 1 : return sal_False;
1120 :
1121 1 : return m_pCache->rowUpdated();
1122 : }
1123 :
1124 2 : sal_Bool SAL_CALL ORowSetBase::rowInserted( ) throw(SQLException, RuntimeException, std::exception)
1125 : {
1126 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1127 :
1128 2 : checkCache();
1129 :
1130 2 : if ( impl_rowDeleted() )
1131 1 : return sal_False;
1132 :
1133 1 : return m_pCache->rowInserted();
1134 : }
1135 :
1136 1244 : sal_Bool SAL_CALL ORowSetBase::rowDeleted( ) throw(SQLException, RuntimeException, std::exception)
1137 : {
1138 1244 : ::osl::MutexGuard aGuard( *m_pMutex );
1139 1244 : checkCache();
1140 1244 : return impl_rowDeleted();
1141 : }
1142 :
1143 15818 : bool ORowSetBase::impl_rowDeleted( )
1144 : {
1145 15818 : return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
1146 : }
1147 :
1148 : // XWarningsSupplier
1149 0 : Any SAL_CALL ORowSetBase::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
1150 : {
1151 0 : ::osl::MutexGuard aGuard( *m_pMutex );
1152 :
1153 0 : if ( m_pCache )
1154 : {
1155 0 : Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1156 0 : if ( xWarnings.is() )
1157 0 : return xWarnings->getWarnings();
1158 : }
1159 :
1160 0 : return Any();
1161 : }
1162 :
1163 0 : void SAL_CALL ORowSetBase::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
1164 : {
1165 0 : ::osl::MutexGuard aGuard( *m_pMutex );
1166 :
1167 0 : if ( m_pCache )
1168 : {
1169 0 : Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1170 0 : if ( xWarnings.is() )
1171 0 : xWarnings->clearWarnings();
1172 0 : }
1173 0 : }
1174 :
1175 1887 : void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
1176 : {
1177 1887 : if (!isPropertyChangeNotificationEnabled())
1178 1887 : return;
1179 :
1180 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
1181 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1182 : OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
1183 1887 : sal_Int32 i=0;
1184 1887 : TDataColumns::iterator aEnd = m_aDataColumns.end();
1185 7977 : for(TDataColumns::iterator aIter = m_aDataColumns.begin();aIter != aEnd;++aIter,++i)
1186 : {
1187 : try
1188 : {
1189 6090 : (*aIter)->fireValueChange(_rOldRow.is() ? (_rOldRow->get())[i+1] : ::connectivity::ORowSetValue());
1190 : }
1191 0 : catch (const Exception&)
1192 : {
1193 : SAL_WARN("dbaccess", "firePropertyChange: Exception on column " << i);
1194 : }
1195 : }
1196 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1197 : }
1198 :
1199 14 : void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
1200 : {
1201 : OSL_ENSURE(_nPos < (sal_Int32)m_aDataColumns.size(),"nPos is invalid!");
1202 14 : m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
1203 14 : }
1204 :
1205 1347 : void ORowSetBase::fireRowcount()
1206 : {
1207 1347 : }
1208 :
1209 1350 : bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
1210 : {
1211 1350 : return true;
1212 : }
1213 :
1214 1350 : void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
1215 : {
1216 1350 : }
1217 :
1218 0 : void ORowSetBase::notifyAllListeners(::osl::ResettableMutexGuard& /*_rGuard*/)
1219 : {
1220 0 : }
1221 :
1222 1336 : bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1223 : {
1224 1336 : return true;
1225 : }
1226 :
1227 36 : void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
1228 : {
1229 36 : Any aNew = css::uno::makeAny( _bNew );
1230 72 : Any aOld = css::uno::makeAny( _bOld );
1231 72 : fire( &_nProperty, &aNew, &aOld, 1, sal_False );
1232 36 : }
1233 :
1234 6437 : void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
1235 : {
1236 : SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1237 :
1238 6437 : bool bSuccess = false;
1239 6437 : if ( m_aBookmark.hasValue() )
1240 : {
1241 19209 : if (_ePrepareForDirection == MOVE_NONE_REFRESH ||
1242 25567 : (m_pCache->isAfterLast() != bool(isAfterLast())) || ( m_pCache->isBeforeFirst() != bool(isBeforeFirst()) ) ||
1243 25567 : m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
1244 4501 : bSuccess = m_pCache->moveToBookmark( m_aBookmark );
1245 : else
1246 1899 : bSuccess = true;
1247 : }
1248 : else
1249 : {
1250 37 : if ( m_bBeforeFirst )
1251 : {
1252 22 : bSuccess = m_pCache->beforeFirst();
1253 : }
1254 15 : else if ( m_bAfterLast )
1255 : {
1256 5 : bSuccess = m_pCache->afterLast();
1257 : }
1258 : else
1259 : {
1260 : OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
1261 10 : switch ( _ePrepareForDirection )
1262 : {
1263 : case MOVE_FORWARD:
1264 7 : if ( m_nDeletedPosition > 1 )
1265 7 : bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
1266 : else
1267 : {
1268 0 : m_pCache->beforeFirst();
1269 0 : bSuccess = true;
1270 : }
1271 7 : break;
1272 :
1273 : case MOVE_BACKWARD:
1274 3 : if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
1275 : {
1276 0 : m_pCache->afterLast();
1277 0 : bSuccess = true;
1278 : }
1279 : else
1280 3 : bSuccess = m_pCache->absolute( m_nDeletedPosition );
1281 3 : break;
1282 :
1283 : case MOVE_NONE:
1284 : case MOVE_NONE_REFRESH:
1285 0 : bSuccess = false; // will be asserted below
1286 0 : break;
1287 : }
1288 : }
1289 : }
1290 : OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
1291 : (void)bSuccess;
1292 :
1293 : SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1294 6437 : }
1295 :
1296 34983 : void ORowSetBase::checkCache()
1297 : {
1298 34983 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1299 34983 : if(!m_pCache)
1300 0 : throwFunctionSequenceException(*m_pMySelf);
1301 34983 : }
1302 :
1303 6 : void ORowSetBase::movementFailed()
1304 : {
1305 : SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1306 6 : m_aOldRow->clearRow();
1307 6 : m_aCurrentRow = m_pCache->getEnd();
1308 6 : m_bBeforeFirst = m_pCache->isBeforeFirst();
1309 6 : m_bAfterLast = m_pCache->isAfterLast();
1310 6 : m_aBookmark = Any();
1311 6 : m_aCurrentRow.setBookmark(m_aBookmark);
1312 : OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
1313 : SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1314 6 : }
1315 :
1316 1922 : ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
1317 : {
1318 : OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
1319 1922 : ORowSetRow aOldValues;
1320 1922 : if ( !_bWasNew && m_aOldRow->getRow().is() )
1321 1734 : aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
1322 1922 : return aOldValues;
1323 : }
1324 :
1325 0 : void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1326 : {
1327 0 : _rDefault.clear();
1328 0 : }
1329 :
1330 25 : void ORowSetBase::onDeleteRow( const Any& _rBookmark )
1331 : {
1332 25 : if ( rowDeleted() )
1333 : // not interested in
1334 26 : return;
1335 :
1336 24 : ::osl::MutexGuard aGuard( *m_pMutex );
1337 : //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
1338 24 : if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1339 : {
1340 19 : positionCache( MOVE_NONE );
1341 19 : m_nDeletedPosition = m_pCache->getRow();
1342 24 : }
1343 : }
1344 :
1345 25 : void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
1346 : {
1347 25 : if ( rowDeleted() )
1348 : {
1349 : // if we're a clone, and on a deleted row, and the main RowSet deleted another
1350 : // row (only the main RowSet can, clones can't), which is *before* our
1351 : // deleted position, then we have to adjust this position
1352 1 : if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
1353 0 : --m_nDeletedPosition;
1354 26 : return;
1355 : }
1356 :
1357 24 : ::osl::MutexGuard aGuard( *m_pMutex );
1358 24 : if ( compareBookmarks( _rBookmark, m_aBookmark ) == CompareBookmark::EQUAL )
1359 : {
1360 19 : m_aOldRow->clearRow();
1361 19 : m_aCurrentRow = m_pCache->getEnd();
1362 19 : m_aBookmark = Any();
1363 19 : m_aCurrentRow.setBookmark( m_aBookmark );
1364 24 : }
1365 : }
1366 :
1367 670 : sal_Int32 ORowSetBase::impl_getRowCount() const
1368 : {
1369 670 : sal_Int32 nRowCount( m_pCache->m_nRowCount );
1370 670 : if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
1371 33 : ++nRowCount;
1372 670 : return nRowCount;
1373 : }
1374 :
1375 30 : struct ORowSetNotifierImpl
1376 : {
1377 : ::std::vector<sal_Int32> aChangedColumns;
1378 : ::std::vector<Any> aChangedBookmarks;
1379 : ORowSetValueVector::Vector aRow;
1380 :
1381 : };
1382 :
1383 :
1384 1943 : ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
1385 : :m_pRowSet( _pRowSet )
1386 : ,m_bWasNew( false )
1387 1943 : ,m_bWasModified( false )
1388 : #ifdef DBG_UTIL
1389 : ,m_bNotifyCalled( false )
1390 : #endif
1391 : {
1392 :
1393 : OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1394 :
1395 : // remember the "inserted" and "modified" state for later firing
1396 1943 : m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
1397 1943 : m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
1398 :
1399 : // if the row set is on the insert row, then we need to cancel this
1400 1943 : if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
1401 3 : m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
1402 1943 : }
1403 :
1404 15 : ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet,const ORowSetValueVector::Vector& i_aRow )
1405 15 : :m_pImpl(new ORowSetNotifierImpl)
1406 : ,m_pRowSet( _pRowSet )
1407 : ,m_bWasNew( false )
1408 30 : ,m_bWasModified( false )
1409 : #ifdef DBG_UTIL
1410 : ,m_bNotifyCalled( false )
1411 : #endif
1412 : {
1413 :
1414 : OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1415 15 : m_pImpl->aRow = i_aRow; // yes, create a copy to store the old values
1416 15 : }
1417 :
1418 1958 : ORowSetNotifier::~ORowSetNotifier( )
1419 : {
1420 1958 : }
1421 :
1422 1942 : void ORowSetNotifier::fire()
1423 : {
1424 : // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
1425 : // (the former would be quite pathological, e.g. after a failed movement)
1426 :
1427 5823 : if ( m_bWasModified
1428 3887 : && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
1429 : )
1430 3 : m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
1431 :
1432 5823 : if ( m_bWasNew
1433 3887 : && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
1434 : )
1435 3 : m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
1436 :
1437 : #ifdef DBG_UTIL
1438 : m_bNotifyCalled = true;
1439 : #endif
1440 1942 : }
1441 :
1442 28 : ::std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const
1443 : {
1444 : OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1445 28 : return m_pImpl->aChangedColumns;
1446 : }
1447 :
1448 15 : void ORowSetNotifier::firePropertyChange()
1449 : {
1450 : OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1451 15 : if( m_pImpl.get() )
1452 : {
1453 15 : ::std::vector<sal_Int32>::iterator aIter = m_pImpl->aChangedColumns.begin();
1454 29 : for(;aIter != m_pImpl->aChangedColumns.end();++aIter)
1455 : {
1456 14 : m_pRowSet->firePropertyChange((*aIter)-1 ,m_pImpl->aRow[(*aIter)-1], ORowSetBase::GrantNotifierAccess());
1457 : }
1458 15 : if ( !m_pImpl->aChangedColumns.empty() )
1459 14 : m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
1460 : }
1461 15 : }
1462 :
1463 : } // namespace dbaccess
1464 :
1465 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|