Branch data 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 : :
21 : : #include "BookmarkSet.hxx"
22 : : #include "CRowSetColumn.hxx"
23 : : #include "CRowSetDataColumn.hxx"
24 : : #include "KeySet.hxx"
25 : : #include "OptimisticSet.hxx"
26 : : #include "RowSetBase.hxx"
27 : : #include "RowSetCache.hxx"
28 : : #include "StaticSet.hxx"
29 : : #include "WrappedResultSet.hxx"
30 : : #include "core_resource.hrc"
31 : : #include "core_resource.hxx"
32 : : #include "dbastrings.hrc"
33 : :
34 : : #include <com/sun/star/sdbc/ColumnValue.hpp>
35 : : #include <com/sun/star/sdbc/ResultSetConcurrency.hpp>
36 : : #include <com/sun/star/sdbcx/CompareBookmark.hpp>
37 : : #include <com/sun/star/sdbcx/KeyType.hpp>
38 : : #include <com/sun/star/sdbcx/Privilege.hpp>
39 : : #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
40 : : #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
41 : : #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
42 : :
43 : : #include <comphelper/extract.hxx>
44 : : #include <comphelper/property.hxx>
45 : : #include <comphelper/seqstream.hxx>
46 : : #include <comphelper/uno3.hxx>
47 : : #include <connectivity/dbexception.hxx>
48 : : #include <connectivity/dbtools.hxx>
49 : : #include <connectivity/sqliterator.hxx>
50 : : #include <connectivity/sqlnode.hxx>
51 : : #include <connectivity/sqlparse.hxx>
52 : : #include <tools/debug.hxx>
53 : : #include <tools/diagnose_ex.h>
54 : : #include <osl/diagnose.h>
55 : :
56 : : #include <algorithm>
57 : :
58 : : using namespace dbaccess;
59 : : using namespace dbtools;
60 : : using namespace connectivity;
61 : : using namespace ::com::sun::star::uno;
62 : : using namespace ::com::sun::star::beans;
63 : : using namespace ::com::sun::star::sdbc;
64 : : using namespace ::com::sun::star::sdb;
65 : : using namespace ::com::sun::star::sdbcx;
66 : : using namespace ::com::sun::star::container;
67 : : using namespace ::com::sun::star::lang;
68 : : using namespace ::cppu;
69 : : using namespace ::osl;
70 : :
71 : : #define CHECK_MATRIX_POS(M) OSL_ENSURE(((M) >= static_cast<ORowSetMatrix::difference_type>(0)) && ((M) < static_cast<sal_Int32>(m_pMatrix->size())),"Position is invalid!")
72 : :
73 : : // This class calls m_pCacheSet->FOO_checked(..., sal_False)
74 : : // (where FOO is absolute, last, previous)
75 : : // when it does not immediately care about the values in the row's columns.
76 : : // As a corollary, m_pCacheSet may be left in an inconsistent state,
77 : : // and all ->fillFOO calls (and ->getFOO) may fail or give wrong results,
78 : : // until m_pCacheSet is moved (or refreshed) again.
79 : : // So always make sure m_pCacheSet is moved or refreshed before accessing column values.
80 : :
81 : : DBG_NAME(ORowSetCache)
82 : :
83 : 40 : ORowSetCache::ORowSetCache(const Reference< XResultSet >& _xRs,
84 : : const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
85 : : const ::comphelper::ComponentContext& _rContext,
86 : : const ::rtl::OUString& _rUpdateTableName,
87 : : sal_Bool& _bModified,
88 : : sal_Bool& _bNew,
89 : : const ORowSetValueVector& _aParameterValueForCache,
90 : : const ::rtl::OUString& i_sRowSetFilter,
91 : : sal_Int32 i_nMaxRows)
92 : : :m_xSet(_xRs)
93 [ + - ][ + - ]: 80 : ,m_xMetaData(Reference< XResultSetMetaDataSupplier >(_xRs,UNO_QUERY)->getMetaData())
94 : : ,m_aContext( _rContext )
95 : : ,m_pCacheSet(NULL)
96 : : ,m_pMatrix(NULL)
97 : : ,m_pInsertMatrix(NULL)
98 : : ,m_nLastColumnIndex(0)
99 : : ,m_nFetchSize(0)
100 : : ,m_nRowCount(0)
101 : : ,m_nPrivileges( Privilege::SELECT )
102 : : ,m_nPosition(0)
103 : : ,m_nStartPos(0)
104 : : ,m_nEndPos(0)
105 : : ,m_bRowCountFinal(sal_False)
106 : : ,m_bBeforeFirst(sal_True)
107 : : ,m_bAfterLast( sal_False )
108 : : ,m_bUpdated(sal_False)
109 : : ,m_bModified(_bModified)
110 [ + - ]: 120 : ,m_bNew(_bNew)
[ + - + - ]
[ + - ][ + - ]
111 : : {
112 : : DBG_CTOR(ORowSetCache,NULL);
113 : :
114 : : // first try if the result can be used to do inserts and updates
115 [ + - ]: 40 : Reference< XPropertySet> xProp(_xRs,UNO_QUERY);
116 [ + - ][ + - ]: 40 : Reference< XPropertySetInfo > xPropInfo = xProp->getPropertySetInfo();
117 : 40 : sal_Bool bBookmarkable = sal_False;
118 : : try
119 : : {
120 [ + - ]: 40 : Reference< XResultSetUpdate> xUp(_xRs,UNO_QUERY_THROW);
121 [ + - ][ + - ]: 80 : bBookmarkable = xPropInfo->hasPropertyByName(PROPERTY_ISBOOKMARKABLE) &&
[ + - ][ + - ]
[ # # ]
122 [ + - ][ + - ]: 40 : any2bool(xProp->getPropertyValue(PROPERTY_ISBOOKMARKABLE)) && Reference< XRowLocate >(_xRs, UNO_QUERY).is();
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ # #
# # # # ]
123 [ + - ]: 40 : if ( bBookmarkable )
124 : : {
125 [ + - ][ + - ]: 40 : xUp->moveToInsertRow();
126 [ + - ][ + - ]: 40 : xUp->cancelRowUpdates();
127 [ + - ][ + - ]: 40 : _xRs->beforeFirst();
128 : 40 : m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
129 [ + - ]: 40 : m_pCacheSet = new WrappedResultSet(i_nMaxRows);
130 [ + - ][ + - ]: 40 : m_xCacheSet = m_pCacheSet;
131 [ + - ]: 40 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
132 : : return;
133 [ - + ][ # # ]: 40 : }
134 : : }
135 [ # # ]: 0 : catch(const Exception& ex)
136 : : {
137 : : (void)ex;
138 : : }
139 : : try
140 : : {
141 [ # # ][ # # ]: 0 : if ( xPropInfo->hasPropertyByName(PROPERTY_RESULTSETTYPE) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # #
# # ]
142 [ # # ][ # # ]: 0 : ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETTYPE)) != ResultSetType::FORWARD_ONLY)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
143 [ # # ][ # # ]: 0 : _xRs->beforeFirst();
144 : : }
145 [ # # ]: 0 : catch(const SQLException& e)
146 : : {
147 : : (void)e;
148 : : }
149 : :
150 : : // check if all keys of the updateable table are fetched
151 : 0 : sal_Bool bAllKeysFound = sal_False;
152 : 0 : sal_Int32 nTablesCount = 0;
153 : :
154 [ # # ][ # # ]: 0 : sal_Bool bNeedKeySet = !bBookmarkable || (xPropInfo->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
[ # # ][ # # ]
[ # # ]
155 [ # # ][ # # ]: 0 : ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY);
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
156 : :
157 : 0 : Reference< XIndexAccess> xUpdateTableKeys;
158 : 0 : ::rtl::OUString aUpdateTableName = _rUpdateTableName;
159 : 0 : Reference< XConnection> xConnection;
160 : : // first we need a connection
161 [ # # ][ # # ]: 0 : Reference< XStatement> xStmt(_xRs->getStatement(),UNO_QUERY);
[ # # ]
162 [ # # ]: 0 : if(xStmt.is())
163 [ # # ][ # # ]: 0 : xConnection = xStmt->getConnection();
[ # # ]
164 : : else
165 : : {
166 [ # # ][ # # ]: 0 : Reference< XPreparedStatement> xPrepStmt(_xRs->getStatement(),UNO_QUERY);
[ # # ]
167 [ # # ][ # # ]: 0 : xConnection = xPrepStmt->getConnection();
[ # # ]
168 : : }
169 : : OSL_ENSURE(xConnection.is(),"No connection!");
170 [ # # ]: 0 : if(_xAnalyzer.is())
171 : : {
172 : : try
173 : : {
174 [ # # ]: 0 : Reference<XTablesSupplier> xTabSup(_xAnalyzer,UNO_QUERY);
175 : : OSL_ENSURE(xTabSup.is(),"ORowSet::execute composer isn't a tablesupplier!");
176 [ # # ][ # # ]: 0 : Reference<XNameAccess> xTables = xTabSup->getTables();
177 [ # # ][ # # ]: 0 : Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames();
178 [ # # ][ # # ]: 0 : if ( aTableNames.getLength() > 1 && _rUpdateTableName.isEmpty() && bNeedKeySet )
[ # # ][ # # ]
179 : : {// here we have a join or union and nobody told us which table to update, so we update them all
180 : 0 : m_nPrivileges = Privilege::SELECT|Privilege::DELETE|Privilege::INSERT|Privilege::UPDATE;
181 [ # # # # ]: 0 : OptimisticSet* pCursor = new OptimisticSet(m_aContext,xConnection,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
182 : 0 : m_pCacheSet = pCursor;
183 [ # # ][ # # ]: 0 : m_xCacheSet = m_pCacheSet;
184 : : try
185 : : {
186 [ # # ]: 0 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
187 [ # # ]: 0 : if ( pCursor->isReadOnly() )
188 : 0 : m_nPrivileges = Privilege::SELECT;
189 [ # # ]: 0 : m_aKeyColumns = pCursor->getJoinedKeyColumns();
190 : : return;
191 : : }
192 [ # # ]: 0 : catch(const Exception&)
193 : : {
194 : : }
195 : 0 : m_pCacheSet = NULL;
196 : 0 : m_xCacheSet.clear();
197 : : }
198 : : else
199 : : {
200 [ # # ][ # # ]: 0 : if(!_rUpdateTableName.isEmpty() && xTables->hasByName(_rUpdateTableName))
[ # # ][ # # ]
[ # # ]
201 [ # # ][ # # ]: 0 : xTables->getByName(_rUpdateTableName) >>= m_aUpdateTable;
[ # # ]
202 [ # # ][ # # ]: 0 : else if(xTables->getElementNames().getLength())
[ # # ][ # # ]
203 : : {
204 [ # # ][ # # ]: 0 : aUpdateTableName = xTables->getElementNames()[0];
[ # # ][ # # ]
205 [ # # ][ # # ]: 0 : xTables->getByName(aUpdateTableName) >>= m_aUpdateTable;
[ # # ]
206 : : }
207 [ # # ]: 0 : Reference<XIndexAccess> xIndexAccess(xTables,UNO_QUERY);
208 [ # # ]: 0 : if(xIndexAccess.is())
209 [ # # ][ # # ]: 0 : nTablesCount = xIndexAccess->getCount();
210 : : else
211 [ # # ][ # # ]: 0 : nTablesCount = xTables->getElementNames().getLength();
[ # # ]
212 : :
213 [ # # ][ # # ]: 0 : if(m_aUpdateTable.is() && nTablesCount < 3) // for we can't handle more than 2 tables in our keyset
[ # # ]
214 : : {
215 [ # # ]: 0 : Reference<XPropertySet> xSet(m_aUpdateTable,UNO_QUERY);
216 [ # # ]: 0 : const Reference<XNameAccess> xPrimaryKeyColumns = dbtools::getPrimaryKeyColumns_throw(xSet);
217 [ # # ]: 0 : if ( xPrimaryKeyColumns.is() )
218 : : {
219 [ # # ]: 0 : Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
220 [ # # ]: 0 : if ( xColSup.is() )
221 : : {
222 [ # # ][ # # ]: 0 : Reference<XNameAccess> xSelColumns = xColSup->getColumns();
223 [ # # ][ # # ]: 0 : Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
224 [ # # ][ # # ]: 0 : SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false);
[ # # ][ # # ]
[ # # ]
225 [ # # ][ # # ]: 0 : ::dbaccess::getColumnPositions(xSelColumns,xPrimaryKeyColumns->getElementNames(),aUpdateTableName,aColumnNames);
[ # # ][ # # ]
226 [ # # ][ # # ]: 0 : bAllKeysFound = !aColumnNames.empty() && sal_Int32(aColumnNames.size()) == xPrimaryKeyColumns->getElementNames().getLength();
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
227 : 0 : }
228 : 0 : }
229 : 0 : }
230 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ]
231 : : }
232 [ # # ]: 0 : catch(Exception&)
233 : : {
234 : : }
235 : : }
236 : :
237 : : // first check if resultset is bookmarkable
238 [ # # ]: 0 : if(!bNeedKeySet)
239 : : {
240 : : try
241 : : {
242 [ # # ]: 0 : m_pCacheSet = new OBookmarkSet(i_nMaxRows);
243 [ # # ][ # # ]: 0 : m_xCacheSet = m_pCacheSet;
244 [ # # ]: 0 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
245 : :
246 : : // check privileges
247 : 0 : m_nPrivileges = Privilege::SELECT;
248 [ # # ][ # # ]: 0 : if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it
249 : : {
250 [ # # ]: 0 : Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
251 [ # # ][ # # ]: 0 : if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
252 : : {
253 : 0 : m_nPrivileges = 0;
254 [ # # ][ # # ]: 0 : xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
[ # # ]
255 [ # # ]: 0 : if(!m_nPrivileges)
256 : 0 : m_nPrivileges = Privilege::SELECT;
257 [ # # ]: 0 : }
258 : : }
259 : : }
260 [ # # ]: 0 : catch(const SQLException&)
261 : : {
262 : 0 : bNeedKeySet = sal_True;
263 : : }
264 : :
265 : : }
266 [ # # ]: 0 : if(bNeedKeySet)
267 : : {
268 : : // need to check if we could handle this select clause
269 [ # # ][ # # ]: 0 : bAllKeysFound = bAllKeysFound && (nTablesCount == 1 || checkJoin(xConnection,_xAnalyzer,aUpdateTableName));
[ # # ][ # # ]
270 : :
271 [ # # ]: 0 : if(!bAllKeysFound )
272 : : {
273 [ # # ]: 0 : if ( bBookmarkable )
274 : : {
275 : : // here I know that we have a read only bookmarkable cursor
276 [ # # ][ # # ]: 0 : _xRs->beforeFirst();
277 : 0 : m_nPrivileges = Privilege::SELECT;
278 [ # # ]: 0 : m_pCacheSet = new WrappedResultSet(i_nMaxRows);
279 [ # # ][ # # ]: 0 : m_xCacheSet = m_pCacheSet;
280 [ # # ]: 0 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
281 : : return;
282 : : }
283 [ # # ]: 0 : m_pCacheSet = new OStaticSet(i_nMaxRows);
284 [ # # ][ # # ]: 0 : m_xCacheSet = m_pCacheSet;
285 [ # # ]: 0 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
286 : 0 : m_nPrivileges = Privilege::SELECT;
287 : : }
288 : : else
289 : : {
290 [ # # ][ # # ]: 0 : Reference<XDatabaseMetaData> xMeta = xConnection->getMetaData();
291 [ # # ][ # # ]: 0 : SelectColumnsMetaData aColumnNames(xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers() ? true : false);
[ # # ][ # # ]
[ # # ]
292 [ # # ]: 0 : Reference<XColumnsSupplier> xColSup(_xAnalyzer,UNO_QUERY);
293 [ # # ][ # # ]: 0 : Reference<XNameAccess> xSelColumns = xColSup->getColumns();
294 [ # # ][ # # ]: 0 : Reference<XNameAccess> xColumns = m_aUpdateTable->getColumns();
295 [ # # ][ # # ]: 0 : ::dbaccess::getColumnPositions(xSelColumns,xColumns->getElementNames(),aUpdateTableName,aColumnNames);
[ # # ][ # # ]
296 : :
297 : : // check privileges
298 : 0 : m_nPrivileges = Privilege::SELECT;
299 : 0 : sal_Bool bNoInsert = sal_False;
300 : :
301 [ # # ][ # # ]: 0 : Sequence< ::rtl::OUString> aNames(xColumns->getElementNames());
302 : 0 : const ::rtl::OUString* pIter = aNames.getConstArray();
303 : 0 : const ::rtl::OUString* pEnd = pIter + aNames.getLength();
304 [ # # ]: 0 : for(;pIter != pEnd;++pIter)
305 : : {
306 [ # # ][ # # ]: 0 : Reference<XPropertySet> xColumn(xColumns->getByName(*pIter),UNO_QUERY);
[ # # ]
307 : : OSL_ENSURE(xColumn.is(),"Column in table is null!");
308 [ # # ]: 0 : if(xColumn.is())
309 : : {
310 : 0 : sal_Int32 nNullable = 0;
311 [ # # ][ # # ]: 0 : xColumn->getPropertyValue(PROPERTY_ISNULLABLE) >>= nNullable;
[ # # ]
312 [ # # ][ # # ]: 0 : if(nNullable == ColumnValue::NO_NULLS && aColumnNames.find(*pIter) == aColumnNames.end())
[ # # ][ # # ]
[ # # # #
# # ][ # # ]
313 : : { // we found a column where null is not allowed so we can't insert new values
314 : 0 : bNoInsert = sal_True;
315 : : break; // one column is enough
316 : : }
317 : : }
318 [ # # ]: 0 : }
319 : :
320 [ # # ]: 0 : OKeySet* pKeySet = new OKeySet(m_aUpdateTable,xUpdateTableKeys,aUpdateTableName ,_xAnalyzer,_aParameterValueForCache,i_nMaxRows,m_nRowCount);
321 : : try
322 : : {
323 : 0 : m_pCacheSet = pKeySet;
324 [ # # ][ # # ]: 0 : m_xCacheSet = m_pCacheSet;
325 [ # # ]: 0 : pKeySet->construct(_xRs,i_sRowSetFilter);
326 : :
327 [ # # ][ # # ]: 0 : if(Reference<XResultSetUpdate>(_xRs,UNO_QUERY).is()) // this interface is optional so we have to check it
328 : : {
329 [ # # ]: 0 : Reference<XPropertySet> xTable(m_aUpdateTable,UNO_QUERY);
330 [ # # ][ # # ]: 0 : if(xTable.is() && xTable->getPropertySetInfo()->hasPropertyByName(PROPERTY_PRIVILEGES))
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # #
# # # # ]
331 : : {
332 : 0 : m_nPrivileges = 0;
333 [ # # ][ # # ]: 0 : xTable->getPropertyValue(PROPERTY_PRIVILEGES) >>= m_nPrivileges;
[ # # ]
334 [ # # ]: 0 : if(!m_nPrivileges)
335 : 0 : m_nPrivileges = Privilege::SELECT;
336 : 0 : }
337 : : }
338 [ # # ]: 0 : if(bNoInsert)
339 : 0 : m_nPrivileges |= ~Privilege::INSERT; // remove the insert privilege
340 : : }
341 [ # # # # ]: 0 : catch(const SQLException&)
342 : : {
343 : : // we couldn't create a keyset here so we have to create a static cache
344 [ # # ]: 0 : if ( m_pCacheSet )
345 : 0 : m_pCacheSet = NULL;
346 [ # # ]: 0 : m_xCacheSet = NULL;
347 [ # # ]: 0 : m_pCacheSet = new OStaticSet(i_nMaxRows);
348 [ # # # # ]: 0 : m_xCacheSet = m_pCacheSet;
349 [ # # ]: 0 : m_pCacheSet->construct(_xRs,i_sRowSetFilter);
350 : 0 : m_nPrivileges = Privilege::SELECT;
351 [ # # ]: 0 : }
352 : : }
353 : :
354 : : }
355 : : // last check
356 [ # # ][ # # ]: 0 : if(!bAllKeysFound && xProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_RESULTSETCONCURRENCY) &&
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # #
# # ]
357 [ # # ][ # # ]: 0 : ::comphelper::getINT32(xProp->getPropertyValue(PROPERTY_RESULTSETCONCURRENCY)) == ResultSetConcurrency::READ_ONLY)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # # # ]
358 [ # # ][ # # ]: 40 : m_nPrivileges = Privilege::SELECT;
[ # # ][ # # ]
[ + - ][ - + ]
359 : : }
360 : :
361 [ + - ][ + - ]: 40 : ORowSetCache::~ORowSetCache()
362 : : {
363 : 40 : m_pCacheSet = NULL;
364 [ + - ]: 40 : m_xCacheSet = NULL;
365 [ + - ]: 40 : if(m_pMatrix)
366 : : {
367 : 40 : m_pMatrix->clear();
368 [ + - ]: 40 : delete m_pMatrix;
369 : : }
370 : :
371 [ + - ]: 40 : if(m_pInsertMatrix)
372 : : {
373 : 40 : m_pInsertMatrix->clear();
374 [ + - ]: 40 : delete m_pInsertMatrix;
375 : : }
376 [ + - ][ + - ]: 40 : m_xSet = WeakReference< XResultSet>();
[ + - ]
377 [ + - ]: 40 : m_xMetaData = NULL;
378 [ + - ]: 40 : m_aUpdateTable = NULL;
379 : :
380 : : DBG_DTOR(ORowSetCache,NULL);
381 : 40 : }
382 : :
383 : 46 : void ORowSetCache::setFetchSize(sal_Int32 _nSize)
384 : : {
385 [ - + ]: 46 : if(_nSize == m_nFetchSize)
386 : 46 : return;
387 : :
388 : 46 : m_nFetchSize = _nSize;
389 [ + + ]: 46 : if(!m_pMatrix)
390 : : {
391 [ + - ]: 40 : m_pMatrix = new ORowSetMatrix(_nSize);
392 : 40 : m_aMatrixIter = m_pMatrix->end();
393 : 40 : m_aMatrixEnd = m_pMatrix->end();
394 : :
395 [ + - ]: 40 : m_pInsertMatrix = new ORowSetMatrix(1); // a little bit overkill but ??? :-)
396 : 40 : m_aInsertRow = m_pInsertMatrix->end();
397 : : }
398 : : else
399 : : {
400 : : // now correct the iterator in our iterator vector
401 [ + - ]: 6 : ::std::vector<sal_Int32> aPositions;
402 [ + - ]: 6 : ::std::map<sal_Int32,sal_Bool> aCacheIterToChange;
403 : : // first get the positions where they stand now
404 : 6 : ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
405 : 6 : ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end();
406 [ + + ]: 12 : for(;aCacheIter != aCacheEnd;++aCacheIter)
407 : : {
408 [ + - ]: 6 : aCacheIterToChange[aCacheIter->first] = sal_False;
409 [ + - ][ + + ]: 6 : if ( !aCacheIter->second.pRowSet->isInsertRow()
[ + + ]
410 : 6 : /*&& aCacheIter->second.aIterator != m_pMatrix->end()*/ && !m_bModified )
411 : : {
412 [ + - ]: 4 : ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
413 [ + - ]: 4 : aPositions.push_back(nDist);
414 [ + - ]: 4 : aCacheIterToChange[aCacheIter->first] = sal_True;
415 : : }
416 : : }
417 [ + - ]: 6 : sal_Int32 nKeyPos = (m_aMatrixIter - m_pMatrix->begin());
418 [ + - ]: 6 : m_pMatrix->resize(_nSize);
419 : :
420 [ + - ]: 6 : if ( nKeyPos < _nSize )
421 [ + - ]: 6 : m_aMatrixIter = m_pMatrix->begin() + nKeyPos;
422 : : else
423 : 0 : m_aMatrixIter = m_pMatrix->end();
424 : 6 : m_aMatrixEnd = m_pMatrix->end();
425 : :
426 : : // now adjust their positions because a resize invalidates all iterators
427 [ + - ]: 6 : ::std::vector<sal_Int32>::const_iterator aIter = aPositions.begin();
428 [ + - ]: 6 : ::std::map<sal_Int32,sal_Bool>::const_iterator aPosChangeIter = aCacheIterToChange.begin();
429 [ + - ][ + - ]: 24 : for( aCacheIter = m_aCacheIterators.begin();
[ + + ]
430 [ + - ]: 12 : aPosChangeIter != aCacheIterToChange.end();
431 : : ++aPosChangeIter,++aCacheIter)
432 : : {
433 [ + - ][ + + ]: 6 : if ( aPosChangeIter->second )
434 : : {
435 : : CHECK_MATRIX_POS(*aIter);
436 [ + - ][ + - ]: 4 : if ( *aIter < _nSize )
437 [ + - ][ + - ]: 4 : aCacheIter->second.aIterator = m_pMatrix->begin() + *aIter++;
[ + - ]
438 : : else
439 : 0 : aCacheIter->second.aIterator = m_pMatrix->end();
440 : : }
441 : 6 : }
442 : : }
443 [ + + ]: 46 : if(!m_nPosition)
444 : : {
445 : 40 : sal_Int32 nNewSt = 0;
446 [ + - ]: 40 : fillMatrix(nNewSt,_nSize);
447 : : OSL_ENSURE(nNewSt == 0, "fillMatrix set new start to unexpected value");
448 : 40 : m_nStartPos = 0;
449 : 40 : m_nEndPos = _nSize;
450 : : }
451 [ + - ][ + - ]: 6 : else if (m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos)
452 : : {
453 : 6 : sal_Int32 nNewSt = -1;
454 : 6 : _nSize += m_nStartPos;
455 [ + - ]: 6 : fillMatrix(nNewSt, _nSize);
456 [ + - ]: 6 : if (nNewSt >= 0)
457 : : {
458 : 6 : m_nStartPos = nNewSt;
459 : 6 : m_nEndPos = _nSize;
460 [ + - ]: 6 : m_aMatrixIter = calcPosition();
461 : : }
462 : : else
463 : : {
464 : 0 : m_nEndPos = m_nStartPos + m_nFetchSize;
465 : 6 : }
466 : : }
467 : : else
468 : : {
469 : : OSL_FAIL("m_nPosition not between m_nStartPos and m_nEndpos");
470 : : // try to repair
471 : 0 : moveWindow();
472 : 0 : m_aMatrixIter = calcPosition();
473 : : }
474 : : }
475 : :
476 : : // XResultSetMetaDataSupplier
477 : 572 : Reference< XResultSetMetaData > ORowSetCache::getMetaData( )
478 : : {
479 : 572 : return m_xMetaData;
480 : : }
481 : :
482 : 272 : Any lcl_getBookmark(ORowSetValue& i_aValue,OCacheSet* i_pCacheSet)
483 : : {
484 [ - + ]: 272 : switch ( i_aValue.getTypeKind() )
485 : : {
486 : : case DataType::TINYINT:
487 : : case DataType::SMALLINT:
488 : : case DataType::INTEGER:
489 [ # # ]: 0 : return makeAny((sal_Int32)i_aValue);
490 : : default:
491 [ + - ][ - + ]: 272 : if ( i_pCacheSet && i_aValue.isNull())
[ - + ]
492 [ # # ]: 0 : i_aValue = i_pCacheSet->getBookmark();
493 : 272 : return i_aValue.getAny();
494 : : }
495 : : }
496 : :
497 : : // ::com::sun::star::sdbcx::XRowLocate
498 : 272 : Any ORowSetCache::getBookmark( )
499 : : {
500 [ - + ]: 272 : if(m_bAfterLast)
501 [ # # ][ # # ]: 0 : throwFunctionSequenceException(m_xSet.get());
502 : :
503 [ + - ][ + - ]: 272 : if ( m_aMatrixIter >= m_pMatrix->end() || m_aMatrixIter < m_pMatrix->begin() || !(*m_aMatrixIter).is())
[ + - ][ + - ]
[ - + ][ + - ]
[ + - ][ - +
# # # # ]
504 : : {
505 : 0 : return Any(); // this is allowed here because the rowset knowns what it is doing
506 : : }
507 : :
508 : 272 : return lcl_getBookmark(((*m_aMatrixIter)->get())[0],m_pCacheSet);
509 : : }
510 : :
511 : 398 : sal_Bool ORowSetCache::moveToBookmark( const Any& bookmark )
512 : : {
513 [ + - ]: 398 : if ( m_pCacheSet->moveToBookmark(bookmark) )
514 : : {
515 : 398 : m_bBeforeFirst = sal_False;
516 : 398 : m_nPosition = m_pCacheSet->getRow();
517 : :
518 : 398 : checkPositionFlags();
519 : :
520 [ + - ]: 398 : if(!m_bAfterLast)
521 : : {
522 : 398 : moveWindow();
523 : 398 : checkPositionFlags();
524 [ + - ]: 398 : if ( !m_bAfterLast )
525 : : {
526 : 398 : m_aMatrixIter = calcPosition();
527 : : OSL_ENSURE(m_aMatrixIter->is(),"Iterator after moveToBookmark not valid");
528 : : }
529 : : else
530 : 0 : m_aMatrixIter = m_pMatrix->end();
531 : : }
532 : : else
533 : 0 : m_aMatrixIter = m_pMatrix->end();
534 : : }
535 : : else
536 : 0 : return sal_False;
537 : :
538 [ + - ][ + - ]: 398 : return m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
[ + - ][ + - ]
[ # # ]
539 : : }
540 : :
541 : 2 : sal_Bool ORowSetCache::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows )
542 : : {
543 : 2 : sal_Bool bRet( moveToBookmark( bookmark ) );
544 [ + - ]: 2 : if ( bRet )
545 : : {
546 : 2 : m_nPosition = m_pCacheSet->getRow() + rows;
547 : 2 : absolute(m_nPosition);
548 : :
549 [ + - ][ + - ]: 2 : bRet = m_aMatrixIter != m_pMatrix->end() && (*m_aMatrixIter).is();
[ + - ][ # # ]
[ + - ]
550 : : }
551 : :
552 : 2 : return bRet;
553 : : }
554 : :
555 : 68 : sal_Int32 ORowSetCache::compareBookmarks( const Any& _first, const Any& _second )
556 : : {
557 [ + - ][ + - ]: 68 : return (!_first.hasValue() || !_second.hasValue()) ? CompareBookmark::NOT_COMPARABLE : m_pCacheSet->compareBookmarks(_first,_second);
558 : : }
559 : :
560 : 2 : sal_Bool ORowSetCache::hasOrderedBookmarks( )
561 : : {
562 : 2 : return m_pCacheSet->hasOrderedBookmarks();
563 : : }
564 : :
565 : 4 : sal_Int32 ORowSetCache::hashBookmark( const Any& bookmark )
566 : : {
567 : 4 : return m_pCacheSet->hashBookmark(bookmark);
568 : : }
569 : :
570 : : // XRowUpdate
571 : 0 : void ORowSetCache::updateNull(sal_Int32 columnIndex,ORowSetValueVector::Vector& io_aRow
572 : : ,::std::vector<sal_Int32>& o_ChangedColumns
573 : : )
574 : : {
575 : 0 : checkUpdateConditions(columnIndex);
576 : :
577 : 0 : ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
578 [ # # ]: 0 : if ( !rInsert[columnIndex].isNull() )
579 : : {
580 : 0 : rInsert[columnIndex].setBound(sal_True);
581 : 0 : rInsert[columnIndex].setNull();
582 : 0 : rInsert[columnIndex].setModified();
583 : 0 : io_aRow[columnIndex].setNull();
584 : :
585 : 0 : m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
586 : 0 : impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
587 : : }
588 : 0 : }
589 : :
590 : 12 : void ORowSetCache::updateValue(sal_Int32 columnIndex,const ORowSetValue& x
591 : : ,ORowSetValueVector::Vector& io_aRow
592 : : ,::std::vector<sal_Int32>& o_ChangedColumns
593 : : )
594 : : {
595 : 12 : checkUpdateConditions(columnIndex);
596 : :
597 : 12 : ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
598 [ + - ]: 12 : if ( rInsert[columnIndex] != x )
599 : : {
600 : 12 : rInsert[columnIndex].setBound(sal_True);
601 : 12 : rInsert[columnIndex] = x;
602 : 12 : rInsert[columnIndex].setModified();
603 : 12 : io_aRow[columnIndex] = rInsert[columnIndex];
604 : :
605 : 12 : m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
606 : 12 : impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
607 : : }
608 : 12 : }
609 : :
610 : 0 : void ORowSetCache::updateCharacterStream( sal_Int32 columnIndex, const Reference< ::com::sun::star::io::XInputStream >& x
611 : : , sal_Int32 length,ORowSetValueVector::Vector& io_aRow
612 : : ,::std::vector<sal_Int32>& o_ChangedColumns
613 : : )
614 : : {
615 [ # # ]: 0 : checkUpdateConditions(columnIndex);
616 : :
617 [ # # ]: 0 : Sequence<sal_Int8> aSeq;
618 [ # # ]: 0 : if(x.is())
619 [ # # ][ # # ]: 0 : x->readBytes(aSeq,length);
620 : :
621 : 0 : ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
622 [ # # ]: 0 : rInsert[columnIndex].setBound(sal_True);
623 [ # # ][ # # ]: 0 : rInsert[columnIndex] = aSeq;
624 [ # # ]: 0 : rInsert[columnIndex].setModified();
625 [ # # ][ # # ]: 0 : io_aRow[columnIndex] = makeAny(x);
[ # # ]
626 : :
627 [ # # ]: 0 : m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
628 [ # # ][ # # ]: 0 : impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
629 : 0 : }
630 : :
631 : 0 : void ORowSetCache::updateObject( sal_Int32 columnIndex, const Any& x
632 : : ,ORowSetValueVector::Vector& io_aRow
633 : : ,::std::vector<sal_Int32>& o_ChangedColumns
634 : : )
635 : : {
636 [ # # ]: 0 : checkUpdateConditions(columnIndex);
637 : :
638 : 0 : ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
639 : 0 : ORowSetValue aTemp;
640 [ # # ]: 0 : aTemp.fill(x);
641 [ # # ][ # # ]: 0 : if ( rInsert[columnIndex] != aTemp )
[ # # ]
642 : : {
643 [ # # ]: 0 : rInsert[columnIndex].setBound(sal_True);
644 [ # # ][ # # ]: 0 : rInsert[columnIndex] = aTemp;
645 [ # # ]: 0 : rInsert[columnIndex].setModified();
646 [ # # ][ # # ]: 0 : io_aRow[columnIndex] = rInsert[columnIndex];
[ # # ]
647 : :
648 [ # # ]: 0 : m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
649 [ # # ]: 0 : impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
650 [ # # ]: 0 : }
651 : 0 : }
652 : :
653 : 0 : void ORowSetCache::updateNumericObject( sal_Int32 columnIndex, const Any& x, sal_Int32 /*scale*/
654 : : ,ORowSetValueVector::Vector& io_aRow
655 : : ,::std::vector<sal_Int32>& o_ChangedColumns
656 : : )
657 : : {
658 [ # # ]: 0 : checkUpdateConditions(columnIndex);
659 : :
660 : 0 : ORowSetValueVector::Vector& rInsert = ((*m_aInsertRow)->get());
661 : 0 : ORowSetValue aTemp;
662 [ # # ]: 0 : aTemp.fill(x);
663 [ # # ][ # # ]: 0 : if ( rInsert[columnIndex] != aTemp )
[ # # ]
664 : : {
665 [ # # ]: 0 : rInsert[columnIndex].setBound(sal_True);
666 [ # # ][ # # ]: 0 : rInsert[columnIndex] = aTemp;
667 [ # # ]: 0 : rInsert[columnIndex].setModified();
668 [ # # ][ # # ]: 0 : io_aRow[columnIndex] = rInsert[columnIndex];
[ # # ]
669 : :
670 [ # # ]: 0 : m_pCacheSet->mergeColumnValues(columnIndex,rInsert,io_aRow,o_ChangedColumns);
671 [ # # ]: 0 : impl_updateRowFromCache_throw(io_aRow,o_ChangedColumns);
672 [ # # ]: 0 : }
673 : 0 : }
674 : :
675 : : // XResultSet
676 : 132 : sal_Bool ORowSetCache::next( )
677 : : {
678 [ + - ]: 132 : if(!isAfterLast())
679 : : {
680 : 132 : m_bBeforeFirst = sal_False;
681 : 132 : ++m_nPosition;
682 : :
683 : : // after we increment the position we have to check if we are already after the last row
684 : 132 : checkPositionFlags();
685 [ + + ]: 132 : if(!m_bAfterLast)
686 : : {
687 : 124 : moveWindow();
688 : :
689 : : OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
690 : 124 : m_aMatrixIter = calcPosition();
691 : 124 : checkPositionFlags();
692 : : }
693 : : }
694 : :
695 : 132 : return !m_bAfterLast;
696 : : }
697 : :
698 : 382 : sal_Bool ORowSetCache::isBeforeFirst( )
699 : : {
700 : 382 : return m_bBeforeFirst;
701 : : }
702 : :
703 : 654 : sal_Bool ORowSetCache::isAfterLast( )
704 : : {
705 : 654 : return m_bAfterLast;
706 : : }
707 : :
708 : 18 : sal_Bool ORowSetCache::isFirst( )
709 : : {
710 : 18 : return m_nPosition == 1; // ask resultset for
711 : : }
712 : :
713 : 4 : sal_Bool ORowSetCache::isLast( )
714 : : {
715 : 4 : return m_nPosition == m_nRowCount;
716 : : }
717 : :
718 : 18 : sal_Bool ORowSetCache::beforeFirst( )
719 : : {
720 [ + + ]: 18 : if(!m_bBeforeFirst)
721 : : {
722 : 8 : m_bAfterLast = sal_False;
723 : 8 : m_nPosition = 0;
724 : 8 : m_bBeforeFirst = sal_True;
725 : 8 : m_pCacheSet->beforeFirst();
726 : 8 : moveWindow();
727 : 8 : m_aMatrixIter = m_pMatrix->end();
728 : : }
729 : 18 : return sal_True;
730 : : }
731 : :
732 : 10 : sal_Bool ORowSetCache::afterLast( )
733 : : {
734 [ + - ]: 10 : if(!m_bAfterLast)
735 : : {
736 : 10 : m_bBeforeFirst = sal_False;
737 : 10 : m_bAfterLast = sal_True;
738 : :
739 [ - + ]: 10 : if(!m_bRowCountFinal)
740 : : {
741 : 0 : m_pCacheSet->last_checked(sal_False);
742 : 0 : m_bRowCountFinal = sal_True;
743 : 0 : m_nRowCount = m_pCacheSet->getRow();// + 1 removed
744 : : }
745 : 10 : m_pCacheSet->afterLast();
746 : :
747 : 10 : m_nPosition = 0;
748 : 10 : m_aMatrixIter = m_pMatrix->end();
749 : : }
750 : 10 : return sal_True;
751 : : }
752 : :
753 : 46 : sal_Bool ORowSetCache::fillMatrix(sal_Int32& _nNewStartPos, sal_Int32 &_nNewEndPos)
754 : : {
755 : : OSL_ENSURE(_nNewStartPos != _nNewEndPos,"ORowSetCache::fillMatrix: StartPos and EndPos can not be equal!");
756 : : // If _nNewStartPos >= 0, then fill the whole window with new data
757 : : // Else if _nNewStartPos == -1, then fill only segment [m_nEndPos, _nNewEndPos)
758 : : // Else, undefined (invalid argument)
759 : : OSL_ENSURE( _nNewStartPos >= -1, "ORowSetCache::fillMatrix: invalid _nNewStartPos" );
760 : :
761 : 46 : ORowSetMatrix::iterator aIter;
762 : : sal_Int32 i;
763 : : sal_Bool bCheck;
764 : : sal_Int32 requestedStartPos;
765 [ + + ]: 46 : if ( _nNewStartPos == -1 )
766 : : {
767 [ + - ]: 6 : aIter = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
768 : 6 : i = m_nEndPos + 1;
769 : 6 : requestedStartPos = m_nStartPos;
770 : : }
771 : : else
772 : : {
773 : 40 : aIter = m_pMatrix->begin();
774 : 40 : i = _nNewStartPos + 1;
775 : 40 : requestedStartPos = _nNewStartPos;
776 : : }
777 [ + - ]: 46 : bCheck = m_pCacheSet->absolute(i);
778 : :
779 : :
780 [ + - ]: 340 : for(; i <= _nNewEndPos; ++i,++aIter)
781 : : {
782 [ + + ]: 340 : if(bCheck)
783 : : {
784 [ + - ]: 294 : if(!aIter->is())
785 [ + - ][ + - ]: 294 : *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ + - ][ + - ]
786 [ + - ]: 294 : m_pCacheSet->fillValueRow(*aIter,i);
787 : : }
788 : : else
789 : : { // there are no more rows found so we can fetch some before start
790 : :
791 [ + + ]: 46 : if(!m_bRowCountFinal)
792 : : {
793 [ + - ][ + + ]: 40 : if(m_pCacheSet->previous_checked(sal_False)) // because we stand after the last row
794 [ + - ]: 34 : m_nRowCount = m_pCacheSet->getRow(); // here we have the row count
795 [ + + ]: 40 : if(!m_nRowCount)
796 : 6 : m_nRowCount = i-1; // it can be that getRow return zero
797 : 40 : m_bRowCountFinal = sal_True;
798 : : }
799 : 46 : const ORowSetMatrix::iterator aEnd = aIter;
800 : 46 : ORowSetMatrix::iterator aRealEnd = m_pMatrix->end();
801 : : sal_Int32 nPos;
802 [ - + ]: 46 : if (m_nRowCount >= m_nFetchSize)
803 : : {
804 : 0 : nPos = m_nRowCount - m_nFetchSize;
805 : : }
806 : : else
807 : : {
808 : 46 : nPos = 0;
809 : : }
810 : 46 : _nNewStartPos = nPos;
811 : 46 : _nNewEndPos = m_nRowCount;
812 : 46 : ++nPos;
813 [ + - ]: 46 : bCheck = m_pCacheSet->absolute(nPos);
814 : :
815 [ + + ][ - + ]: 46 : for(;bCheck && nPos <= requestedStartPos && aIter != aRealEnd; ++aIter, ++nPos)
[ # # ][ # # ]
[ - + ]
816 : : {
817 [ # # ]: 0 : if(!aIter->is())
818 [ # # ][ # # ]: 0 : *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ # # ][ # # ]
819 [ # # ]: 0 : m_pCacheSet->fillValueRow(*aIter, nPos);
820 [ # # ]: 0 : bCheck = m_pCacheSet->next();
821 : : }
822 [ + - ][ - + ]: 46 : if(aIter != aEnd)
823 [ # # ]: 46 : ::std::rotate(m_pMatrix->begin(),aEnd,aIter);
824 : : break;
825 : : }
826 [ + - ]: 294 : bCheck = m_pCacheSet->next();
827 : : }
828 : : // we have to read one row forward to ensure that we know when we are on last row
829 : : // but only when we don't know it already
830 [ - + ]: 46 : if(!m_bRowCountFinal)
831 : : {
832 [ # # ][ # # ]: 0 : if(!m_pCacheSet->next())
833 : : {
834 [ # # ][ # # ]: 0 : if(m_pCacheSet->previous_checked(sal_False)) // because we stand after the last row
835 [ # # ]: 0 : m_nRowCount = m_pCacheSet->getRow(); // here we have the row count
836 : 0 : m_bRowCountFinal = sal_True;
837 : : }
838 : : else
839 [ # # ]: 0 : m_nRowCount = std::max(i,m_nRowCount);
840 : :
841 : : }
842 : 46 : return bCheck;
843 : : }
844 : :
845 : : // If m_nPosition is out of the current window,
846 : : // move it and update m_nStartPos and m_nEndPos
847 : : // Caller is responsible for updating m_aMatrixIter
848 : 606 : sal_Bool ORowSetCache::moveWindow()
849 : : {
850 : : OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
851 : : OSL_ENSURE(m_nEndPos >= m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
852 : : OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
853 : :
854 [ + + ][ + + ]: 606 : if ( m_nStartPos < m_nPosition && m_nPosition <= m_nEndPos )
855 : : {
856 : : // just move inside the window
857 : : OSL_ENSURE((m_nPosition - m_nStartPos) <= (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
858 : : // make double plus sure that we have fetched that row
859 [ + - ]: 596 : m_aMatrixIter = calcPosition();
860 : : OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(), "New m_aMatrixIter is at end(), but should not.");
861 [ + + ]: 596 : if(!m_aMatrixIter->is())
862 : : {
863 [ + - ]: 8 : sal_Bool bOk( m_pCacheSet->absolute( m_nPosition ) );
864 [ + - ]: 8 : if ( bOk )
865 : : {
866 [ + - ][ + - ]: 8 : *m_aMatrixIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ + - ][ + - ]
867 [ + - ]: 8 : m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
868 : : // we have to read one row forward to ensure that we know when we are on last row
869 : : // but only when we don't know it already
870 [ - + ]: 8 : if ( !m_bRowCountFinal )
871 : : {
872 [ # # ]: 0 : bOk = m_pCacheSet->absolute_checked( m_nPosition + 1,sal_False );
873 [ # # ]: 0 : if ( bOk )
874 [ # # ]: 0 : m_nRowCount = std::max(sal_Int32(m_nPosition+1),m_nRowCount);
875 : : }
876 : : }
877 [ - + ][ # # ]: 8 : if(!bOk && !m_bRowCountFinal)
878 : : {
879 : : // because we stand after the last row
880 [ # # ][ # # ]: 0 : m_nRowCount = m_pCacheSet->previous_checked(sal_False) ? m_pCacheSet->getRow() : 0;
[ # # ]
881 : 0 : m_bRowCountFinal = sal_True;
882 : : }
883 : : }
884 : 596 : return sal_True;
885 : : }
886 : :
887 : 10 : sal_Bool bRet = sal_True;
888 : :
889 : 10 : sal_Int32 nDiff = (m_nFetchSize - 1) / 2;
890 : 10 : sal_Int32 nNewStartPos = (m_nPosition - nDiff) - 1; //m_nPosition is 1-based, but m_nStartPos is 0-based
891 : 10 : sal_Int32 nNewEndPos = nNewStartPos + m_nFetchSize;
892 : :
893 [ + - ]: 10 : if ( nNewStartPos < 0 )
894 : : {
895 : : // The computed new window crashes through the floor (begins before first row);
896 : : // nNew*Pos has to be shifted by -nNewStartPos
897 : 10 : nNewEndPos -= nNewStartPos;
898 : 10 : nNewStartPos = 0;
899 : : }
900 : :
901 [ - + ]: 10 : if ( nNewStartPos < m_nStartPos )
902 : : { // need to fill data *before* m_nStartPos
903 [ # # ]: 0 : if ( nNewEndPos > m_nStartPos )
904 : : { // The two regions are overlapping.
905 : : // We'll first rotate the contents of m_pMatrix so that the overlap area
906 : : // is positioned right; in the old window it is at the beginning,
907 : : // it has to go to the end.
908 : : // then we fill in the rows between new and old start pos.
909 : :
910 : : sal_Bool bCheck;
911 [ # # ]: 0 : bCheck = m_pCacheSet->absolute(nNewStartPos + 1);
912 : :
913 : : // m_nEndPos < nNewEndPos when window not filled (e.g. there are less rows in total than window size)
914 [ # # ]: 0 : m_nEndPos = std::min(nNewEndPos, m_nEndPos);
915 : 0 : const sal_Int32 nOverlapSize = m_nEndPos - m_nStartPos;
916 : 0 : const sal_Int32 nStartPosOffset = m_nStartPos - nNewStartPos; // by how much m_nStartPos moves
917 : 0 : m_nStartPos = nNewStartPos;
918 : : OSL_ENSURE( static_cast<ORowSetMatrix::size_type>(nOverlapSize) <= m_pMatrix->size(), "new window end is after end of cache matrix!" );
919 : : // the first position in m_pMatrix whose data we don't keep;
920 : : // content will be moved to m_pMatrix.begin()
921 [ # # ]: 0 : ORowSetMatrix::iterator aEnd (m_pMatrix->begin() + nOverlapSize);
922 : : // the first unused position after we are done; it == m_pMatrix.end() if and only if the window is full
923 [ # # ]: 0 : ORowSetMatrix::iterator aNewEnd (aEnd + nStartPosOffset);
924 : : // *m_pMatrix now looks like:
925 : : // [0; nOverlapSize) i.e. [begin(); aEnd): data kept
926 : : // [nOverlapSize; nOverlapSize + nStartPosOffet) i.e. [aEnd, aNewEnd): new data of positions < old m_nStartPos
927 : : // [nOverlapSize + nStartPosOffet; size()) i.e. [aNewEnd, end()): unused
928 : : // Note that nOverlapSize + nStartPosOffet == m_nEndPos - m_nStartPos (new values)
929 : : // When we are finished:
930 : : // [0; nStartPosOffset) i.e. [begin(); aEnd): new data of positions < old m_nStartPos
931 : : // [nStartPosOffset; nOverlapSize + nStartPosOffet) i.e. [aEnd, aNewEnd): kept
932 : : // [nOverlapSize + nStartPosOffet; size()) i.e. [aNewEnd, end()): unused
933 : :
934 [ # # ]: 0 : if ( bCheck )
935 : : {
936 : : {
937 : 0 : ORowSetMatrix::iterator aIter(aEnd);
938 : 0 : sal_Int32 nPos = m_nStartPos + 1;
939 [ # # ][ # # ]: 0 : bCheck = fill(aIter, aNewEnd, nPos, bCheck);
940 : : }
941 : :
942 [ # # ]: 0 : ::std::rotate(m_pMatrix->begin(), aEnd, aNewEnd);
943 : : // now correct the iterator in our iterator vector
944 : : // rotateCacheIterator(aEnd-m_pMatrix->begin()); //can't be used because they decrement and here we need to increment
945 : 0 : ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
946 : 0 : const ORowSetCacheMap::const_iterator aCacheEnd = m_aCacheIterators.end();
947 [ # # ]: 0 : for(;aCacheIter != aCacheEnd;++aCacheIter)
948 : : {
949 [ # # ][ # # ]: 0 : if ( !aCacheIter->second.pRowSet->isInsertRow()
[ # # ][ # # ]
950 [ # # ][ # # ]: 0 : && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified )
[ # # ]
951 : : {
952 [ # # ]: 0 : const ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
953 [ # # ]: 0 : if ( nDist >= nOverlapSize )
954 : : {
955 : : // That's from outside the overlap area; invalidate iterator.
956 : 0 : aCacheIter->second.aIterator = m_pMatrix->end();
957 : : }
958 : : else
959 : : {
960 : : // Inside overlap area: move to correct position
961 : : CHECK_MATRIX_POS( (nDist + nStartPosOffset) );
962 : 0 : aCacheIter->second.aIterator += nStartPosOffset;
963 : : OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin()
964 : : && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!");
965 : : }
966 : : }
967 : : }
968 : : }
969 : : else
970 : : { // normally this should never happen
971 : : OSL_FAIL("What the hell is happen here!");
972 : 0 : return sal_False;
973 : : }
974 : : }
975 : : else
976 : : {// no rows can be reused so fill again
977 [ # # ]: 0 : bRet = reFillMatrix(nNewStartPos,nNewEndPos);
978 : : }
979 : : }
980 : :
981 : : OSL_ENSURE(nNewStartPos >= m_nStartPos, "ORowSetCache::moveWindow internal error: new start pos before current start pos");
982 [ + - ]: 10 : if ( m_nEndPos < nNewEndPos )
983 : : { // need to fill data *after* m_nEndPos
984 [ + - ]: 10 : if( nNewStartPos < m_nEndPos )
985 : : { // The two regions are overlapping.
986 : 10 : const sal_Int32 nRowsInCache = m_nEndPos - m_nStartPos;
987 [ + - ]: 10 : if ( nRowsInCache < m_nFetchSize )
988 : : {
989 : : // There is some unused space in *m_pMatrix; fill it
990 : : CHECK_MATRIX_POS(nRowsInCache);
991 : 10 : sal_Int32 nPos = m_nEndPos + 1;
992 [ + - ]: 10 : sal_Bool bCheck = m_pCacheSet->absolute(nPos);
993 [ + - ]: 10 : ORowSetMatrix::iterator aIter = m_pMatrix->begin() + nRowsInCache;
994 [ + - ]: 10 : const sal_Int32 nRowsToFetch = std::min(nNewEndPos-m_nEndPos, m_nFetchSize-nRowsInCache);
995 [ + - ][ + - ]: 10 : const ORowSetMatrix::const_iterator aEnd = aIter + nRowsToFetch;
996 [ + - ]: 10 : bCheck = fill(aIter, aEnd, nPos, bCheck);
997 : 10 : m_nEndPos = nPos - 1;
998 : : OSL_ENSURE( (!bCheck && m_nEndPos <= nNewEndPos ) ||
999 : : ( bCheck && m_nEndPos == nNewEndPos ),
1000 : : "ORowSetCache::moveWindow opportunistic fetch-after-current-end went badly");
1001 : : }
1002 : :
1003 : : // À priori, the rows from begin() [inclusive] to (begin() + nNewStartPos - m_nStartPos) [exclusive]
1004 : : // have to be refilled with new to-be-fetched rows.
1005 : : // The rows behind this can be reused
1006 : 10 : ORowSetMatrix::iterator aIter = m_pMatrix->begin();
1007 : 10 : const sal_Int32 nNewStartPosInMatrix = nNewStartPos - m_nStartPos;
1008 : : CHECK_MATRIX_POS( nNewStartPosInMatrix );
1009 : : // first position we reuse
1010 [ + - ][ + - ]: 10 : const ORowSetMatrix::const_iterator aEnd = m_pMatrix->begin() + nNewStartPosInMatrix;
1011 : : // End of used portion of the matrix. Is < m_pMatrix->end() if less data than window size
1012 [ + - ]: 10 : ORowSetMatrix::iterator aDataEnd = m_pMatrix->begin() + (m_nEndPos - m_nStartPos);
1013 : :
1014 : 10 : sal_Int32 nPos = m_nEndPos + 1;
1015 [ + - ]: 10 : sal_Bool bCheck = m_pCacheSet->absolute(nPos);
1016 [ + - ]: 10 : bCheck = fill(aIter, aEnd, nPos, bCheck); // refill the region we don't need anymore
1017 : : //aIter and nPos are now the position *after* last filled in one!
1018 : :
1019 : : // bind end to front
1020 [ - + ]: 10 : if(bCheck)
1021 : : {
1022 : : OSL_ENSURE(aIter == aEnd, "fill() said went till end, but did not.");
1023 : : // rotate the end to the front
1024 [ # # ]: 0 : ::std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
1025 : : // now correct the iterator in our iterator vector
1026 [ # # ]: 0 : rotateCacheIterator( nNewStartPosInMatrix );
1027 : 0 : m_nStartPos = nNewStartPos;
1028 : 0 : m_nEndPos = nNewEndPos;
1029 : : // now I can say how many rows we have
1030 : : // we have to read one row forward to ensure that we know when we are on last row
1031 : : // but only when we don't know it already
1032 : 0 : sal_Bool bOk = sal_True;
1033 [ # # ]: 0 : if(!m_bRowCountFinal)
1034 [ # # ]: 0 : bOk = m_pCacheSet->next();
1035 [ # # ]: 0 : if(!bOk)
1036 : : {
1037 [ # # ]: 0 : m_pCacheSet->previous_checked(sal_False); // because we stand after the last row
1038 : 0 : m_nRowCount = nPos; // here we have the row count
1039 : : OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos is not valid!");
1040 : 0 : m_bRowCountFinal = sal_True;
1041 : : }
1042 [ # # ]: 0 : else if(!m_bRowCountFinal)
1043 [ # # ]: 0 : m_nRowCount = std::max(nPos+1, m_nRowCount); //+1 because we successfully moved to row after nPos
1044 : : else
1045 : : OSL_ENSURE(m_nRowCount >= nPos, "Final m_nRowCount is smaller than row I moved to!");
1046 : : }
1047 : : else
1048 : : { // the end was reached before or at end() so we can set the start before or at nNewStartPos
1049 : : // and possibly keep more of m_pMatrix than planned.
1050 [ + - ]: 10 : const ORowSetMatrix::iterator::difference_type nFetchedRows = aIter - m_pMatrix->begin();
1051 : : // *m_pMatrix now looks like:
1052 : : // [0; nFetchedRows) i.e. [begin(); aIter): newly fetched data for positions m_nEndPos to m_nEndPos+nFetchedRows
1053 : : // [nFetchedRows; ???) i.e. [aIter; aDataEnd]: data to be kept for positions m_nStartPos+nFetchedRows to ???
1054 : :
1055 : 10 : nPos -= 1;
1056 : 10 : m_nStartPos += nFetchedRows;
1057 : 10 : m_nEndPos = nPos;
1058 [ + - ]: 10 : ::std::rotate(m_pMatrix->begin(), aIter, aDataEnd);
1059 : : // now correct the iterator in our iterator vector
1060 [ + - ]: 10 : rotateCacheIterator( nFetchedRows );
1061 : :
1062 [ - + ]: 10 : if ( !m_bRowCountFinal )
1063 : : {
1064 [ # # ]: 0 : m_pCacheSet->previous_checked(sal_False); // because we stand after the last row
1065 [ # # ]: 0 : m_nRowCount = std::max(m_nRowCount, nPos); // here we have the row count
1066 : : OSL_ENSURE(nPos == m_pCacheSet->getRow(),"nPos isn't valid!");
1067 : 0 : m_bRowCountFinal = sal_True;
1068 : : }
1069 : :
1070 : : }
1071 : : // here we need only to check if the beginning row is valid. If not we have to fetch it.
1072 [ - + ]: 10 : if(!m_pMatrix->begin()->is())
1073 : : {
1074 : 0 : aIter = m_pMatrix->begin();
1075 : :
1076 : 0 : nPos = m_nStartPos + 1;
1077 [ # # ]: 0 : bCheck = m_pCacheSet->absolute_checked(nPos, sal_True);
1078 [ # # ][ # # ]: 10 : for(; !aIter->is() && bCheck;++aIter, ++nPos)
[ # # ]
1079 : : {
1080 : : OSL_ENSURE(aIter != m_pMatrix->end(),"Invalid iterator");
1081 : :
1082 [ # # ][ # # ]: 0 : *aIter = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ # # ][ # # ]
1083 [ # # ]: 0 : m_pCacheSet->fillValueRow(*aIter, nPos);
1084 : :
1085 [ # # ]: 0 : bCheck = m_pCacheSet->next();
1086 : : }
1087 : : }
1088 : : }
1089 : : else // no rows can be reused so fill again
1090 [ # # ]: 0 : bRet = reFillMatrix(nNewStartPos,nNewEndPos);
1091 : : }
1092 : :
1093 [ - + ]: 10 : if(!m_bRowCountFinal)
1094 [ # # ]: 0 : m_nRowCount = std::max(m_nPosition,m_nRowCount);
1095 : : OSL_ENSURE(m_nStartPos >= 0,"ORowSetCache::moveWindow: m_nStartPos is less than 0!");
1096 : : OSL_ENSURE(m_nEndPos > m_nStartPos,"ORowSetCache::moveWindow: m_nStartPos not smaller than m_nEndPos");
1097 : : OSL_ENSURE(m_nEndPos-m_nStartPos <= m_nFetchSize,"ORowSetCache::moveWindow: m_nStartPos and m_nEndPos too far apart");
1098 : :
1099 : 606 : return bRet;
1100 : : }
1101 : :
1102 : 50 : sal_Bool ORowSetCache::first( )
1103 : : {
1104 : : // First move to the first row.
1105 : : // Then check if the cache window is at the beginning.
1106 : : // If not, then position the window and fill it with data.
1107 : : // We move the window smartly, i.e. we clear only the rows that are out of range
1108 : 50 : sal_Bool bRet = m_pCacheSet->first();
1109 [ + + ]: 50 : if(bRet)
1110 : : {
1111 : 46 : m_bBeforeFirst = m_bAfterLast = sal_False;
1112 : 46 : m_nPosition = 1;
1113 : 46 : moveWindow();
1114 : 46 : m_aMatrixIter = m_pMatrix->begin();
1115 : : }
1116 : : else
1117 : : {
1118 : 4 : m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True;
1119 : 4 : m_nRowCount = m_nPosition = 0;
1120 : :
1121 : : OSL_ENSURE(m_bBeforeFirst || m_bNew,"ORowSetCache::first return false and BeforeFirst isn't true");
1122 : 4 : m_aMatrixIter = m_pMatrix->end();
1123 : : }
1124 : 50 : return bRet;
1125 : : }
1126 : :
1127 : 4 : sal_Bool ORowSetCache::last( )
1128 : : {
1129 : 4 : sal_Bool bRet = m_pCacheSet->last();
1130 [ + - ]: 4 : if(bRet)
1131 : : {
1132 : 4 : m_bBeforeFirst = m_bAfterLast = sal_False;
1133 [ - + ]: 4 : if(!m_bRowCountFinal)
1134 : : {
1135 : 0 : m_bRowCountFinal = sal_True;
1136 : 0 : m_nRowCount = m_pCacheSet->getRow(); // not + 1
1137 : : }
1138 : 4 : m_nPosition = m_pCacheSet->getRow();
1139 : 4 : moveWindow();
1140 : : // we have to repositioning because moveWindow can modify the cache
1141 : 4 : m_pCacheSet->last();
1142 : : OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
1143 : 4 : m_aMatrixIter = calcPosition();
1144 : : }
1145 : : else
1146 : : {
1147 : 0 : m_bRowCountFinal = m_bBeforeFirst = m_bAfterLast = sal_True;
1148 : 0 : m_nRowCount = m_nPosition = 0;
1149 : : OSL_ENSURE(m_bBeforeFirst,"ORowSetCache::last return false and BeforeFirst isn't true");
1150 : 0 : m_aMatrixIter = m_pMatrix->end();
1151 : : }
1152 : : #if OSL_DEBUG_LEVEL > 1
1153 : : if(bRet)
1154 : : {
1155 : : OSL_ENSURE((*m_aMatrixIter).is(),"ORowSetCache::last: Row not valid!");
1156 : : }
1157 : : #endif
1158 : :
1159 : 4 : return bRet;
1160 : : }
1161 : :
1162 : 62 : sal_Int32 ORowSetCache::getRow( )
1163 : : {
1164 [ + - ][ + - ]: 62 : return (isBeforeFirst() || isAfterLast()) ? 0 : m_nPosition;
1165 : : }
1166 : :
1167 : 24 : sal_Bool ORowSetCache::absolute( sal_Int32 row )
1168 : : {
1169 [ - + ]: 24 : if(!row )
1170 [ # # ][ # # ]: 0 : throw SQLException(DBACORE_RESSTRING(RID_STR_NO_ABS_ZERO),NULL,SQLSTATE_GENERAL,1000,Any() );
[ # # ][ # # ]
1171 : :
1172 [ - + ]: 24 : if(row < 0)
1173 : : {
1174 : : // here we have to scroll from the last row to backward so we have to go to last row and
1175 : : // and two the previous
1176 [ # # ][ # # ]: 0 : if(m_bRowCountFinal || last())
[ # # ]
1177 : : {
1178 : 0 : m_nPosition = m_nRowCount + row + 1; // + row because row is negative and +1 because row==-1 means last row
1179 [ # # ]: 0 : if(m_nPosition < 1)
1180 : : {
1181 : 0 : m_bBeforeFirst = sal_True;
1182 : 0 : m_bAfterLast = sal_False;
1183 : 0 : m_aMatrixIter = m_pMatrix->end();
1184 : : }
1185 : : else
1186 : : {
1187 : 0 : m_bBeforeFirst = sal_False;
1188 : 0 : m_bAfterLast = m_nPosition > m_nRowCount;
1189 : 0 : moveWindow();
1190 : : OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
1191 : 0 : m_aMatrixIter = calcPosition();
1192 : : }
1193 : : }
1194 : : else
1195 : 0 : m_aMatrixIter = m_pMatrix->end();
1196 : : }
1197 : : else
1198 : : {
1199 : 24 : m_nPosition = row;
1200 : : // the position flags
1201 : 24 : m_bBeforeFirst = sal_False;
1202 : 24 : checkPositionFlags();
1203 : :
1204 [ + - ]: 24 : if(!m_bAfterLast)
1205 : : {
1206 : 24 : moveWindow();
1207 : 24 : checkPositionFlags();
1208 [ + - ]: 24 : if(!m_bAfterLast)
1209 : 24 : m_aMatrixIter = calcPosition();
1210 : : else
1211 : 0 : m_aMatrixIter = m_pMatrix->end();
1212 : : }
1213 : : else
1214 : 0 : m_aMatrixIter = m_pMatrix->end();
1215 : : }
1216 : :
1217 [ + - ][ + - ]: 24 : return !(m_bAfterLast || m_bBeforeFirst);
1218 : : }
1219 : :
1220 : 16 : sal_Bool ORowSetCache::relative( sal_Int32 rows )
1221 : : {
1222 : 16 : sal_Bool bErg = sal_True;
1223 [ + - ]: 16 : if(rows)
1224 : : {
1225 : 16 : sal_Int32 nNewPosition = m_nPosition + rows;
1226 : :
1227 [ - + ][ # # ]: 16 : if ( m_bBeforeFirst && rows > 0 )
1228 : 0 : nNewPosition = rows;
1229 [ + - ][ - + ]: 16 : else if ( m_bRowCountFinal && m_bAfterLast && rows < 0 )
[ # # ]
1230 : 0 : nNewPosition = m_nRowCount + 1 + rows;
1231 : : else
1232 [ + - ][ + - ]: 16 : if ( m_bBeforeFirst || ( m_bRowCountFinal && m_bAfterLast ) )
[ - + ]
1233 [ # # ][ # # ]: 0 : throw SQLException( DBACORE_RESSTRING( RID_STR_NO_RELATIVE ), NULL, SQLSTATE_GENERAL, 1000, Any() );
[ # # ][ # # ]
1234 [ + - ]: 16 : if ( nNewPosition )
1235 : : {
1236 : 16 : bErg = absolute( nNewPosition );
1237 [ + - ][ + - ]: 16 : bErg = bErg && !isAfterLast() && !isBeforeFirst();
[ + - ]
1238 : : }
1239 : : else
1240 : : {
1241 : 0 : m_bBeforeFirst = sal_True;
1242 : 0 : bErg = sal_False;
1243 : : }
1244 : : }
1245 : 16 : return bErg;
1246 : : }
1247 : :
1248 : 2 : sal_Bool ORowSetCache::previous( )
1249 : : {
1250 : 2 : sal_Bool bRet = sal_False;
1251 [ + - ]: 2 : if(!isBeforeFirst())
1252 : : {
1253 [ - + ]: 2 : if(m_bAfterLast) // we stand after the last row so one before is the last row
1254 : 0 : bRet = last();
1255 : : else
1256 : : {
1257 : 2 : m_bAfterLast = sal_False;
1258 : 2 : --m_nPosition;
1259 : 2 : moveWindow();
1260 : : OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
1261 : :
1262 : 2 : checkPositionFlags();
1263 : :
1264 [ - + ]: 2 : if(!m_nPosition)
1265 : : {
1266 : 0 : m_bBeforeFirst = sal_True;
1267 : 0 : m_aMatrixIter = m_pMatrix->end();
1268 : : }
1269 : : else
1270 : : {
1271 : 2 : m_aMatrixIter = calcPosition();
1272 : 2 : bRet = (*m_aMatrixIter).is();
1273 : : }
1274 : : }
1275 : : }
1276 : 2 : return bRet;
1277 : : }
1278 : :
1279 : 2 : void ORowSetCache::refreshRow( )
1280 : : {
1281 [ - + ]: 2 : if(isAfterLast())
1282 [ # # ][ # # ]: 0 : throw SQLException(DBACORE_RESSTRING(RID_STR_NO_REFESH_AFTERLAST),NULL,SQLSTATE_GENERAL,1000,Any() );
[ # # ][ # # ]
1283 : : OSL_ENSURE(m_aMatrixIter != m_pMatrix->end(),"refreshRow() called for invalid row!");
1284 : 2 : m_pCacheSet->refreshRow();
1285 : 2 : m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
1286 [ - + ]: 2 : if ( m_bNew )
1287 : : {
1288 : 0 : cancelRowModification();
1289 : : }
1290 : 2 : }
1291 : :
1292 : 2 : sal_Bool ORowSetCache::rowUpdated( )
1293 : : {
1294 : 2 : return m_pCacheSet->rowUpdated();
1295 : : }
1296 : :
1297 : 4 : sal_Bool ORowSetCache::rowInserted( )
1298 : : {
1299 : 4 : return m_pCacheSet->rowInserted();
1300 : : }
1301 : :
1302 : : // XResultSetUpdate
1303 : 2 : sal_Bool ORowSetCache::insertRow(::std::vector< Any >& o_aBookmarks)
1304 : : {
1305 [ + - ][ - + ]: 2 : if ( !m_bNew || !m_aInsertRow->is() )
[ - + ]
1306 [ # # ][ # # ]: 0 : throw SQLException(DBACORE_RESSTRING(RID_STR_NO_MOVETOINSERTROW_CALLED),NULL,SQLSTATE_GENERAL,1000,Any() );
[ # # ][ # # ]
1307 : :
1308 : 2 : m_pCacheSet->insertRow(*m_aInsertRow,m_aUpdateTable);
1309 : :
1310 : 2 : sal_Bool bRet( rowInserted() );
1311 [ + - ]: 2 : if ( bRet )
1312 : : {
1313 : 2 : ++m_nRowCount;
1314 [ + - ][ + - ]: 2 : Any aBookmark = ((*m_aInsertRow)->get())[0].makeAny();
1315 : 2 : m_bAfterLast = m_bBeforeFirst = sal_False;
1316 [ + - ]: 2 : if(aBookmark.hasValue())
1317 : : {
1318 [ + - ]: 2 : moveToBookmark(aBookmark);
1319 : : // update the cached values
1320 : 2 : ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get();
1321 : 2 : ORowSetMatrix::iterator aIter = m_pMatrix->begin();
1322 [ + - ][ + + ]: 102 : for(;aIter != m_pMatrix->end();++aIter)
1323 : : {
1324 [ + - ][ + + ]: 100 : if ( m_aMatrixIter != aIter && aIter->is() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) )
[ + + ][ + - ]
[ - + ][ - + ]
1325 : : {
1326 [ # # ][ # # ]: 0 : o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet));
[ # # ]
1327 : : }
1328 : : }
1329 : : }
1330 : : else
1331 : : {
1332 : : OSL_FAIL("There must be a bookmark after the row was inserted!");
1333 : 2 : }
1334 : : }
1335 : 2 : return bRet;
1336 : : }
1337 : :
1338 : 2 : void ORowSetCache::resetInsertRow(sal_Bool _bClearInsertRow)
1339 : : {
1340 [ + - ]: 2 : if ( _bClearInsertRow )
1341 : 2 : clearInsertRow();
1342 : 2 : m_bNew = sal_False;
1343 : 2 : m_bModified = sal_False;
1344 : 2 : }
1345 : :
1346 : 0 : void ORowSetCache::cancelRowModification()
1347 : : {
1348 : : // clear the insertrow references -> implies that the current row of the rowset changes as well
1349 : 0 : ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
1350 : 0 : ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end();
1351 [ # # ]: 0 : for(;aCacheIter != aCacheEnd;++aCacheIter)
1352 : : {
1353 [ # # ][ # # ]: 0 : if ( aCacheIter->second.pRowSet->isInsertRow() && aCacheIter->second.aIterator == m_aInsertRow )
[ # # ][ # # ]
1354 : 0 : aCacheIter->second.aIterator = m_pMatrix->end();
1355 : : }
1356 [ # # ]: 0 : resetInsertRow(sal_False);
1357 : 0 : }
1358 : :
1359 : 8 : void ORowSetCache::updateRow( ORowSetMatrix::iterator& _rUpdateRow,::std::vector< Any >& o_aBookmarks )
1360 : : {
1361 [ + - ][ - + ]: 8 : if(isAfterLast() || isBeforeFirst())
[ - + ]
1362 [ # # ][ # # ]: 0 : throw SQLException(DBACORE_RESSTRING(RID_STR_NO_UPDATEROW),NULL,SQLSTATE_GENERAL,1000,Any() );
[ # # ][ # # ]
1363 : :
1364 [ + - ][ + - ]: 8 : Any aBookmark = ((*_rUpdateRow)->get())[0].makeAny();
1365 : : OSL_ENSURE(aBookmark.hasValue(),"Bookmark must have a value!");
1366 : : // here we don't have to reposition our CacheSet, when we try to update a row,
1367 : : // the row was already fetched
1368 [ + - ]: 8 : moveToBookmark(aBookmark);
1369 [ + - ]: 8 : m_pCacheSet->updateRow(*_rUpdateRow,*m_aMatrixIter,m_aUpdateTable);
1370 : : // refetch the whole row
1371 [ + - ]: 8 : (*m_aMatrixIter) = NULL;
1372 : :
1373 [ + - ][ + - ]: 8 : if ( moveToBookmark(aBookmark) )
1374 : : {
1375 : : // update the cached values
1376 : 8 : ORowSetValueVector::Vector& rCurrentRow = ((*m_aMatrixIter))->get();
1377 : 8 : ORowSetMatrix::iterator aIter = m_pMatrix->begin();
1378 [ + - ][ + + ]: 408 : for(;aIter != m_pMatrix->end();++aIter)
1379 : : {
1380 [ + - ][ + + ]: 400 : if ( m_aMatrixIter != aIter && aIter->is() && m_pCacheSet->columnValuesUpdated((*aIter)->get(),rCurrentRow) )
[ + + ][ + - ]
[ - + ][ - + ]
1381 : : {
1382 [ # # ][ # # ]: 0 : o_aBookmarks.push_back(lcl_getBookmark((*aIter)->get()[0],m_pCacheSet));
[ # # ]
1383 : : }
1384 : : }
1385 : : }
1386 : :
1387 : 8 : m_bModified = sal_False;
1388 : 8 : }
1389 : :
1390 : 2 : bool ORowSetCache::deleteRow( )
1391 : : {
1392 [ + - ][ - + ]: 2 : if(isAfterLast() || isBeforeFirst())
[ - + ]
1393 [ # # ][ # # ]: 0 : throw SQLException(DBACORE_RESSTRING(RID_STR_NO_DELETEROW),NULL,SQLSTATE_GENERAL,1000,Any() );
[ # # ][ # # ]
1394 : :
1395 [ + - ]: 2 : m_pCacheSet->deleteRow(*m_aMatrixIter,m_aUpdateTable);
1396 [ + - ][ - + ]: 2 : if ( !m_pCacheSet->rowDeleted() )
1397 : 0 : return false;
1398 : :
1399 : 2 : --m_nRowCount;
1400 : : OSL_ENSURE(((m_nPosition - m_nStartPos) - 1) < (sal_Int32)m_pMatrix->size(),"Position is behind end()!");
1401 [ + - ]: 2 : ORowSetMatrix::iterator aPos = calcPosition();
1402 [ + - ]: 2 : (*aPos) = NULL;
1403 : :
1404 : 2 : ORowSetMatrix::iterator aEnd = m_pMatrix->end();
1405 [ + - ][ + - ]: 2 : for(++aPos;aPos != aEnd && aPos->is();++aPos)
[ - + ][ - + ]
1406 : : {
1407 [ # # ][ # # ]: 0 : *(aPos-1) = *aPos;
1408 [ # # ]: 0 : (*aPos) = NULL;
1409 : : }
1410 : 2 : m_aMatrixIter = m_pMatrix->end();
1411 : :
1412 : 2 : --m_nPosition;
1413 : 2 : return true;
1414 : : }
1415 : :
1416 : 2 : void ORowSetCache::cancelRowUpdates( )
1417 : : {
1418 : 2 : m_bNew = m_bModified = sal_False;
1419 [ - + ]: 2 : if(!m_nPosition)
1420 : : {
1421 : : OSL_FAIL("cancelRowUpdates:Invalid positions pos == 0");
1422 [ # # ][ # # ]: 0 : ::dbtools::throwFunctionSequenceException(NULL);
1423 : : }
1424 : :
1425 [ + - ]: 2 : if(m_pCacheSet->absolute(m_nPosition))
1426 : 2 : m_pCacheSet->fillValueRow(*m_aMatrixIter,m_nPosition);
1427 : : else
1428 : : {
1429 : : OSL_FAIL("cancelRowUpdates couldn't position right with absolute");
1430 [ # # ][ # # ]: 0 : ::dbtools::throwFunctionSequenceException(NULL);
1431 : : }
1432 : 2 : }
1433 : :
1434 : 2 : void ORowSetCache::moveToInsertRow( )
1435 : : {
1436 : 2 : m_bNew = sal_True;
1437 : 2 : m_bUpdated = m_bAfterLast = sal_False;
1438 : :
1439 : 2 : m_aInsertRow = m_pInsertMatrix->begin();
1440 [ + - ]: 2 : if(!m_aInsertRow->is())
1441 [ + - ][ + - ]: 2 : *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ + - ][ + - ]
1442 : :
1443 : : // we don't unbound the bookmark column
1444 [ + - ]: 2 : ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1;
1445 : 2 : ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
1446 [ + - ][ + - ]: 64 : for(sal_Int32 i = 1;aIter != aEnd;++aIter,++i)
[ + + ]
1447 : : {
1448 [ + - ]: 62 : aIter->setBound(sal_False);
1449 [ + - ]: 62 : aIter->setModified(sal_False);
1450 [ + - ][ + - ]: 62 : aIter->setNull();
1451 [ + - ][ + - ]: 62 : aIter->setTypeKind(m_xMetaData->getColumnType(i));
[ + - ][ + - ]
1452 : : }
1453 : 2 : }
1454 : :
1455 : 44 : ORowSetCacheIterator ORowSetCache::createIterator(ORowSetBase* _pRowSet)
1456 : : {
1457 : 44 : ORowSetCacheIterator_Helper aHelper;
1458 : 44 : aHelper.aIterator = m_pMatrix->end();
1459 : 44 : aHelper.pRowSet = _pRowSet;
1460 [ + - ]: 44 : return ORowSetCacheIterator(m_aCacheIterators.insert(m_aCacheIterators.begin(),ORowSetCacheMap::value_type(m_aCacheIterators.size()+1,aHelper)),this,_pRowSet);
1461 : : }
1462 : :
1463 : 4 : void ORowSetCache::deleteIterator(const ORowSetBase* _pRowSet)
1464 : : {
1465 : 4 : ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
1466 [ + + ]: 16 : for(;aCacheIter != m_aCacheIterators.end();)
1467 : : {
1468 [ + + ]: 12 : if ( aCacheIter->second.pRowSet == _pRowSet )
1469 : : {
1470 [ + - ]: 4 : m_aCacheIterators.erase(aCacheIter);
1471 : 4 : aCacheIter = m_aCacheIterators.begin();
1472 : : }
1473 : : else
1474 : 8 : ++aCacheIter;
1475 : : }
1476 : 4 : }
1477 : :
1478 : 10 : void ORowSetCache::rotateCacheIterator(ORowSetMatrix::difference_type _nDist)
1479 : : {
1480 [ - + ]: 10 : if(_nDist)
1481 : : {
1482 : : // now correct the iterator in our iterator vector
1483 : 0 : ORowSetCacheMap::iterator aCacheIter = m_aCacheIterators.begin();
1484 : 0 : ORowSetCacheMap::iterator aCacheEnd = m_aCacheIterators.end();
1485 [ # # ]: 0 : for(;aCacheIter != aCacheEnd;++aCacheIter)
1486 : : {
1487 [ # # ][ # # ]: 0 : if ( !aCacheIter->second.pRowSet->isInsertRow()
[ # # ][ # # ]
1488 [ # # ][ # # ]: 0 : && aCacheIter->second.aIterator != m_pMatrix->end() && !m_bModified )
[ # # ]
1489 : : {
1490 [ # # ]: 0 : ptrdiff_t nDist = (aCacheIter->second.aIterator - m_pMatrix->begin());
1491 [ # # ]: 0 : if(nDist < _nDist)
1492 : : {
1493 : 0 : aCacheIter->second.aIterator = m_pMatrix->end();
1494 : : }
1495 : : else
1496 : : {
1497 : : OSL_ENSURE((aCacheIter->second.aIterator - m_pMatrix->begin()) >= _nDist,"Invalid Dist value!");
1498 : 0 : aCacheIter->second.aIterator -= _nDist;
1499 : : OSL_ENSURE(aCacheIter->second.aIterator >= m_pMatrix->begin()
1500 : : && aCacheIter->second.aIterator < m_pMatrix->end(),"Iterator out of area!");
1501 : : }
1502 : : }
1503 : : }
1504 : : }
1505 : 10 : }
1506 : :
1507 : 10 : void ORowSetCache::setUpdateIterator(const ORowSetMatrix::iterator& _rOriginalRow)
1508 : : {
1509 : 10 : m_aInsertRow = m_pInsertMatrix->begin();
1510 [ + - ]: 10 : if(!m_aInsertRow->is())
1511 [ + - ][ + - ]: 10 : *m_aInsertRow = new ORowSetValueVector(m_xMetaData->getColumnCount());
[ + - ][ + - ]
1512 : :
1513 [ + - ]: 10 : (*(*m_aInsertRow)) = (*(*_rOriginalRow));
1514 : : // we don't unbound the bookmark column
1515 : 10 : ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin();
1516 : 10 : ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
1517 [ + - ][ + + ]: 90 : for(;aIter != aEnd;++aIter)
[ + - ]
1518 [ + - ]: 80 : aIter->setModified(sal_False);
1519 : 10 : }
1520 : :
1521 : 1102 : void ORowSetCache::checkPositionFlags()
1522 : : {
1523 [ + - ]: 1102 : if(m_bRowCountFinal)
1524 : : {
1525 : 1102 : m_bAfterLast = m_nPosition > m_nRowCount;
1526 [ + + ]: 1102 : if(m_bAfterLast)
1527 : 8 : m_nPosition = 0;//m_nRowCount;
1528 : : }
1529 : 1102 : }
1530 : :
1531 : 12 : void ORowSetCache::checkUpdateConditions(sal_Int32 columnIndex)
1532 : : {
1533 [ + - ][ - + ]: 12 : if(m_bAfterLast || columnIndex >= (sal_Int32)(*m_aInsertRow)->get().size())
[ - + ]
1534 [ # # ][ # # ]: 0 : throwFunctionSequenceException(m_xSet.get());
1535 : 12 : }
1536 : :
1537 : 0 : sal_Bool ORowSetCache::checkInnerJoin(const ::connectivity::OSQLParseNode *pNode,const Reference< XConnection>& _xConnection,const ::rtl::OUString& _sUpdateTableName)
1538 : : {
1539 : 0 : sal_Bool bOk = sal_False;
1540 [ # # # # : 0 : if (pNode->count() == 3 && // Ausdruck is geklammert
# # # # #
# ][ # # ]
1541 : 0 : SQL_ISPUNCTUATION(pNode->getChild(0),"(") &&
1542 : 0 : SQL_ISPUNCTUATION(pNode->getChild(2),")"))
1543 : : {
1544 : 0 : bOk = checkInnerJoin(pNode->getChild(1),_xConnection,_sUpdateTableName);
1545 : : }
1546 [ # # ][ # # ]: 0 : else if ((SQL_ISRULE(pNode,search_condition) || SQL_ISRULE(pNode,boolean_term)) && // AND/OR link
[ # # ]
[ # # # # ]
[ # # ]
1547 : 0 : pNode->count() == 3)
1548 : : {
1549 : : // only allow an AND link
1550 [ # # ][ # # ]: 0 : if ( SQL_ISTOKEN(pNode->getChild(1),AND) )
[ # # ]
1551 : 0 : bOk = checkInnerJoin(pNode->getChild(0),_xConnection,_sUpdateTableName)
1552 [ # # ][ # # ]: 0 : && checkInnerJoin(pNode->getChild(2),_xConnection,_sUpdateTableName);
1553 : : }
1554 [ # # ][ # # ]: 0 : else if (SQL_ISRULE(pNode,comparison_predicate))
[ # # ]
1555 : : {
1556 : : // only the comparison of columns is allowed
1557 : : OSL_ENSURE(pNode->count() == 3,"checkInnerJoin: Fehler im Parse Tree");
1558 [ # # ][ # # ]: 0 : if (!(SQL_ISRULE(pNode->getChild(0),column_ref) &&
[ # # ][ # # ]
1559 [ # # ][ # # ]: 0 : SQL_ISRULE(pNode->getChild(2),column_ref) &&
[ # # ]
1560 [ # # # # ]: 0 : pNode->getChild(1)->getNodeType() == SQL_NODE_EQUAL))
[ # # ][ # # ]
[ # # ][ # # ]
1561 : : {
1562 : 0 : bOk = sal_False;
1563 : : }
1564 : 0 : ::rtl::OUString sColumnName,sTableRange;
1565 [ # # ][ # # ]: 0 : OSQLParseTreeIterator::getColumnRange( pNode->getChild(0), _xConnection, sColumnName, sTableRange );
1566 : 0 : bOk = sTableRange == _sUpdateTableName;
1567 [ # # ]: 0 : if ( !bOk )
1568 : : {
1569 [ # # ][ # # ]: 0 : OSQLParseTreeIterator::getColumnRange( pNode->getChild(2), _xConnection, sColumnName, sTableRange );
1570 : 0 : bOk = sTableRange == _sUpdateTableName;
1571 : 0 : }
1572 : : }
1573 : 0 : return bOk;
1574 : : }
1575 : :
1576 : 0 : sal_Bool ORowSetCache::checkJoin(const Reference< XConnection>& _xConnection,
1577 : : const Reference< XSingleSelectQueryAnalyzer >& _xAnalyzer,
1578 : : const ::rtl::OUString& _sUpdateTableName )
1579 : : {
1580 : 0 : sal_Bool bOk = sal_False;
1581 [ # # ][ # # ]: 0 : ::rtl::OUString sSql = _xAnalyzer->getQuery();
1582 : 0 : ::rtl::OUString sErrorMsg;
1583 [ # # ][ # # ]: 0 : ::connectivity::OSQLParser aSqlParser( m_aContext.getLegacyServiceFactory() );
1584 : : SAL_WNODEPRECATED_DECLARATIONS_PUSH
1585 [ # # ]: 0 : ::std::auto_ptr< ::connectivity::OSQLParseNode> pSqlParseNode( aSqlParser.parseTree(sErrorMsg,sSql));
1586 : : SAL_WNODEPRECATED_DECLARATIONS_POP
1587 [ # # ][ # # ]: 0 : if ( pSqlParseNode.get() && SQL_ISRULE(pSqlParseNode, select_statement) )
[ # # ][ # # ]
[ # # ]
1588 : : {
1589 [ # # ]: 0 : OSQLParseNode* pTableRefCommalist = pSqlParseNode->getByRule(::connectivity::OSQLParseNode::table_ref_commalist);
1590 : : OSL_ENSURE(pTableRefCommalist,"NO tables why!?");
1591 [ # # ][ # # ]: 0 : if(pTableRefCommalist && pTableRefCommalist->count() == 1)
[ # # ]
1592 : : {
1593 : : // we found only one element so it must some kind of join here
1594 [ # # ]: 0 : OSQLParseNode* pJoin = pTableRefCommalist->getByRule(::connectivity::OSQLParseNode::qualified_join);
1595 [ # # ]: 0 : if(pJoin)
1596 : : { // we are only intereseted in qualified joins like RIGHT or LEFT
1597 [ # # ]: 0 : OSQLParseNode* pJoinType = pJoin->getChild(1);
1598 : 0 : OSQLParseNode* pOuterType = NULL;
1599 [ # # ][ # # ]: 0 : if(SQL_ISRULE(pJoinType,join_type) && pJoinType->count() == 2)
[ # # ][ # # ]
[ # # ]
1600 [ # # ]: 0 : pOuterType = pJoinType->getChild(0);
1601 [ # # ][ # # ]: 0 : else if(SQL_ISRULE(pJoinType,outer_join_type))
[ # # ][ # # ]
1602 : 0 : pOuterType = pJoinType;
1603 : :
1604 : 0 : sal_Bool bCheck = sal_False;
1605 : 0 : sal_Bool bLeftSide = sal_False;
1606 [ # # ]: 0 : if(pOuterType)
1607 : : { // found outer join
1608 [ # # ][ # # ]: 0 : bLeftSide = SQL_ISTOKEN(pOuterType->getChild(0),LEFT);
[ # # ][ # # ]
1609 [ # # ][ # # ]: 0 : bCheck = bLeftSide || SQL_ISTOKEN(pOuterType->getChild(0),RIGHT);
[ # # ][ # # ]
[ # # ]
1610 : : }
1611 : :
1612 [ # # ]: 0 : if(bCheck)
1613 : : { // here we know that we have to check on which side our table resides
1614 [ # # ]: 0 : const OSQLParseNode* pTableRef = pJoin->getByRule(::connectivity::OSQLParseNode::qualified_join);
1615 [ # # ]: 0 : if(bLeftSide)
1616 [ # # ]: 0 : pTableRef = pJoin->getChild(0);
1617 : : else
1618 [ # # ]: 0 : pTableRef = pJoin->getChild(3);
1619 : : OSL_ENSURE(SQL_ISRULE(pTableRef,table_ref),"Must be a tableref here!");
1620 : :
1621 [ # # ]: 0 : ::rtl::OUString sTableRange = OSQLParseNode::getTableRange(pTableRef);
1622 [ # # ]: 0 : if(sTableRange.isEmpty())
1623 [ # # ][ # # ]: 0 : pTableRef->getChild(0)->parseNodeToStr( sTableRange, _xConnection, NULL, sal_False, sal_False );
1624 : 0 : bOk = sTableRange == _sUpdateTableName;
1625 : : }
1626 : : }
1627 : : }
1628 : : else
1629 : : {
1630 [ # # ][ # # ]: 0 : OSQLParseNode* pWhereOpt = pSqlParseNode->getChild(3)->getChild(1);
1631 [ # # ][ # # ]: 0 : if ( pWhereOpt && !pWhereOpt->isLeaf() )
[ # # ]
1632 [ # # ][ # # ]: 0 : bOk = checkInnerJoin(pWhereOpt->getChild(1),_xConnection,_sUpdateTableName);
1633 : : }
1634 : : }
1635 [ # # ][ # # ]: 0 : return bOk;
1636 : : }
1637 : :
1638 : 2 : void ORowSetCache::clearInsertRow()
1639 : : {
1640 : : // we don't unbound the bookmark column
1641 [ + - ][ + - ]: 2 : if ( m_aInsertRow != m_pInsertMatrix->end() && m_aInsertRow->is() )
[ + - ][ + - ]
[ + - # # ]
1642 : : {
1643 [ + - ]: 2 : ORowSetValueVector::Vector::iterator aIter = (*m_aInsertRow)->get().begin()+1;
1644 : 2 : ORowSetValueVector::Vector::iterator aEnd = (*m_aInsertRow)->get().end();
1645 [ + - ][ + - ]: 64 : for(;aIter != aEnd;++aIter)
[ + + ]
1646 : : {
1647 [ + - ]: 62 : aIter->setBound(sal_False);
1648 [ + - ]: 62 : aIter->setModified(sal_False);
1649 [ + - ][ + - ]: 62 : aIter->setNull();
1650 : : }
1651 : : }
1652 : 2 : }
1653 : :
1654 : 1156 : ORowSetMatrix::iterator ORowSetCache::calcPosition() const
1655 : : {
1656 : 1156 : sal_Int32 nValue = (m_nPosition - m_nStartPos) - 1;
1657 : : CHECK_MATRIX_POS(nValue);
1658 [ + - ][ - + ]: 1156 : return ( nValue < 0 || nValue >= static_cast<sal_Int32>(m_pMatrix->size()) ) ? m_pMatrix->end() : (m_pMatrix->begin() + nValue);
[ + - ][ + - ]
[ + - ]
[ # # # # ]
1659 : : }
1660 : :
1661 : 44 : TORowSetOldRowHelperRef ORowSetCache::registerOldRow()
1662 : : {
1663 [ + - ][ + - ]: 44 : TORowSetOldRowHelperRef pRef = new ORowSetOldRowHelper(ORowSetRow());
[ + - ][ + - ]
1664 [ + - ]: 44 : m_aOldRows.push_back(pRef);
1665 : 44 : return pRef;
1666 : : }
1667 : :
1668 : 4 : void ORowSetCache::deregisterOldRow(const TORowSetOldRowHelperRef& _rRow)
1669 : : {
1670 : 4 : TOldRowSetRows::iterator aOldRowEnd = m_aOldRows.end();
1671 [ + - ][ + - ]: 8 : for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
1672 : : {
1673 [ + + ]: 8 : if ( aOldRowIter->get() == _rRow.get() )
1674 : : {
1675 [ + - ]: 4 : m_aOldRows.erase(aOldRowIter);
1676 : 4 : break;
1677 : : }
1678 : :
1679 : : }
1680 : 4 : }
1681 : :
1682 : 0 : sal_Bool ORowSetCache::reFillMatrix(sal_Int32 _nNewStartPos,sal_Int32 _nNewEndPos)
1683 : : {
1684 : : OSL_ENSURE( _nNewEndPos - _nNewStartPos == m_nFetchSize, "reFillMatrix called with Start/EndPos not m_nFetchSize apart");
1685 [ # # ]: 0 : const TOldRowSetRows::const_iterator aOldRowEnd = m_aOldRows.end();
1686 [ # # ][ # # ]: 0 : for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
1687 : : {
1688 [ # # ][ # # ]: 0 : if ( aOldRowIter->is() && (*aOldRowIter)->getRow().is() )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1689 [ # # ][ # # ]: 0 : (*aOldRowIter)->setRow(new ORowSetValueVector( *((*aOldRowIter)->getRow()) ) );
[ # # ][ # # ]
[ # # ][ # # ]
1690 : : }
1691 : 0 : sal_Int32 nNewSt = _nNewStartPos;
1692 [ # # ]: 0 : sal_Bool bRet = fillMatrix(nNewSt,_nNewEndPos);
1693 : 0 : m_nStartPos = nNewSt;
1694 : 0 : m_nEndPos = _nNewEndPos;
1695 [ # # ]: 0 : rotateCacheIterator(static_cast<ORowSetMatrix::difference_type>(m_nFetchSize+1)); // invalidate every iterator
1696 : 0 : return bRet;
1697 : : }
1698 : :
1699 : 20 : sal_Bool ORowSetCache::fill(ORowSetMatrix::iterator& _aIter,const ORowSetMatrix::const_iterator& _aEnd,sal_Int32& _nPos,sal_Bool _bCheck)
1700 : : {
1701 : 20 : const sal_Int32 nColumnCount = m_xMetaData->getColumnCount();
1702 [ + + ][ + - ]: 22 : for(; _bCheck && _aIter != _aEnd; _aIter++, _nPos++)
[ + + ]
1703 : : {
1704 [ + - ]: 2 : if ( !_aIter->is() )
1705 [ + - ]: 2 : *_aIter = new ORowSetValueVector(nColumnCount);
1706 : : else
1707 : : {
1708 [ # # ]: 0 : const TOldRowSetRows::const_iterator aOldRowEnd = m_aOldRows.end();
1709 [ # # ][ # # ]: 0 : for (TOldRowSetRows::iterator aOldRowIter = m_aOldRows.begin(); aOldRowIter != aOldRowEnd; ++aOldRowIter)
1710 : : {
1711 [ # # ][ # # ]: 0 : if ( (*aOldRowIter)->getRow() == *_aIter )
[ # # ]
1712 [ # # ][ # # ]: 0 : *_aIter = new ORowSetValueVector(nColumnCount);
1713 : : }
1714 : : }
1715 : 2 : m_pCacheSet->fillValueRow(*_aIter, _nPos);
1716 : 2 : _bCheck = m_pCacheSet->next();
1717 : : }
1718 : 20 : return _bCheck;
1719 : : }
1720 : :
1721 : 8 : bool ORowSetCache::isResultSetChanged() const
1722 : : {
1723 : 8 : return m_pCacheSet->isResultSetChanged();
1724 : : }
1725 : :
1726 : 0 : void ORowSetCache::reset(const Reference< XResultSet>& _xDriverSet)
1727 : : {
1728 [ # # ][ # # ]: 0 : m_xMetaData.set(Reference< XResultSetMetaDataSupplier >(_xDriverSet,UNO_QUERY)->getMetaData());
[ # # ]
1729 : 0 : m_pCacheSet->reset(_xDriverSet);
1730 : :
1731 : 0 : m_bRowCountFinal = sal_False;
1732 : 0 : m_nRowCount = 0;
1733 : 0 : reFillMatrix(m_nStartPos,m_nEndPos);
1734 : 0 : }
1735 : :
1736 : 12 : void ORowSetCache::impl_updateRowFromCache_throw(ORowSetValueVector::Vector& io_aRow
1737 : : ,::std::vector<sal_Int32>& o_ChangedColumns)
1738 : : {
1739 [ - + ]: 12 : if ( o_ChangedColumns.size() > 1 )
1740 : : {
1741 : 0 : ORowSetMatrix::iterator aIter = m_pMatrix->begin();
1742 [ # # ][ # # ]: 0 : for(;aIter != m_pMatrix->end();++aIter)
1743 : : {
1744 [ # # ][ # # ]: 0 : if ( aIter->is() && m_pCacheSet->updateColumnValues((*aIter)->get(),io_aRow,o_ChangedColumns))
[ # # ][ # # ]
1745 : : {
1746 : 0 : break;
1747 : : }
1748 : : }
1749 : :
1750 [ # # ][ # # ]: 0 : if ( aIter == m_pMatrix->end() )
1751 : : {
1752 [ # # ]: 0 : m_pCacheSet->fillMissingValues(io_aRow);
1753 : : }
1754 : : }
1755 : 12 : }
1756 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|