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