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 362 : 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 362 : ,m_bIsInsertRow(false)
96 : {
97 362 : sal_Int32 nRBT = PropertyAttribute::READONLY | PropertyAttribute::BOUND | PropertyAttribute::TRANSIENT;
98 :
99 362 : sal_Int32 nInitialRowCountValue = 0;
100 362 : sal_Bool bInitialRowCountFinalValue( sal_False );
101 362 : registerPropertyNoMember( PROPERTY_ROWCOUNT, PROPERTY_ID_ROWCOUNT, nRBT, ::getCppuType( &nInitialRowCountValue ), &nInitialRowCountValue );
102 362 : registerPropertyNoMember( PROPERTY_ISROWCOUNTFINAL, PROPERTY_ID_ISROWCOUNTFINAL, nRBT, ::getBooleanCppuType(), &bInitialRowCountFinalValue );
103 362 : }
104 :
105 716 : ORowSetBase::~ORowSetBase()
106 : {
107 358 : if(m_pColumns)
108 : {
109 38 : TDataColumns().swap(m_aDataColumns);
110 38 : m_pColumns->acquire();
111 38 : m_pColumns->disposing();
112 38 : delete m_pColumns;
113 38 : m_pColumns = NULL;
114 : }
115 :
116 358 : if ( m_pEmptyCollection )
117 0 : delete m_pEmptyCollection;
118 :
119 358 : }
120 :
121 : // com::sun::star::lang::XTypeProvider
122 4 : Sequence< Type > ORowSetBase::getTypes() throw (RuntimeException, std::exception)
123 : {
124 4 : return ::comphelper::concatSequences(ORowSetBase_BASE::getTypes(),OPropertyStateContainer::getTypes());
125 : }
126 :
127 : // com::sun::star::uno::XInterface
128 6540 : Any ORowSetBase::queryInterface( const Type & rType ) throw (RuntimeException, std::exception)
129 : {
130 6540 : Any aRet = ORowSetBase_BASE::queryInterface(rType);
131 6540 : if(!aRet.hasValue())
132 4982 : aRet = OPropertyStateContainer::queryInterface(rType);
133 6540 : return aRet;
134 : }
135 :
136 1220 : void SAL_CALL ORowSetBase::getFastPropertyValue(Any& rValue,sal_Int32 nHandle) const
137 : {
138 1220 : if(m_pCache)
139 : {
140 732 : switch(nHandle)
141 : {
142 : case PROPERTY_ID_ROWCOUNT:
143 84 : rValue <<= impl_getRowCount();
144 84 : break;
145 : case PROPERTY_ID_ISROWCOUNTFINAL:
146 8 : rValue.setValue(&m_pCache->m_bRowCountFinal,::getCppuBooleanType());
147 8 : break;
148 : default:
149 640 : OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
150 : }
151 : }
152 : else
153 488 : OPropertyStateContainer::getFastPropertyValue(rValue,nHandle);
154 1220 : }
155 :
156 : // OComponentHelper
157 360 : void SAL_CALL ORowSetBase::disposing(void)
158 : {
159 360 : MutexGuard aGuard(*m_pMutex);
160 :
161 360 : if ( m_pColumns )
162 : {
163 38 : TDataColumns().swap(m_aDataColumns);
164 38 : m_pColumns->disposing();
165 : }
166 360 : if ( m_pCache )
167 : {
168 4 : m_pCache->deregisterOldRow(m_aOldRow);
169 4 : m_pCache->deleteIterator(this);
170 : }
171 360 : m_pCache = NULL;
172 360 : }
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 *const_cast<ORowSetBase*>(this)->getArrayHelper();
186 : }
187 :
188 : // XRow
189 1000 : sal_Bool SAL_CALL ORowSetBase::wasNull( ) throw(SQLException, RuntimeException, std::exception)
190 : {
191 1000 : ::osl::MutexGuard aGuard( *m_pMutex );
192 1000 : checkCache();
193 1000 : return impl_wasNull();
194 : }
195 :
196 1000 : bool ORowSetBase::impl_wasNull()
197 : {
198 1000 : return ((m_nLastColumnIndex != -1) && !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is()) ? ((*m_aCurrentRow)->get())[m_nLastColumnIndex].isNull() : sal_True;
199 : }
200 :
201 4952 : const ORowSetValue& ORowSetBase::getValue(sal_Int32 columnIndex)
202 : {
203 4952 : checkCache();
204 4952 : return impl_getValue(columnIndex);
205 : }
206 :
207 4952 : const ORowSetValue& ORowSetBase::impl_getValue(sal_Int32 columnIndex)
208 : {
209 4952 : if ( m_bBeforeFirst || m_bAfterLast )
210 : {
211 : SAL_WARN("dbaccess", "ORowSetBase::getValue: Illegal call here (we're before first or after last)!");
212 860 : ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_CURSOR_BEFORE_OR_AFTER ), SQL_INVALID_CURSOR_POSITION, *m_pMySelf );
213 : }
214 :
215 4522 : if ( impl_rowDeleted() )
216 : {
217 0 : return m_aEmptyValue;
218 : }
219 :
220 4522 : bool bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
221 4522 : if ( !bValidCurrentRow )
222 : {
223 : // currentrow is null when the clone moves the window
224 0 : positionCache( MOVE_NONE_REFRESH_ONLY );
225 0 : m_aCurrentRow = m_pCache->m_aMatrixIter;
226 0 : m_bIsInsertRow = false;
227 : OSL_ENSURE(!m_aCurrentRow.isNull(),"ORowSetBase::getValue: we don't stand on a valid row! Row is null.");
228 :
229 0 : bValidCurrentRow = ( !m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd() && m_aCurrentRow->is() );
230 : }
231 :
232 4522 : 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 4522 : return ((*m_aCurrentRow)->get())[m_nLastColumnIndex = columnIndex];
254 : }
255 :
256 : // we should normally never reach this
257 0 : return m_aEmptyValue;
258 : }
259 :
260 98 : OUString SAL_CALL ORowSetBase::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
261 : {
262 98 : ::osl::MutexGuard aGuard( *m_pMutex );
263 98 : 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 0 : sal_Int32 SAL_CALL ORowSetBase::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
285 : {
286 0 : ::osl::MutexGuard aGuard( *m_pMutex );
287 0 : 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_REFRESH_ONLY );
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 28 : Any SAL_CALL ORowSetBase::getBookmark( ) throw(SQLException, RuntimeException, std::exception)
403 : {
404 : SAL_INFO("dbaccess", "ORowSetBase::getBookmark() Clone = " << m_bClone);
405 28 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
406 28 : ::osl::MutexGuard aGuard( *m_pMutex );
407 28 : checkCache();
408 :
409 28 : 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 28 : if ( impl_rowDeleted() )
413 0 : ::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 28 : return m_aBookmark;
417 : }
418 :
419 4 : 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 4 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
424 :
425 4 : 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 4 : checkCache();
435 :
436 4 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
437 4 : if ( bRet )
438 : {
439 : // check if we are inserting a row
440 4 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
441 :
442 4 : ORowSetNotifier aNotifier( this );
443 : // this will call cancelRowModification on the cache if necessary
444 :
445 8 : ORowSetRow aOldValues = getOldRow(bWasNew);
446 :
447 4 : bRet = m_pCache->moveToBookmark(bookmark);
448 4 : doCancelModification( );
449 4 : if(bRet)
450 : {
451 : // notification order
452 : // - column values
453 : // - cursorMoved
454 4 : setCurrentRow( true, true, aOldValues, aGuard );
455 : }
456 : else
457 : {
458 0 : movementFailed();
459 : }
460 :
461 : // - IsModified
462 : // - IsNew
463 8 : aNotifier.fire( );
464 : }
465 : SAL_INFO("dbaccess", "ORowSetBase::moveToBookmark(Any) = " << bRet << " Clone = " << m_bClone);
466 4 : 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 10 : sal_Int32 SAL_CALL ORowSetBase::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException, std::exception)
513 : {
514 10 : ::osl::MutexGuard aGuard( *m_pMutex );
515 10 : checkCache();
516 10 : return m_pCache->compareBookmarks(_first,_second);
517 : }
518 :
519 2 : sal_Bool SAL_CALL ORowSetBase::hasOrderedBookmarks( ) throw(SQLException, RuntimeException, std::exception)
520 : {
521 2 : ::osl::MutexGuard aGuard( *m_pMutex );
522 2 : checkCache();
523 2 : return m_pCache->hasOrderedBookmarks();
524 : }
525 :
526 4 : sal_Int32 SAL_CALL ORowSetBase::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException, std::exception)
527 : {
528 4 : ::osl::MutexGuard aGuard( *m_pMutex );
529 4 : checkCache();
530 4 : return m_pCache->hashBookmark(bookmark);
531 : }
532 :
533 : // XResultSetMetaDataSupplier
534 632 : Reference< XResultSetMetaData > SAL_CALL ORowSetBase::getMetaData( ) throw(SQLException, RuntimeException, std::exception)
535 : {
536 632 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
537 :
538 632 : Reference< XResultSetMetaData > xMeta;
539 632 : if(m_pCache)
540 632 : xMeta = m_pCache->getMetaData();
541 :
542 632 : return xMeta;
543 : }
544 :
545 : // XColumnLocate
546 2 : sal_Int32 SAL_CALL ORowSetBase::findColumn( const OUString& columnName ) throw(SQLException, RuntimeException, std::exception)
547 : {
548 2 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
549 :
550 2 : ::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 2 : return m_pColumns ? m_pColumns->findColumn(columnName) : sal_Int32(0);
553 : }
554 :
555 : // ::com::sun::star::sdbcx::XColumnsSupplier
556 604 : Reference< XNameAccess > SAL_CALL ORowSetBase::getColumns( ) throw(RuntimeException, std::exception)
557 : {
558 604 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
559 :
560 604 : ::osl::MutexGuard aGuard( m_aColumnsMutex );
561 604 : 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 604 : return m_pColumns;
569 : }
570 :
571 : // XResultSet
572 182 : sal_Bool SAL_CALL ORowSetBase::next( ) throw(SQLException, RuntimeException, std::exception)
573 : {
574 : SAL_INFO("dbaccess", "ORowSetBase::next() Clone = " << m_bClone);
575 182 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
576 182 : checkCache();
577 :
578 182 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
579 182 : if ( bRet )
580 : {
581 : // check if we are inserting a row
582 182 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
583 :
584 182 : ORowSetNotifier aNotifier( this );
585 : // this will call cancelRowModification on the cache if necessary
586 :
587 364 : ORowSetRow aOldValues = getOldRow(bWasNew);
588 :
589 182 : positionCache( MOVE_FORWARD );
590 182 : bool bAfterLast = m_pCache->isAfterLast();
591 182 : bRet = m_pCache->next();
592 182 : doCancelModification( );
593 :
594 182 : if ( bRet || bAfterLast != m_pCache->isAfterLast() )
595 : {
596 : // notification order
597 : // - column values
598 : // - cursorMoved
599 182 : setCurrentRow( bRet, true, aOldValues, aGuard );
600 : OSL_ENSURE(!m_bBeforeFirst,"BeforeFirst is true. I don't know why?");
601 : }
602 : else
603 : {
604 : // moved after the last row
605 0 : movementFailed();
606 : OSL_ENSURE(m_bAfterLast,"AfterLast is false. I don't know why?");
607 : }
608 :
609 : // - IsModified
610 : // - IsNew
611 182 : aNotifier.fire();
612 :
613 : // - RowCount/IsRowCountFinal
614 364 : fireRowcount();
615 : }
616 : SAL_INFO("dbaccess", "ORowSetBase::next() = " << bRet << " Clone = " << m_bClone);
617 182 : return bRet;
618 : }
619 :
620 643 : sal_Bool SAL_CALL ORowSetBase::isBeforeFirst( ) throw(SQLException, RuntimeException, std::exception)
621 : {
622 643 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
623 643 : ::osl::MutexGuard aGuard( *m_pMutex );
624 643 : checkCache();
625 :
626 : SAL_INFO("dbaccess", "ORowSetBase::isBeforeFirst() = " << m_bBeforeFirst << " Clone = " << m_bClone);
627 :
628 643 : return m_bBeforeFirst;
629 : }
630 :
631 645 : sal_Bool SAL_CALL ORowSetBase::isAfterLast( ) throw(SQLException, RuntimeException, std::exception)
632 : {
633 645 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
634 645 : ::osl::MutexGuard aGuard( *m_pMutex );
635 645 : checkCache();
636 : SAL_INFO("dbaccess", "ORowSetBase::isAfterLast() = " << m_bAfterLast << " Clone = " << m_bClone);
637 :
638 645 : return m_bAfterLast;
639 : }
640 :
641 58 : bool ORowSetBase::isOnFirst()
642 : {
643 58 : return isFirst();
644 : }
645 :
646 60 : sal_Bool SAL_CALL ORowSetBase::isFirst( ) throw(SQLException, RuntimeException, std::exception)
647 : {
648 : SAL_INFO("dbaccess", "ORowSetBase::isFirst() Clone = " << m_bClone);
649 :
650 60 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
651 60 : ::osl::MutexGuard aGuard( *m_pMutex );
652 60 : checkCache();
653 :
654 60 : if ( m_bBeforeFirst || m_bAfterLast )
655 42 : return sal_False;
656 :
657 18 : if ( impl_rowDeleted() )
658 0 : return ( m_nDeletedPosition == 1 );
659 :
660 18 : bool bIsFirst = m_pCache->isFirst();
661 :
662 : SAL_INFO("dbaccess", "ORowSetBase::isFirst() = " << bIsFirst << " Clone = " << m_bClone);
663 18 : return bIsFirst;
664 : }
665 :
666 4 : bool ORowSetBase::isOnLast()
667 : {
668 4 : return isLast();
669 : }
670 :
671 6 : sal_Bool SAL_CALL ORowSetBase::isLast( ) throw(SQLException, RuntimeException, std::exception)
672 : {
673 : SAL_INFO("dbaccess", "ORowSetBase::isLast() Clone = " << m_bClone);
674 6 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
675 6 : ::osl::MutexGuard aGuard( *m_pMutex );
676 6 : checkCache();
677 :
678 6 : if ( m_bBeforeFirst || m_bAfterLast )
679 2 : return sal_False;
680 :
681 4 : if ( impl_rowDeleted() )
682 : {
683 0 : if ( !m_pCache->m_bRowCountFinal )
684 0 : return sal_False;
685 : else
686 0 : return ( m_nDeletedPosition == impl_getRowCount() );
687 : }
688 :
689 4 : bool bIsLast = m_pCache->isLast();
690 :
691 : SAL_INFO("dbaccess", "ORowSetBase::isLast() = " << bIsLast << " Clone = " << m_bClone);
692 4 : return bIsLast;
693 : }
694 :
695 26 : void SAL_CALL ORowSetBase::beforeFirst( ) throw(SQLException, RuntimeException, std::exception)
696 : {
697 : SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
698 26 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
699 26 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
700 :
701 26 : checkPositioningAllowed();
702 :
703 : // check if we are inserting a row
704 26 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
705 :
706 26 : if((bWasNew || !m_bBeforeFirst) && notifyAllListenersCursorBeforeMove(aGuard) )
707 : {
708 12 : ORowSetNotifier aNotifier( this );
709 : // this will call cancelRowModification on the cache if necessary
710 :
711 12 : if ( !m_bBeforeFirst )
712 : {
713 12 : ORowSetRow aOldValues = getOldRow(bWasNew);
714 12 : m_pCache->beforeFirst();
715 12 : doCancelModification( );
716 :
717 : // notification order
718 : // - column values
719 : // - cursorMoved
720 12 : setCurrentRow( true, true, aOldValues, aGuard );
721 :
722 : // - IsModified
723 : // - Isnew
724 12 : aNotifier.fire();
725 :
726 : // - RowCount/IsRowCountFinal
727 12 : fireRowcount();
728 : }
729 :
730 : // to be done _after_ the notifications!
731 12 : m_aOldRow->clearRow();
732 : }
733 26 : SAL_INFO("dbaccess", "ORowSetBase::beforeFirst() Clone = " << m_bClone);
734 26 : }
735 :
736 10 : void SAL_CALL ORowSetBase::afterLast( ) throw(SQLException, RuntimeException, std::exception)
737 : {
738 : SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
739 10 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
740 :
741 10 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
742 10 : checkPositioningAllowed();
743 :
744 10 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
745 :
746 10 : if((bWasNew || !m_bAfterLast) && notifyAllListenersCursorBeforeMove(aGuard) )
747 : {
748 : // check if we are inserting a row
749 10 : ORowSetNotifier aNotifier( this );
750 : // this will call cancelRowModification on the cache if necessary
751 :
752 10 : if(!m_bAfterLast)
753 : {
754 10 : ORowSetRow aOldValues = getOldRow(bWasNew);
755 :
756 10 : m_pCache->afterLast();
757 10 : doCancelModification( );
758 :
759 : // notification order
760 : // - column values
761 : // - cursorMoved
762 10 : setCurrentRow( true, true, aOldValues, aGuard );
763 :
764 : // - IsModified
765 : // - Isnew
766 10 : aNotifier.fire();
767 :
768 : // - RowCount/IsRowCountFinal
769 10 : fireRowcount();
770 10 : }
771 : }
772 10 : SAL_INFO("dbaccess", "ORowSetBase::afterLast() Clone = " << m_bClone);
773 10 : }
774 :
775 64 : bool SAL_CALL ORowSetBase::move( ::std::mem_fun_t<bool,ORowSetBase>& _aCheckFunctor,
776 : ::std::mem_fun_t<bool,ORowSetCache>& _aMovementFunctor)
777 : {
778 : SAL_INFO("dbaccess", "ORowSetBase::move() Clone = " << m_bClone);
779 64 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
780 64 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
781 64 : checkPositioningAllowed();
782 :
783 62 : bool bRet( notifyAllListenersCursorBeforeMove( aGuard ) );
784 62 : if( bRet )
785 : {
786 : // check if we are inserting a row
787 62 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
788 :
789 62 : ORowSetNotifier aNotifier( this );
790 : // this will call cancelRowModification on the cache if necessary
791 :
792 124 : ORowSetRow aOldValues = getOldRow(bWasNew);
793 :
794 62 : bool bMoved = ( bWasNew || !_aCheckFunctor(this) );
795 :
796 62 : bRet = _aMovementFunctor(m_pCache);
797 62 : doCancelModification( );
798 :
799 62 : if ( bRet )
800 : {
801 : // notification order
802 : // - column values
803 : // - cursorMoved
804 56 : setCurrentRow( bMoved, true, aOldValues, aGuard );
805 : }
806 : else
807 : { // first goes wrong so there is no row
808 6 : movementFailed();
809 : }
810 :
811 : // - IsModified
812 : // - IsNew
813 62 : aNotifier.fire();
814 :
815 : // - RowCount/IsRowCountFinal
816 124 : fireRowcount();
817 : }
818 : SAL_INFO("dbaccess", "ORowSetBase::move() = " << bRet << " Clone = " << m_bClone);
819 64 : return bRet;
820 : }
821 :
822 60 : sal_Bool SAL_CALL ORowSetBase::first( ) throw(SQLException, RuntimeException, std::exception)
823 : {
824 : SAL_INFO("dbaccess", "ORowSetBase::first() Clone = " << m_bClone);
825 60 : ::std::mem_fun_t<bool,ORowSetBase> ioF_tmp(&ORowSetBase::isOnFirst);
826 60 : ::std::mem_fun_t<bool,ORowSetCache> F_tmp(&ORowSetCache::first);
827 60 : return move(ioF_tmp,F_tmp);
828 : }
829 :
830 4 : sal_Bool SAL_CALL ORowSetBase::last( ) throw(SQLException, RuntimeException, std::exception)
831 : {
832 : SAL_INFO("dbaccess", "ORowSetBase::last() Clone = " << m_bClone);
833 4 : ::std::mem_fun_t<bool,ORowSetBase> ioL_tmp(&ORowSetBase::isOnLast);
834 4 : ::std::mem_fun_t<bool,ORowSetCache> L_tmp(&ORowSetCache::last);
835 4 : return move(ioL_tmp,L_tmp);
836 : }
837 :
838 92 : sal_Int32 SAL_CALL ORowSetBase::getRow( ) throw(SQLException, RuntimeException, std::exception)
839 : {
840 : SAL_INFO("dbaccess", "ORowSetBase::getRow() Clone = " << m_bClone);
841 92 : ::osl::MutexGuard aGuard( *m_pMutex );
842 :
843 92 : checkCache();
844 92 : return impl_getRow();
845 : }
846 :
847 92 : sal_Int32 ORowSetBase::impl_getRow()
848 : {
849 92 : sal_Int32 nPos = 0;
850 92 : if ( m_bBeforeFirst )
851 4 : nPos = 0;
852 88 : else if ( m_bAfterLast )
853 0 : nPos = impl_getRowCount() + 1;
854 88 : else if ( impl_rowDeleted() )
855 0 : nPos = m_nDeletedPosition;
856 88 : else if ( !m_bClone && m_pCache->m_bNew )
857 0 : nPos = 0;
858 : else
859 : {
860 264 : if ( m_pCache->isAfterLast()
861 88 : || m_pCache->isBeforeFirst()
862 440 : || ( m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
863 : )
864 : {
865 0 : positionCache( MOVE_NONE_REFRESH_ONLY );
866 : }
867 88 : nPos = m_pCache->getRow();
868 : }
869 : SAL_INFO("dbaccess", "ORowSetBase::impl_getRow() = " << nPos << " Clone = " << m_bClone);
870 92 : return nPos;
871 : }
872 :
873 4 : sal_Bool SAL_CALL ORowSetBase::absolute( sal_Int32 row ) throw(SQLException, RuntimeException, std::exception)
874 : {
875 : SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") Clone = " << m_bClone);
876 4 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
877 4 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
878 4 : checkPositioningAllowed();
879 :
880 4 : bool bRet = ( row > 0 )
881 4 : && notifyAllListenersCursorBeforeMove( aGuard );
882 4 : if ( bRet )
883 : {
884 : // check if we are inserting a row
885 4 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
886 :
887 4 : ORowSetNotifier aNotifier( this );
888 : // this will call cancelRowModification on the cache if necessary
889 :
890 8 : ORowSetRow aOldValues = getOldRow(bWasNew);
891 :
892 4 : bRet = m_pCache->absolute(row);
893 4 : doCancelModification( );
894 :
895 4 : if(bRet)
896 : {
897 : // notification order
898 : // - column values
899 : // - cursorMoved
900 4 : setCurrentRow( true, true, aOldValues, aGuard );
901 : }
902 : else
903 : { // absolute movement goes wrong we stand left or right side of the rows
904 0 : movementFailed();
905 : }
906 :
907 : // - IsModified
908 : // - IsNew
909 4 : aNotifier.fire();
910 :
911 : // - RowCount/IsRowCountFinal
912 8 : fireRowcount();
913 : }
914 : SAL_INFO("dbaccess", "ORowSetBase::absolute(" << row << ") = " << bRet << " Clone = " << m_bClone);
915 4 : return bRet;
916 : }
917 :
918 16 : sal_Bool SAL_CALL ORowSetBase::relative( sal_Int32 rows ) throw(SQLException, RuntimeException, std::exception)
919 : {
920 : SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") Clone = " << m_bClone);
921 16 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
922 :
923 16 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
924 :
925 16 : if(!rows)
926 0 : return sal_True; // in this case do nothing
927 :
928 16 : checkPositioningAllowed();
929 :
930 : bool bRet =
931 16 : ( ( !m_bAfterLast || rows <= 0 )
932 16 : && ( !m_bBeforeFirst || rows >= 0 )
933 32 : && notifyAllListenersCursorBeforeMove( aGuard )
934 16 : );
935 :
936 16 : if ( bRet )
937 : {
938 : // check if we are inserting a row
939 16 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
940 :
941 16 : ORowSetNotifier aNotifier( this );
942 : // this will call cancelRowModification on the cache if necessary
943 :
944 32 : ORowSetRow aOldValues = getOldRow(bWasNew);
945 :
946 16 : positionCache( rows > 0 ? MOVE_FORWARD : MOVE_BACKWARD );
947 16 : bRet = m_pCache->relative(rows);
948 16 : doCancelModification( );
949 :
950 16 : if(bRet)
951 : {
952 : // notification order
953 : // - column values
954 : // - cursorMoved
955 16 : setCurrentRow( true, true, aOldValues, aGuard );
956 : }
957 : else
958 : {
959 0 : movementFailed();
960 : }
961 :
962 : // - IsModified
963 : // - IsNew
964 16 : aNotifier.fire();
965 :
966 : // - RowCount/IsRowCountFinal
967 32 : fireRowcount();
968 : }
969 : SAL_INFO("dbaccess", "ORowSetBase::relative(" << rows << ") = " << bRet << " Clone = " << m_bClone);
970 16 : return bRet;
971 : }
972 :
973 2 : sal_Bool SAL_CALL ORowSetBase::previous( ) throw(SQLException, RuntimeException, std::exception)
974 : {
975 : SAL_INFO("dbaccess", "ORowSetBase::previous() Clone = " << m_bClone);
976 2 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
977 2 : ::osl::ResettableMutexGuard aGuard( *m_pMutex );
978 :
979 2 : checkPositioningAllowed();
980 :
981 2 : bool bRet = !m_bBeforeFirst
982 2 : && notifyAllListenersCursorBeforeMove(aGuard);
983 :
984 2 : if ( bRet )
985 : {
986 : // check if we are inserting a row
987 2 : bool bWasNew = m_pCache->m_bNew || rowDeleted();
988 :
989 2 : ORowSetNotifier aNotifier( this );
990 : // this will call cancelRowModification on the cache if necessary
991 :
992 4 : ORowSetRow aOldValues = getOldRow(bWasNew);
993 :
994 2 : positionCache( MOVE_BACKWARD );
995 2 : bRet = m_pCache->previous();
996 2 : doCancelModification( );
997 :
998 : // if m_bBeforeFirst is false and bRet is false than we stood on the first row
999 2 : if(!m_bBeforeFirst || bRet)
1000 : {
1001 : // notification order
1002 : // - column values
1003 : // - cursorMoved
1004 2 : setCurrentRow( true, true, aOldValues, aGuard );
1005 : }
1006 : else
1007 : {
1008 : SAL_WARN("dbaccess", "ORowSetBase::previous: inconsistency!" );
1009 : // we should never reach this place, as we should not get into this whole branch if m_bBeforeFirst
1010 : // was |true| from the beginning
1011 0 : movementFailed();
1012 : }
1013 :
1014 : // - IsModified
1015 : // - IsNew
1016 2 : aNotifier.fire();
1017 :
1018 : // - RowCount/IsRowCountFinal
1019 4 : fireRowcount();
1020 : }
1021 : SAL_INFO("dbaccess", "ORowSetBase::previous() = " << bRet << " Clone = " << m_bClone);
1022 2 : return bRet;
1023 : }
1024 :
1025 290 : void ORowSetBase::setCurrentRow( bool _bMoved, bool _bDoNotify, const ORowSetRow& _rOldValues, ::osl::ResettableMutexGuard& _rGuard )
1026 : {
1027 : SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1028 290 : m_bBeforeFirst = m_pCache->isBeforeFirst();
1029 290 : m_bAfterLast = m_pCache->isAfterLast();
1030 :
1031 290 : if(!(m_bBeforeFirst || m_bAfterLast))
1032 : {
1033 256 : m_aBookmark = m_pCache->getBookmark();
1034 : OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1035 256 : m_aCurrentRow = m_pCache->m_aMatrixIter;
1036 256 : m_bIsInsertRow = false;
1037 : OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is null!");
1038 256 : m_aCurrentRow.setBookmark(m_aBookmark);
1039 : OSL_ENSURE(!m_aCurrentRow.isNull() && m_aCurrentRow != m_pCache->getEnd(),"Position of matrix iterator isn't valid!");
1040 : OSL_ENSURE(m_aCurrentRow->is(),"Currentrow isn't valid");
1041 : OSL_ENSURE(m_aBookmark.hasValue(),"Bookmark has no value!");
1042 :
1043 256 : m_aCurrentRow = m_pCache->m_aMatrixIter;
1044 256 : m_bIsInsertRow = false;
1045 : OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
1046 : #if OSL_DEBUG_LEVEL > 0
1047 : ORowSetRow rRow = (*m_aCurrentRow);
1048 : OSL_ENSURE(rRow.is() ,"Invalid size of vector!");
1049 : #endif
1050 : // the cache could repositioned so we need to adjust the cache
1051 512 : if ( _bMoved && m_aCurrentRow.isNull() )
1052 : {
1053 0 : positionCache( MOVE_NONE_REFRESH_ONLY );
1054 0 : m_aCurrentRow = m_pCache->m_aMatrixIter;
1055 0 : m_bIsInsertRow = false;
1056 : OSL_ENSURE(!m_aCurrentRow.isNull(),"CurrentRow is nul after positionCache!");
1057 : }
1058 : }
1059 : else
1060 : {
1061 34 : m_aOldRow->clearRow();
1062 34 : m_aCurrentRow = m_pCache->getEnd();
1063 34 : m_aBookmark = Any();
1064 34 : m_aCurrentRow.setBookmark(m_aBookmark);
1065 : }
1066 :
1067 : // notification order
1068 : // - column values
1069 290 : if ( _bDoNotify )
1070 290 : firePropertyChange(_rOldValues);
1071 :
1072 : // TODO: can this be done before the notifications?
1073 290 : if(!(m_bBeforeFirst || m_bAfterLast) && !m_aCurrentRow.isNull() && m_aCurrentRow->is() && m_aCurrentRow != m_pCache->getEnd())
1074 256 : m_aOldRow->setRow(new ORowSetValueVector( *(*m_aCurrentRow) ));
1075 :
1076 290 : if ( _bMoved && _bDoNotify )
1077 : // - cursorMoved
1078 266 : notifyAllListenersCursorMoved( _rGuard );
1079 :
1080 : SAL_INFO("dbaccess", "ORowSetBase::setCurrentRow() Clone = " << m_bClone);
1081 290 : }
1082 :
1083 128 : void ORowSetBase::checkPositioningAllowed() throw( SQLException, RuntimeException )
1084 : {
1085 128 : if(!m_pCache || m_nResultSetType == ResultSetType::FORWARD_ONLY)
1086 4 : throwFunctionSequenceException(*m_pMySelf);
1087 126 : }
1088 :
1089 2 : Reference< XInterface > ORowSetBase::getStatement(void) throw( SQLException, RuntimeException, std::exception )
1090 : {
1091 2 : return NULL;
1092 : }
1093 :
1094 2 : void SAL_CALL ORowSetBase::refreshRow( ) throw(SQLException, RuntimeException, std::exception)
1095 : {
1096 2 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1097 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1098 2 : checkCache();
1099 2 : if ( impl_rowDeleted() )
1100 0 : throwSQLException( "The current row is deleted", SQL_INVALID_CURSOR_STATE, Reference< XRowSet >( this ) );
1101 :
1102 2 : if(!(m_bBeforeFirst || m_bAfterLast))
1103 : {
1104 2 : bool bWasNew = m_pCache->m_bNew || impl_rowDeleted();
1105 2 : ORowSetRow aOldValues = getOldRow(bWasNew);
1106 2 : positionCache( MOVE_NONE_REFRESH_ONLY );
1107 2 : m_pCache->refreshRow();
1108 2 : firePropertyChange(aOldValues);
1109 2 : }
1110 2 : }
1111 :
1112 2 : sal_Bool SAL_CALL ORowSetBase::rowUpdated( ) throw(SQLException, RuntimeException, std::exception)
1113 : {
1114 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1115 2 : checkCache();
1116 :
1117 2 : if ( impl_rowDeleted() )
1118 0 : return sal_False;
1119 :
1120 2 : return m_pCache->rowUpdated();
1121 : }
1122 :
1123 2 : sal_Bool SAL_CALL ORowSetBase::rowInserted( ) throw(SQLException, RuntimeException, std::exception)
1124 : {
1125 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1126 :
1127 2 : checkCache();
1128 :
1129 2 : if ( impl_rowDeleted() )
1130 0 : return sal_False;
1131 :
1132 2 : return m_pCache->rowInserted();
1133 : }
1134 :
1135 561 : sal_Bool SAL_CALL ORowSetBase::rowDeleted( ) throw(SQLException, RuntimeException, std::exception)
1136 : {
1137 561 : ::osl::MutexGuard aGuard( *m_pMutex );
1138 561 : checkCache();
1139 561 : return impl_rowDeleted();
1140 : }
1141 :
1142 5451 : bool ORowSetBase::impl_rowDeleted( )
1143 : {
1144 5451 : return !m_aBookmark.hasValue() && !m_bBeforeFirst && !m_bAfterLast;
1145 : }
1146 :
1147 : // XWarningsSupplier
1148 0 : Any SAL_CALL ORowSetBase::getWarnings( ) throw(SQLException, RuntimeException, std::exception)
1149 : {
1150 0 : ::osl::MutexGuard aGuard( *m_pMutex );
1151 :
1152 0 : if ( m_pCache )
1153 : {
1154 0 : Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1155 0 : if ( xWarnings.is() )
1156 0 : return xWarnings->getWarnings();
1157 : }
1158 :
1159 0 : return Any();
1160 : }
1161 :
1162 0 : void SAL_CALL ORowSetBase::clearWarnings( ) throw(SQLException, RuntimeException, std::exception)
1163 : {
1164 0 : ::osl::MutexGuard aGuard( *m_pMutex );
1165 :
1166 0 : if ( m_pCache )
1167 : {
1168 0 : Reference< XWarningsSupplier > xWarnings( m_pCache->m_xSet.get(), UNO_QUERY );
1169 0 : if ( xWarnings.is() )
1170 0 : xWarnings->clearWarnings();
1171 0 : }
1172 0 : }
1173 :
1174 302 : void ORowSetBase::firePropertyChange(const ORowSetRow& _rOldRow)
1175 : {
1176 302 : if (!isPropertyChangeNotificationEnabled())
1177 302 : return;
1178 :
1179 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange" );
1180 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1181 : OSL_ENSURE(m_pColumns,"Columns can not be NULL here!");
1182 302 : sal_Int32 i=0;
1183 302 : TDataColumns::iterator aEnd = m_aDataColumns.end();
1184 3764 : for(TDataColumns::iterator aIter = m_aDataColumns.begin();aIter != aEnd;++aIter,++i)
1185 : {
1186 : try
1187 : {
1188 3888 : (*aIter)->fireValueChange(_rOldRow.is() ? (_rOldRow->get())[i+1] : ::connectivity::ORowSetValue());
1189 : }
1190 426 : catch (const Exception&)
1191 : {
1192 : SAL_WARN("dbaccess", "firePropertyChange: Exception on column " << i);
1193 : }
1194 : }
1195 : SAL_INFO("dbaccess", "ORowSetBase::firePropertyChange() Clone = " << m_bClone);
1196 : }
1197 :
1198 12 : void ORowSetBase::firePropertyChange(sal_Int32 _nPos,const ::connectivity::ORowSetValue& _rOldValue)
1199 : {
1200 : OSL_ENSURE(_nPos < (sal_Int32)m_aDataColumns.size(),"nPos is invalid!");
1201 12 : m_aDataColumns[_nPos]->fireValueChange(_rOldValue);
1202 12 : }
1203 :
1204 16 : void ORowSetBase::fireRowcount()
1205 : {
1206 16 : }
1207 :
1208 16 : bool ORowSetBase::notifyAllListenersCursorBeforeMove(::osl::ResettableMutexGuard& /*_rGuard*/)
1209 : {
1210 16 : return true;
1211 : }
1212 :
1213 16 : void ORowSetBase::notifyAllListenersCursorMoved(::osl::ResettableMutexGuard& /*_rGuard*/)
1214 : {
1215 16 : }
1216 :
1217 0 : void ORowSetBase::notifyAllListeners(::osl::ResettableMutexGuard& /*_rGuard*/)
1218 : {
1219 0 : }
1220 :
1221 16 : bool ORowSetBase::isPropertyChangeNotificationEnabled() const
1222 : {
1223 16 : return true;
1224 : }
1225 :
1226 28 : void ORowSetBase::fireProperty( sal_Int32 _nProperty, bool _bNew, bool _bOld )
1227 : {
1228 28 : Any aNew = css::uno::makeAny( _bNew );
1229 56 : Any aOld = css::uno::makeAny( _bOld );
1230 56 : fire( &_nProperty, &aNew, &aOld, 1, sal_False );
1231 28 : }
1232 :
1233 210 : void ORowSetBase::positionCache( CursorMoveDirection _ePrepareForDirection )
1234 : {
1235 : SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1236 :
1237 210 : bool bSuccess = false;
1238 210 : if ( m_aBookmark.hasValue() )
1239 : {
1240 776 : if ( _ePrepareForDirection == MOVE_NONE_REFRESH_ONLY ||
1241 760 : m_pCache->compareBookmarks( m_aBookmark, m_pCache->getBookmark() ) != CompareBookmark::EQUAL )
1242 8 : bSuccess = m_pCache->moveToBookmark( m_aBookmark );
1243 : else
1244 188 : bSuccess = true;
1245 : }
1246 : else
1247 : {
1248 14 : if ( m_bBeforeFirst )
1249 : {
1250 12 : bSuccess = m_pCache->beforeFirst();
1251 : }
1252 2 : else if ( m_bAfterLast )
1253 : {
1254 0 : bSuccess = m_pCache->afterLast();
1255 : }
1256 : else
1257 : {
1258 : OSL_ENSURE( m_nDeletedPosition >= 1, "ORowSetBase::positionCache: no bookmark, and no valid 'deleted position'!" );
1259 2 : switch ( _ePrepareForDirection )
1260 : {
1261 : case MOVE_FORWARD:
1262 2 : if ( m_nDeletedPosition > 1 )
1263 2 : bSuccess = m_pCache->absolute( m_nDeletedPosition - 1 );
1264 : else
1265 : {
1266 0 : m_pCache->beforeFirst();
1267 0 : bSuccess = true;
1268 : }
1269 2 : break;
1270 :
1271 : case MOVE_BACKWARD:
1272 0 : if ( m_pCache->m_bRowCountFinal && ( m_nDeletedPosition == impl_getRowCount() ) )
1273 : {
1274 0 : m_pCache->afterLast();
1275 0 : bSuccess = true;
1276 : }
1277 : else
1278 0 : bSuccess = m_pCache->absolute( m_nDeletedPosition );
1279 0 : break;
1280 :
1281 : case MOVE_NONE_REFRESH_ONLY:
1282 0 : bSuccess = false; // will be asserted below
1283 0 : break;
1284 : }
1285 : }
1286 : }
1287 : OSL_ENSURE( bSuccess, "ORowSetBase::positionCache: failed!" );
1288 : (void)bSuccess;
1289 :
1290 : SAL_INFO("dbaccess", "ORowSetBase::positionCache() Clone = " << m_bClone);
1291 210 : }
1292 :
1293 13705 : void ORowSetBase::checkCache()
1294 : {
1295 13705 : ::connectivity::checkDisposed(m_rBHelper.bDisposed);
1296 13705 : if(!m_pCache)
1297 0 : throwFunctionSequenceException(*m_pMySelf);
1298 13705 : }
1299 :
1300 6 : void ORowSetBase::movementFailed()
1301 : {
1302 : SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1303 6 : m_aOldRow->clearRow();
1304 6 : m_aCurrentRow = m_pCache->getEnd();
1305 6 : m_bBeforeFirst = m_pCache->isBeforeFirst();
1306 6 : m_bAfterLast = m_pCache->isAfterLast();
1307 6 : m_aBookmark = Any();
1308 6 : m_aCurrentRow.setBookmark(m_aBookmark);
1309 : OSL_ENSURE(m_bBeforeFirst || m_bAfterLast,"BeforeFirst or AfterLast is wrong!");
1310 : SAL_INFO("dbaccess", "ORowSetBase::movementFailed() Clone = " << m_bClone);
1311 6 : }
1312 :
1313 296 : ORowSetRow ORowSetBase::getOldRow(bool _bWasNew)
1314 : {
1315 : OSL_ENSURE(m_aOldRow.is(),"RowSetRowHElper isn't valid!");
1316 296 : ORowSetRow aOldValues;
1317 296 : if ( !_bWasNew && m_aOldRow->getRow().is() )
1318 230 : aOldValues = new ORowSetValueVector( *(m_aOldRow->getRow())); // remember the old values
1319 296 : return aOldValues;
1320 : }
1321 :
1322 0 : void ORowSetBase::getPropertyDefaultByHandle( sal_Int32 /*_nHandle*/, Any& _rDefault ) const
1323 : {
1324 0 : _rDefault.clear();
1325 0 : }
1326 :
1327 2 : void ORowSetBase::onDeleteRow( const Any& _rBookmark )
1328 : {
1329 2 : if ( rowDeleted() )
1330 : // not interested in
1331 2 : return;
1332 :
1333 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1334 : //OSL_ENSURE( m_aBookmark.hasValue(), "ORowSetBase::onDeleteRow: Bookmark isn't valid!" );
1335 2 : if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 )
1336 : {
1337 2 : positionCache( MOVE_NONE_REFRESH_ONLY );
1338 2 : m_nDeletedPosition = m_pCache->getRow();
1339 2 : }
1340 : }
1341 :
1342 2 : void ORowSetBase::onDeletedRow( const Any& _rBookmark, sal_Int32 _nPos )
1343 : {
1344 2 : if ( rowDeleted() )
1345 : {
1346 : // if we're a clone, and on a deleted row, and the main RowSet deleted another
1347 : // row (only the main RowSet can, clones can't), which is *before* our
1348 : // deleted position, then we have to adjust this position
1349 0 : if ( m_bClone && ( _nPos < m_nDeletedPosition ) )
1350 0 : --m_nDeletedPosition;
1351 2 : return;
1352 : }
1353 :
1354 2 : ::osl::MutexGuard aGuard( *m_pMutex );
1355 2 : if ( compareBookmarks( _rBookmark, m_aBookmark ) == 0 )
1356 : {
1357 2 : m_aOldRow->clearRow();
1358 2 : m_aCurrentRow = m_pCache->getEnd();
1359 2 : m_aBookmark = Any();
1360 2 : m_aCurrentRow.setBookmark( m_aBookmark );
1361 2 : }
1362 : }
1363 :
1364 378 : sal_Int32 ORowSetBase::impl_getRowCount() const
1365 : {
1366 378 : sal_Int32 nRowCount( m_pCache->m_nRowCount );
1367 378 : if ( const_cast< ORowSetBase* >( this )->rowDeleted() && !m_pCache->m_bNew )
1368 4 : ++nRowCount;
1369 378 : return nRowCount;
1370 : }
1371 :
1372 24 : struct ORowSetNotifierImpl
1373 : {
1374 : ::std::vector<sal_Int32> aChangedColumns;
1375 : ::std::vector<Any> aChangedBookmarks;
1376 : ORowSetValueVector::Vector aRow;
1377 :
1378 : };
1379 :
1380 :
1381 298 : ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet )
1382 : :m_pRowSet( _pRowSet )
1383 : ,m_bWasNew( false )
1384 298 : ,m_bWasModified( false )
1385 : #ifdef DBG_UTIL
1386 : ,m_bNotifyCalled( false )
1387 : #endif
1388 : {
1389 :
1390 : OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1391 :
1392 : // remember the "inserted" and "modified" state for later firing
1393 298 : m_bWasNew = m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() );
1394 298 : m_bWasModified = m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() );
1395 :
1396 : // if the row set is on the insert row, then we need to cancel this
1397 298 : if ( m_pRowSet->isModification( ORowSetBase::GrantNotifierAccess() ) )
1398 0 : m_pRowSet->doCancelModification( ORowSetBase::GrantNotifierAccess() );
1399 298 : }
1400 :
1401 12 : ORowSetNotifier::ORowSetNotifier( ORowSetBase* _pRowSet,const ORowSetValueVector::Vector& i_aRow )
1402 12 : :m_pImpl(new ORowSetNotifierImpl)
1403 : ,m_pRowSet( _pRowSet )
1404 : ,m_bWasNew( false )
1405 24 : ,m_bWasModified( false )
1406 : #ifdef DBG_UTIL
1407 : ,m_bNotifyCalled( false )
1408 : #endif
1409 : {
1410 :
1411 : OSL_ENSURE( m_pRowSet, "ORowSetNotifier::ORowSetNotifier: invalid row set. This wil crash." );
1412 12 : m_pImpl->aRow = i_aRow; // yes, create a copy to store the old values
1413 12 : }
1414 :
1415 310 : ORowSetNotifier::~ORowSetNotifier( )
1416 : {
1417 310 : }
1418 :
1419 298 : void ORowSetNotifier::fire()
1420 : {
1421 : // we're not interested in firing changes FALSE->TRUE, only TRUE->FALSE.
1422 : // (the former would be quite pathological, e.g. after a failed movement)
1423 :
1424 892 : if ( m_bWasModified
1425 598 : && ( m_bWasModified != m_pRowSet->isModified( ORowSetBase::GrantNotifierAccess() ) )
1426 : )
1427 2 : m_pRowSet->fireProperty( PROPERTY_ID_ISMODIFIED, false, true, ORowSetBase::GrantNotifierAccess() );
1428 :
1429 894 : if ( m_bWasNew
1430 596 : && ( m_bWasNew != m_pRowSet->isNew( ORowSetBase::GrantNotifierAccess() ) )
1431 : )
1432 0 : m_pRowSet->fireProperty( PROPERTY_ID_ISNEW, false, true, ORowSetBase::GrantNotifierAccess() );
1433 :
1434 : #ifdef DBG_UTIL
1435 : m_bNotifyCalled = true;
1436 : #endif
1437 298 : }
1438 :
1439 24 : ::std::vector<sal_Int32>& ORowSetNotifier::getChangedColumns() const
1440 : {
1441 : OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1442 24 : return m_pImpl->aChangedColumns;
1443 : }
1444 :
1445 12 : void ORowSetNotifier::firePropertyChange()
1446 : {
1447 : OSL_ENSURE(m_pImpl.get(),"Illegal CTor call, use the other one!");
1448 12 : if( m_pImpl.get() )
1449 : {
1450 12 : ::std::vector<sal_Int32>::iterator aIter = m_pImpl->aChangedColumns.begin();
1451 24 : for(;aIter != m_pImpl->aChangedColumns.end();++aIter)
1452 : {
1453 12 : m_pRowSet->firePropertyChange((*aIter)-1 ,m_pImpl->aRow[(*aIter)-1], ORowSetBase::GrantNotifierAccess());
1454 : }
1455 12 : if ( !m_pImpl->aChangedColumns.empty() )
1456 12 : m_pRowSet->fireProperty(PROPERTY_ID_ISMODIFIED,true,false, ORowSetBase::GrantNotifierAccess());
1457 : }
1458 12 : }
1459 :
1460 : } // namespace dbaccess
1461 :
1462 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|