xref: /trunk/main/dbaccess/source/core/api/KeySet.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle andor 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 #ifndef DBACCESS_CORE_API_KEYSET_HXX
32 #include "KeySet.hxx"
33 #endif
34 #ifndef _DBA_CORE_RESOURCE_HXX_
35 #include "core_resource.hxx"
36 #endif
37 #ifndef _DBA_CORE_RESOURCE_HRC_
38 #include "core_resource.hrc"
39 #endif
40 #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
41 #include <com/sun/star/beans/XPropertySet.hpp>
42 #endif
43 #ifndef _COM_SUN_STAR_SDBC_XDATABASEMETADATA_HPP_
44 #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
45 #endif
46 #include <com/sun/star/sdbc/ColumnValue.hpp>
47 #ifndef _COM_SUN_STAR_SDBC_XPREPAREDSTATEMENT_HPP_
48 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
49 #endif
50 #ifndef _COM_SUN_STAR_SDBCxParameterS_HPP_
51 #include <com/sun/star/sdbc/XParameters.hpp>
52 #endif
53 #ifndef _COM_SUN_STAR_SDBC_XGENERATEDRESULTSET_HPP_
54 #include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
55 #endif
56 #ifndef _COM_SUN_STAR_SDBC_XCOLUMNLOCATE_HPP_
57 #include <com/sun/star/sdbc/XColumnLocate.hpp>
58 #endif
59 #ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
60 #include <com/sun/star/container/XIndexAccess.hpp>
61 #endif
62 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
63 #include "dbastrings.hrc"
64 #endif
65 #ifndef _DBASHARED_APITOOLS_HXX_
66 #include "apitools.hxx"
67 #endif
68 #ifndef _COM_SUN_STAR_SDBCX_XKEYSSUPPLIER_HPP_
69 #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
70 #endif
71 #ifndef _COM_SUN_STAR_SDB_XSINGLESELECTQUERYCOMPOSER_HPP_
72 #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
73 #endif
74 #ifndef _COM_SUN_STAR_SDBCX_XINDEXESSUPPLIER_HPP_
75 #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
76 #endif
77 #ifndef _CPPUHELPER_TYPEPROVIDER_HXX_
78 #include <cppuhelper/typeprovider.hxx>
79 #endif
80 #ifndef _COMPHELPER_TYPES_HXX_
81 #include <comphelper/types.hxx>
82 #endif
83 #ifndef _COM_SUN_STAR_SDBCX_KEYTYPE_HPP_
84 #include <com/sun/star/sdbcx/KeyType.hpp>
85 #endif
86 #ifndef _CONNECTIVITY_DBTOOLS_HXX_
87 #include <connectivity/dbtools.hxx>
88 #endif
89 #ifndef _DBHELPER_DBEXCEPTION_HXX_
90 #include <connectivity/dbexception.hxx>
91 #endif
92 #include <list>
93 #include <algorithm>
94 #include <string.h>
95 #ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
96 #include <com/sun/star/io/XInputStream.hpp>
97 #endif
98 #ifndef _COM_SUN_STAR_SDBCX_XTABLESSUPPLIER_HPP_
99 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
100 #endif
101 #ifndef DBACCESS_CORE_API_QUERYCOMPOSER_HXX
102 #include "querycomposer.hxx"
103 #endif
104 #ifndef DBACCESS_SOURCE_CORE_INC_COMPOSERTOOLS_HXX
105 #include "composertools.hxx"
106 #endif
107 #ifndef _TOOLS_DEBUG_HXX
108 #include <tools/debug.hxx>
109 #endif
110 #include <string.h>
111 #include <rtl/logfile.hxx>
112 #include "PrivateRow.hxx"
113 
114 using namespace dbaccess;
115 using namespace ::connectivity;
116 using namespace ::dbtools;
117 using namespace ::com::sun::star::uno;
118 using namespace ::com::sun::star::beans;
119 using namespace ::com::sun::star::sdbc;
120 using namespace ::com::sun::star::sdb;
121 using namespace ::com::sun::star::sdbcx;
122 using namespace ::com::sun::star::container;
123 using namespace ::com::sun::star::lang;
124 using namespace ::com::sun::star::util;
125 using namespace ::com::sun::star::io;
126 using namespace ::com::sun::star;
127 using namespace ::cppu;
128 using namespace ::osl;
129 
130 namespace
131 {
132     void lcl_fillIndexColumns(const Reference<XIndexAccess>& _xIndexes, ::std::vector< Reference<XNameAccess> >& _rAllIndexColumns)
133     {
134         if ( _xIndexes.is() )
135         {
136             Reference<XPropertySet> xIndexColsSup;
137             sal_Int32 nCount = _xIndexes->getCount();
138             for(sal_Int32 j = 0 ; j < nCount ; ++j)
139             {
140                 xIndexColsSup.set(_xIndexes->getByIndex(j),UNO_QUERY);
141                 if( xIndexColsSup.is()
142                     && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE))
143                     && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX))
144                 )
145                     _rAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns());
146             }
147         }
148     }
149 }
150 DBG_NAME(OKeySet)
151 // -------------------------------------------------------------------------
152 OKeySet::OKeySet(const connectivity::OSQLTable& _xTable,
153                  const Reference< XIndexAccess>& _xTableKeys,
154                  const ::rtl::OUString& _rUpdateTableName,    // this can be the alias or the full qualified name
155                  const Reference< XSingleSelectQueryAnalyzer >& _xComposer,
156                  const ORowSetValueVector& _aParameterValueForCache,
157                  sal_Int32 i_nMaxRows,
158                  sal_Int32& o_nRowCount)
159             :OCacheSet(i_nMaxRows)
160             ,m_aParameterValueForCache(_aParameterValueForCache)
161             ,m_pKeyColumnNames(NULL)
162             ,m_pColumnNames(NULL)
163             ,m_pParameterNames(NULL)
164             ,m_pForeignColumnNames(NULL)
165             ,m_xTable(_xTable)
166             ,m_xTableKeys(_xTableKeys)
167             ,m_xComposer(_xComposer)
168             ,m_sUpdateTableName(_rUpdateTableName)
169             ,m_rRowCount(o_nRowCount)
170             ,m_bRowCountFinal(sal_False)
171 {
172     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::OKeySet" );
173     DBG_CTOR(OKeySet,NULL);
174 
175 }
176 // -----------------------------------------------------------------------------
177 OKeySet::~OKeySet()
178 {
179     try
180     {
181         ::comphelper::disposeComponent(m_xStatement);
182     }
183     catch(Exception&)
184     {
185         m_xStatement = NULL;
186     }
187     catch(...)
188     {
189         OSL_ENSURE(0,"Unknown Exception occured");
190     }
191     m_xComposer = NULL;
192 
193     DBG_DTOR(OKeySet,NULL);
194 }
195 void OKeySet::initColumns()
196 {
197     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
198     bool bCase = (xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()) ? true : false;
199     m_pKeyColumnNames.reset( new SelectColumnsMetaData(bCase) );
200     m_pColumnNames.reset( new SelectColumnsMetaData(bCase) );
201     m_pParameterNames.reset( new SelectColumnsMetaData(bCase) );
202     m_pForeignColumnNames.reset( new SelectColumnsMetaData(bCase) );
203 }
204 void OKeySet::findTableColumnsMatching_throw(   const Any& i_aTable,
205                                                 const ::rtl::OUString& i_rUpdateTableName,
206                                                 const Reference<XDatabaseMetaData>& i_xMeta,
207                                                 const Reference<XNameAccess>& i_xQueryColumns,
208                                                 ::std::auto_ptr<SelectColumnsMetaData>& o_pKeyColumnNames)
209 {
210     // first ask the database itself for the best columns which can be used
211     Sequence< ::rtl::OUString> aBestColumnNames;
212     Reference<XNameAccess> xKeyColumns  = getPrimaryKeyColumns_throw(i_aTable);
213     if ( xKeyColumns.is() )
214         aBestColumnNames = xKeyColumns->getElementNames();
215 
216     const Reference<XColumnsSupplier> xTblColSup(i_aTable,UNO_QUERY_THROW);
217     const Reference<XNameAccess> xTblColumns = xTblColSup->getColumns();
218     // locate parameter in select columns
219     Reference<XParametersSupplier> xParaSup(m_xComposer,UNO_QUERY);
220     Reference<XIndexAccess> xQueryParameters = xParaSup->getParameters();
221     const sal_Int32 nParaCount = xQueryParameters->getCount();
222     Sequence< ::rtl::OUString> aParameterColumns(nParaCount);
223     for(sal_Int32 i = 0; i< nParaCount;++i)
224     {
225         Reference<XPropertySet> xPara(xQueryParameters->getByIndex(i),UNO_QUERY_THROW);
226         xPara->getPropertyValue(PROPERTY_REALNAME) >>= aParameterColumns[i];
227     }
228 
229     ::rtl::OUString sUpdateTableName( i_rUpdateTableName );
230     if ( sUpdateTableName.getLength() == 0 )
231     {
232         OSL_ENSURE( false, "OKeySet::findTableColumnsMatching_throw: This is a fallback only - it won't work when the table has an alias name." );
233         // If i_aTable originates from a query composer, and is a table which appears with an alias in the SELECT statement,
234         // then the below code will not produce correct results.
235         // For instance, imagine a "SELECT alias.col FROM table AS alias". Now i_aTable would be the table named
236         // "table", so our sUpdateTableName would be "table" as well - not the information about the "alias" is
237         // already lost here.
238         // now getColumnPositions would travers the columns, and check which of them belong to the table denoted
239         // by sUpdateTableName. Since the latter is "table", but the columns only know that they belong to a table
240         // named "alias", there will be no matching - so getColumnPositions wouldn't find anything.
241 
242         ::rtl::OUString sCatalog, sSchema, sTable;
243         Reference<XPropertySet> xTableProp( i_aTable, UNO_QUERY_THROW );
244         xTableProp->getPropertyValue( PROPERTY_CATALOGNAME )>>= sCatalog;
245         xTableProp->getPropertyValue( PROPERTY_SCHEMANAME ) >>= sSchema;
246         xTableProp->getPropertyValue( PROPERTY_NAME )       >>= sTable;
247         sUpdateTableName = dbtools::composeTableName( i_xMeta, sCatalog, sSchema, sTable, sal_False, ::dbtools::eInDataManipulation );
248     }
249 
250     ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,sUpdateTableName,(*o_pKeyColumnNames),true);
251     ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),sUpdateTableName,(*m_pColumnNames),true);
252     ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,sUpdateTableName,(*m_pParameterNames),true);
253 
254     if ( o_pKeyColumnNames->empty() )
255     {
256         ::dbtools::throwGenericSQLException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Could not find any key column." ) ), *this );
257     }
258 
259     for (   SelectColumnsMetaData::const_iterator keyColumn = o_pKeyColumnNames->begin();
260             keyColumn != o_pKeyColumnNames->end();
261             ++keyColumn
262         )
263     {
264         if ( !xTblColumns->hasByName( keyColumn->second.sRealName ) )
265             continue;
266 
267         Reference<XPropertySet> xProp( xTblColumns->getByName( keyColumn->second.sRealName ), UNO_QUERY );
268         sal_Bool bAuto = sal_False;
269         if ( ( xProp->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= bAuto ) && bAuto )
270             m_aAutoColumns.push_back( keyColumn->first );
271     }
272 }
273 ::rtl::OUStringBuffer OKeySet::createKeyFilter()
274 {
275     static ::rtl::OUString aAnd     = ::rtl::OUString::createFromAscii(" AND ");
276     const ::rtl::OUString aQuote    = getIdentifierQuoteString();
277     ::rtl::OUStringBuffer aFilter;
278     static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM("."));
279     static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
280     // create the where clause
281     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
282     SelectColumnsMetaData::iterator aPosEnd = m_pKeyColumnNames->end();
283     for(SelectColumnsMetaData::iterator aPosIter = m_pKeyColumnNames->begin();aPosIter != aPosEnd;)
284     {
285         aFilter.append(::dbtools::quoteTableName( xMeta,aPosIter->second.sTableName,::dbtools::eInDataManipulation));
286         aFilter.append(s_sDot);
287         aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName));
288         aFilter.append(s_sParam);
289         ++aPosIter;
290         if(aPosIter != aPosEnd)
291             aFilter.append(aAnd);
292     }
293     return aFilter;
294 }
295 // -----------------------------------------------------------------------------
296 void OKeySet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter)
297 {
298     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::construct" );
299     OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
300     initColumns();
301 
302     Reference<XNameAccess> xKeyColumns  = getKeyColumns();
303     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
304     Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY);
305     const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns();
306     findTableColumnsMatching_throw(makeAny(m_xTable),m_sUpdateTableName,xMeta,xQueryColumns,m_pKeyColumnNames);
307 
308     // the first row is empty because it's now easier for us to distinguish when we are beforefirst or first
309     // without extra varaible to be set
310     m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL))));
311     m_aKeyIter = m_aKeyMap.begin();
312 
313     ::rtl::OUStringBuffer aFilter = createKeyFilter();
314 
315     Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
316     Reference< XMultiServiceFactory >  xFactory(m_xConnection, UNO_QUERY_THROW);
317     Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
318     xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
319     Reference<XTablesSupplier> xTabSup(xAnalyzer,uno::UNO_QUERY);
320     Reference<XNameAccess> xSelectTables(xTabSup->getTables(),uno::UNO_QUERY);
321     const Sequence< ::rtl::OUString> aSeq = xSelectTables->getElementNames();
322     if ( aSeq.getLength() > 1 ) // special handling for join
323     {
324         static ::rtl::OUString aAnd     = ::rtl::OUString::createFromAscii(" AND ");
325         const ::rtl::OUString aQuote    = getIdentifierQuoteString();
326         static ::rtl::OUString s_sDot(RTL_CONSTASCII_USTRINGPARAM("."));
327         static ::rtl::OUString s_sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
328         const ::rtl::OUString* pIter = aSeq.getConstArray();
329         const ::rtl::OUString* pEnd   = pIter + aSeq.getLength();
330         for(;pIter != pEnd;++pIter)
331         {
332             if ( *pIter != m_sUpdateTableName )
333             {
334                 connectivity::OSQLTable xSelColSup(xSelectTables->getByName(*pIter),uno::UNO_QUERY);
335                 Reference<XPropertySet> xProp(xSelColSup,uno::UNO_QUERY);
336                 ::rtl::OUString sSelectTableName = ::dbtools::composeTableName( xMeta, xProp, ::dbtools::eInDataManipulation, false, false, false );
337 
338                 ::dbaccess::getColumnPositions(xQueryColumns,xSelColSup->getColumns()->getElementNames(),sSelectTableName,(*m_pForeignColumnNames));
339 
340                 SelectColumnsMetaData::iterator aPosEnd = (*m_pForeignColumnNames).end();
341                 for(SelectColumnsMetaData::iterator aPosIter = (*m_pForeignColumnNames).begin();aPosIter != aPosEnd;++aPosIter)
342                 {
343                     // look for columns not in the source columns to use them as filter as well
344                     // if ( !xSourceColumns->hasByName(aPosIter->first) )
345                     {
346                         if ( aFilter.getLength() )
347                             aFilter.append(aAnd);
348                         aFilter.append(::dbtools::quoteName( aQuote,sSelectTableName));
349                         aFilter.append(s_sDot);
350                         aFilter.append(::dbtools::quoteName( aQuote,aPosIter->second.sRealName));
351                         aFilter.append(s_sParam);
352                     }
353                 }
354                 break;
355             }
356         }
357     } // if ( aSeq.getLength() > 1 ) // special handling for join
358     executeStatement(aFilter,i_sRowSetFilter,xAnalyzer);
359 }
360 void OKeySet::executeStatement(::rtl::OUStringBuffer& io_aFilter,const ::rtl::OUString& i_sRowSetFilter,Reference<XSingleSelectQueryComposer>& io_xAnalyzer)
361 {
362     bool bFilterSet = i_sRowSetFilter.getLength() != 0;
363     if ( bFilterSet )
364     {
365         FilterCreator aFilterCreator;
366         aFilterCreator.append( i_sRowSetFilter );
367         aFilterCreator.append( io_aFilter.makeStringAndClear() );
368         io_aFilter = aFilterCreator.getComposedAndClear();
369     }
370     io_xAnalyzer->setFilter(io_aFilter.makeStringAndClear());
371     if ( bFilterSet )
372     {
373         Sequence< Sequence< PropertyValue > > aFilter2 = io_xAnalyzer->getStructuredFilter();
374         const Sequence< PropertyValue >* pOr = aFilter2.getConstArray();
375         const Sequence< PropertyValue >* pOrEnd = pOr + aFilter2.getLength();
376         for(;pOr != pOrEnd;++pOr)
377         {
378             const PropertyValue* pAnd = pOr->getConstArray();
379             const PropertyValue* pAndEnd = pAnd + pOr->getLength();
380             for(;pAnd != pAndEnd;++pAnd)
381             {
382                 ::rtl::OUString sValue;
383                 if ( !(pAnd->Value >>= sValue) || !(sValue.equalsAscii("?") || sValue.matchAsciiL(":",1,0)) )
384                 { // we have a criteria which has to be taken into account for updates
385                     m_aFilterColumns.push_back(pAnd->Name);
386                 }
387             }
388         }
389     }
390     m_xStatement = m_xConnection->prepareStatement(io_xAnalyzer->getQueryWithSubstitution());
391     ::comphelper::disposeComponent(io_xAnalyzer);
392 }
393 // -------------------------------------------------------------------------
394 Any SAL_CALL OKeySet::getBookmark() throw(SQLException, RuntimeException)
395 {
396     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBookmark" );
397     OSL_ENSURE(m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin(),
398         "getBookmark is only possible when we stand on a valid row!");
399     return makeAny(m_aKeyIter->first);
400 }
401 
402 // -------------------------------------------------------------------------
403 sal_Bool SAL_CALL OKeySet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException)
404 {
405     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToBookmark" );
406     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
407     m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark));
408     return m_aKeyIter != m_aKeyMap.end();
409 }
410 // -------------------------------------------------------------------------
411 sal_Bool SAL_CALL OKeySet::moveRelativeToBookmark( const Any& bookmark, sal_Int32 rows ) throw(SQLException, RuntimeException)
412 {
413     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveRelativeToBookmark" );
414     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
415     m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark));
416     if(m_aKeyIter != m_aKeyMap.end())
417     {
418         relative(rows);
419     }
420 
421     return !isBeforeFirst() && !isAfterLast();
422 }
423 // -------------------------------------------------------------------------
424 sal_Int32 SAL_CALL OKeySet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException)
425 {
426     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::compareBookmarks" );
427     sal_Int32 nFirst = 0, nSecond = 0;
428     _first >>= nFirst;
429     _second >>= nSecond;
430 
431     return (nFirst != nSecond) ? CompareBookmark::NOT_EQUAL : CompareBookmark::EQUAL;
432 }
433 // -------------------------------------------------------------------------
434 sal_Bool SAL_CALL OKeySet::hasOrderedBookmarks(  ) throw(SQLException, RuntimeException)
435 {
436     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hasOrderedBookmarks" );
437     return sal_True;
438 }
439 // -------------------------------------------------------------------------
440 sal_Int32 SAL_CALL OKeySet::hashBookmark( const Any& bookmark ) throw(SQLException, RuntimeException)
441 {
442     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::hashBookmark" );
443     return ::comphelper::getINT32(bookmark);
444 }
445 // -------------------------------------------------------------------------
446 // ::com::sun::star::sdbcx::XDeleteRows
447 Sequence< sal_Int32 > SAL_CALL OKeySet::deleteRows( const Sequence< Any >& rows ,const connectivity::OSQLTable& _xTable) throw(SQLException, RuntimeException)
448 {
449     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRows" );
450     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
451     fillTableName(xSet);
452 
453     ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM ");
454     aSql.append(m_aComposedTableName);
455     aSql.append(::rtl::OUString::createFromAscii(" WHERE "));
456 
457     // list all cloumns that should be set
458     const ::rtl::OUString aQuote    = getIdentifierQuoteString();
459     static ::rtl::OUString aAnd     = ::rtl::OUString::createFromAscii(" AND ");
460     static ::rtl::OUString aOr      = ::rtl::OUString::createFromAscii(" OR ");
461     static ::rtl::OUString aEqual   = ::rtl::OUString::createFromAscii(" = ?");
462 
463 
464     // use keys and indexes for excat postioning
465     // first the keys
466     Reference<XNameAccess> xKeyColumns = getKeyColumns();
467 
468     ::rtl::OUStringBuffer aCondition = ::rtl::OUString::createFromAscii("( ");
469 
470     SelectColumnsMetaData::const_iterator aIter = (*m_pKeyColumnNames).begin();
471     SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
472     for(;aIter != aPosEnd;++aIter)
473     {
474         aCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
475         aCondition.append(aEqual);
476         aCondition.append(aAnd);
477     }
478     aCondition.setLength(aCondition.getLength()-5);
479     const ::rtl::OUString sCon( aCondition.makeStringAndClear() );
480 
481     const Any* pBegin   = rows.getConstArray();
482     const Any* pEnd     = pBegin + rows.getLength();
483 
484     Sequence< Any > aKeys;
485     for(;pBegin != pEnd;++pBegin)
486     {
487         aSql.append(sCon);
488         aSql.append(aOr);
489     }
490     aSql.setLength(aSql.getLength()-3);
491 
492     // now create end execute the prepared statement
493 
494     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
495     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
496 
497     pBegin  = rows.getConstArray();
498     sal_Int32 i=1;
499     for(;pBegin != pEnd;++pBegin)
500     {
501         m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(*pBegin));
502         if(m_aKeyIter != m_aKeyMap.end())
503         {
504             connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyIter = m_aKeyIter->second.first->get().begin();
505             connectivity::ORowVector< ORowSetValue >::Vector::iterator aKeyEnd = m_aKeyIter->second.first->get().end();
506             SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
507             for(sal_uInt16 j = 0;aKeyIter != aKeyEnd;++aKeyIter,++j,++aPosIter)
508             {
509                 setParameter(i++,xParameter,*aKeyIter,aPosIter->second.nType,aPosIter->second.nScale);
510             }
511         }
512     }
513 
514     sal_Bool bOk = xPrep->executeUpdate() > 0;
515     Sequence< sal_Int32 > aRet(rows.getLength());
516     memset(aRet.getArray(),bOk,sizeof(sal_Int32)*aRet.getLength());
517     if(bOk)
518     {
519         pBegin  = rows.getConstArray();
520         pEnd    = pBegin + rows.getLength();
521 
522         for(;pBegin != pEnd;++pBegin)
523         {
524             sal_Int32 nPos = 0;
525             *pBegin >>= nPos;
526             if(m_aKeyIter == m_aKeyMap.find(nPos) && m_aKeyIter != m_aKeyMap.end())
527                 ++m_aKeyIter;
528             m_aKeyMap.erase(nPos);
529             m_bDeleted = sal_True;
530         }
531     }
532     return aRet;
533 }
534 // -------------------------------------------------------------------------
535 void SAL_CALL OKeySet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& _xTable  ) throw(SQLException, RuntimeException)
536 {
537     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::updateRow" );
538     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
539     fillTableName(xSet);
540 
541     ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("UPDATE ");
542     aSql.append(m_aComposedTableName);
543     aSql.append(::rtl::OUString::createFromAscii(" SET "));
544     // list all cloumns that should be set
545     static ::rtl::OUString aPara    = ::rtl::OUString::createFromAscii(" = ?,");
546     ::rtl::OUString aQuote  = getIdentifierQuoteString();
547     static ::rtl::OUString aAnd     = ::rtl::OUString::createFromAscii(" AND ");
548     ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL"));
549     ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
550 
551     // use keys and indexes for excat postioning
552     // first the keys
553     Reference<XNameAccess> xKeyColumns = getKeyColumns();
554 
555     // second the indexes
556     Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
557     Reference<XIndexAccess> xIndexes;
558     if ( xIndexSup.is() )
559         xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
560 
561 
562     ::std::vector< Reference<XNameAccess> > aAllIndexColumns;
563     lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
564 
565     ::rtl::OUString aColumnName;
566     ::rtl::OUStringBuffer sKeyCondition,sIndexCondition;
567     ::std::vector<sal_Int32> aIndexColumnPositions;
568 
569     const sal_Int32 nOldLength = aSql.getLength();
570     sal_Int32 i = 1;
571     // here we build the condition part for the update statement
572     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
573     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
574     for(;aIter != aEnd;++aIter,++i)
575     {
576         //if(xKeyColumns.is() && xKeyColumns->hasByName(aIter->first))
577         if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
578         {
579             sKeyCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
580             if((_rOrginalRow->get())[aIter->second.nPosition].isNull())
581                 sKeyCondition.append(sIsNull);
582             else
583                 sKeyCondition.append(sParam);
584             sKeyCondition.append(aAnd);
585         }
586         else
587         {
588             ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end();
589             for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin();
590                 aIndexIter != aIndexEnd;++aIndexIter)
591             {
592                 if((*aIndexIter)->hasByName(aIter->first))
593                 {
594                     sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
595                     if((_rOrginalRow->get())[aIter->second.nPosition].isNull())
596                         sIndexCondition.append(sIsNull);
597                     else
598                     {
599                         sIndexCondition.append(sParam);
600                         aIndexColumnPositions.push_back(aIter->second.nPosition);
601                     }
602                     sIndexCondition.append(aAnd);
603                     break;
604                 }
605             }
606         }
607         if((_rInsertRow->get())[aIter->second.nPosition].isModified())
608         {
609             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
610             aSql.append(aPara);
611         }
612     }
613 
614     if( aSql.getLength() != nOldLength )
615     {
616         aSql.setLength(aSql.getLength()-1);
617     }
618     else
619         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection );
620 
621     if(sKeyCondition.getLength() || sIndexCondition.getLength())
622     {
623         aSql.append(::rtl::OUString::createFromAscii(" WHERE "));
624         if(sKeyCondition.getLength() && sIndexCondition.getLength())
625         {
626             aSql.append(sKeyCondition.makeStringAndClear());
627             aSql.append(sIndexCondition.makeStringAndClear());
628         }
629         else if(sKeyCondition.getLength())
630         {
631             aSql.append(sKeyCondition.makeStringAndClear());
632         }
633         else if(sIndexCondition.getLength())
634         {
635             aSql.append(sIndexCondition.makeStringAndClear());
636         }
637         aSql.setLength(aSql.getLength()-5); // remove the last AND
638     }
639     else
640         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection );
641 
642     // now create end execute the prepared statement
643 
644     ::rtl::OUString sEmpty;
645     executeUpdate(_rInsertRow ,_rOrginalRow,aSql.makeStringAndClear(),sEmpty,aIndexColumnPositions);
646 }
647 // -----------------------------------------------------------------------------
648 void OKeySet::executeUpdate(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,const ::std::vector<sal_Int32>& _aIndexColumnPositions)
649 {
650     // now create end execute the prepared statement
651     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
652     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
653 
654     bool bRefetch = true;
655     Reference<XRow> xRow;
656     sal_Int32 i = 1;
657     // first the set values
658     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
659     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
660     sal_uInt16 j = 0;
661     for(;aIter != aEnd;++aIter,++j)
662     {
663         if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName )
664         {
665             sal_Int32 nPos = aIter->second.nPosition;
666             if((_rInsertRow->get())[nPos].isModified())
667             {
668                 if ( bRefetch )
669                 {
670                     bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end();
671                 }
672                 impl_convertValue_throw(_rInsertRow,aIter->second);
673                 (_rInsertRow->get())[nPos].setSigned((_rOrginalRow->get())[nPos].isSigned());
674                 setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale);
675             }
676         }
677     }
678     // and then the values of the where condition
679     aIter = m_pKeyColumnNames->begin();
680     aEnd = m_pKeyColumnNames->end();
681     j = 0;
682     for(;aIter != aEnd;++aIter,++j)
683     {
684         if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName )
685         {
686             setParameter(i++,xParameter,(_rOrginalRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale);
687         }
688     }
689     if ( !_aIndexColumnPositions.empty() )
690     {
691         // now we have to set the index values
692         ::std::vector<sal_Int32>::const_iterator aIdxColIter = _aIndexColumnPositions.begin();
693         ::std::vector<sal_Int32>::const_iterator aIdxColEnd = _aIndexColumnPositions.end();
694         j = 0;
695         aIter = m_pColumnNames->begin();
696         for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++j,++aIter)
697         {
698             setParameter(i,xParameter,(_rOrginalRow->get())[*aIdxColIter],(_rOrginalRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale);
699         }
700     }
701     const sal_Int32 nRowsUpdated = xPrep->executeUpdate();
702     m_bUpdated =  nRowsUpdated > 0;
703     if(m_bUpdated)
704     {
705         const sal_Int32 nBookmark = ::comphelper::getINT32((_rInsertRow->get())[0].getAny());
706         m_aKeyIter = m_aKeyMap.find(nBookmark);
707         m_aKeyIter->second.second.first = 2;
708         m_aKeyIter->second.second.second = xRow;
709         copyRowValue(_rInsertRow,m_aKeyIter->second.first,nBookmark);
710         tryRefetch(_rInsertRow,bRefetch);
711     }
712 }
713 // -------------------------------------------------------------------------
714 void SAL_CALL OKeySet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException)
715 {
716     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::insertRow" );
717     ::rtl::OUStringBuffer aSql(::rtl::OUString::createFromAscii("INSERT INTO "));
718     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
719     fillTableName(xSet);
720 
721     aSql.append(m_aComposedTableName);
722     aSql.append(::rtl::OUString::createFromAscii(" ( "));
723     // set values and column names
724     ::rtl::OUStringBuffer aValues(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" VALUES ( ")));
725     static ::rtl::OUString aPara(RTL_CONSTASCII_USTRINGPARAM("?,"));
726     ::rtl::OUString aQuote = getIdentifierQuoteString();
727     static ::rtl::OUString aComma(RTL_CONSTASCII_USTRINGPARAM(","));
728 
729     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
730     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
731     sal_Int32 j = 1;
732     bool bRefetch = true;
733     sal_Bool bModified = sal_False;
734     for(;aIter != aEnd;++aIter,++j)
735     {
736         if((_rInsertRow->get())[aIter->second.nPosition].isModified())
737         {
738             if ( bRefetch )
739             {
740                 bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end();
741             }
742             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
743             aSql.append(aComma);
744             aValues.append(aPara);
745             bModified = sal_True;
746         }
747     }
748     if ( !bModified )
749         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection );
750 
751     aSql.setCharAt(aSql.getLength()-1,')');
752     aValues.setCharAt(aValues.getLength()-1,')');
753     aSql.append(aValues.makeStringAndClear());
754     // now create,fill and execute the prepared statement
755     ::rtl::OUString sEmpty;
756     executeInsert(_rInsertRow,aSql.makeStringAndClear(),sEmpty,bRefetch);
757 }
758 // -------------------------------------------------------------------------
759 void OKeySet::executeInsert( const ORowSetRow& _rInsertRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName,bool bRefetch )
760 {
761     // now create,fill and execute the prepared statement
762     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
763     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
764 
765     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
766     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
767     for(sal_Int32 i = 1;aIter != aEnd;++aIter)
768     {
769         if ( !i_sTableName.getLength() || aIter->second.sTableName == i_sTableName )
770         {
771             const sal_Int32 nPos = aIter->second.nPosition;
772             if((_rInsertRow->get())[nPos].isModified())
773             {
774                 if((_rInsertRow->get())[nPos].isNull())
775                     xParameter->setNull(i++,(_rInsertRow->get())[nPos].getTypeKind());
776                 else
777                 {
778                     impl_convertValue_throw(_rInsertRow,aIter->second);
779                     (_rInsertRow->get())[nPos].setSigned(m_aSignedFlags[nPos-1]);
780                     setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale);
781                 }
782             }
783         }
784     }
785 
786     m_bInserted = xPrep->executeUpdate() > 0;
787     sal_Bool bAutoValuesFetched = sal_False;
788     if ( m_bInserted )
789     {
790         // first insert the default values into the insertrow
791         aIter = m_pColumnNames->begin();
792         for(;aIter != aEnd;++aIter)
793         {
794             if ( !(_rInsertRow->get())[aIter->second.nPosition].isModified() )
795                 (_rInsertRow->get())[aIter->second.nPosition] = aIter->second.sDefaultValue;
796         }
797         try
798         {
799             Reference< XGeneratedResultSet > xGRes(xPrep, UNO_QUERY);
800             if ( xGRes.is() )
801             {
802                 Reference< XResultSet > xRes = xGRes->getGeneratedValues();
803                 Reference< XRow > xRow(xRes,UNO_QUERY);
804                 if ( xRow.is() && xRes->next() )
805                 {
806                     Reference< XResultSetMetaDataSupplier > xMdSup(xRes,UNO_QUERY);
807                     Reference< XResultSetMetaData > xMd = xMdSup->getMetaData();
808                     sal_Int32 nColumnCount = xMd->getColumnCount();
809                     ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin();
810                     ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end();
811                     for (sal_Int32 i = 1;aAutoIter !=  aAutoEnd && i <= nColumnCount; ++aAutoIter,++i)
812                     {
813 #if OSL_DEBUG_LEVEL > 1
814                         ::rtl::OUString sColumnName( xMd->getColumnName(i) );
815 #endif
816                         SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter);
817                         if ( aFind != m_pKeyColumnNames->end() )
818                             (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow);
819                     }
820                     bAutoValuesFetched = sal_True;
821                 }
822             }
823         }
824         catch(Exception&)
825         {
826             OSL_ENSURE(0,"Could not execute GeneratedKeys() stmt");
827         }
828     }
829 
830     ::comphelper::disposeComponent(xPrep);
831 
832     if ( !i_sTableName.getLength() && !bAutoValuesFetched && m_bInserted )
833     {
834         // first check if all key column values were set
835         const ::rtl::OUString sMax(RTL_CONSTASCII_USTRINGPARAM(" MAX("));
836         const ::rtl::OUString sMaxEnd(RTL_CONSTASCII_USTRINGPARAM("),"));
837         const ::rtl::OUString sQuote = getIdentifierQuoteString();
838         ::rtl::OUString sMaxStmt;
839         aEnd = m_pKeyColumnNames->end();
840         ::std::vector< ::rtl::OUString >::iterator aAutoIter = m_aAutoColumns.begin();
841         ::std::vector< ::rtl::OUString >::iterator aAutoEnd = m_aAutoColumns.end();
842         for (;aAutoIter !=  aAutoEnd; ++aAutoIter)
843         {
844             // we will only fetch values which are keycolumns
845             SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter);
846             if ( aFind != aEnd )
847             {
848                 sMaxStmt += sMax;
849                 sMaxStmt += ::dbtools::quoteName( sQuote,aFind->second.sRealName
850 );
851                 sMaxStmt += sMaxEnd;
852             }
853         }
854 
855         if(sMaxStmt.getLength())
856         {
857             sMaxStmt = sMaxStmt.replaceAt(sMaxStmt.getLength()-1,1,::rtl::OUString::createFromAscii(" "));
858             ::rtl::OUString sStmt = ::rtl::OUString::createFromAscii("SELECT ");
859             sStmt += sMaxStmt;
860             sStmt += ::rtl::OUString::createFromAscii("FROM ");
861             ::rtl::OUString sCatalog,sSchema,sTable;
862             ::dbtools::qualifiedNameComponents(m_xConnection->getMetaData(),m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
863             sStmt += ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
864             try
865             {
866                 // now fetch the autoincrement values
867                 Reference<XStatement> xStatement = m_xConnection->createStatement();
868                 Reference<XResultSet> xRes = xStatement->executeQuery(sStmt);
869                 Reference<XRow> xRow(xRes,UNO_QUERY);
870                 if(xRow.is() && xRes->next())
871                 {
872                     aAutoIter = m_aAutoColumns.begin();
873                     for (sal_Int32 i=1;aAutoIter != aAutoEnd; ++aAutoIter,++i)
874                     {
875                         // we will only fetch values which are keycolumns
876                         SelectColumnsMetaData::iterator aFind = m_pKeyColumnNames->find(*aAutoIter);
877                         if ( aFind != aEnd )
878                             (_rInsertRow->get())[aFind->second.nPosition].fill(i,aFind->second.nType,aFind->second.bNullable,xRow);
879                     }
880                 }
881                 ::comphelper::disposeComponent(xStatement);
882             }
883             catch(SQLException&)
884             {
885                 OSL_ENSURE(0,"Could not fetch with MAX() ");
886             }
887         }
888     }
889     if ( m_bInserted )
890     {
891         OKeySetMatrix::iterator aKeyIter = m_aKeyMap.end();
892         --aKeyIter;
893         ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >(m_pKeyColumnNames->size());
894         copyRowValue(_rInsertRow,aKeyRow,aKeyIter->first + 1);
895 
896         m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(aKeyIter->first + 1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(1,NULL)))).first;
897         // now we set the bookmark for this row
898         (_rInsertRow->get())[0] = makeAny((sal_Int32)m_aKeyIter->first);
899         tryRefetch(_rInsertRow,bRefetch);
900     }
901 }
902 void OKeySet::tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch)
903 {
904     if ( bRefetch )
905     {
906         // we just areassign the base members
907         try
908         {
909             Reference< XParameters > xParameter(m_xStatement,UNO_QUERY);
910             OSL_ENSURE(xParameter.is(),"No Parameter interface!");
911             xParameter->clearParameters();
912 
913             sal_Int32 nPos=1;
914             connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter;
915             connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd;
916             OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first);
917             if ( aUpdateFind == m_aUpdatedParameter.end() )
918             {
919                 aParaIter = m_aParameterValueForCache.get().begin();
920                 aParaEnd = m_aParameterValueForCache.get().end();
921             }
922             else
923             {
924                 aParaIter = aUpdateFind->second.get().begin();
925                 aParaEnd = aUpdateFind->second.get().end();
926             }
927 
928             for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos)
929             {
930                 ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() );
931             }
932             connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter2 = m_aKeyIter->second.first->get().begin();
933             SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
934             SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
935             for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos)
936                 setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale);
937             aPosIter = (*m_pForeignColumnNames).begin();
938             aPosEnd = (*m_pForeignColumnNames).end();
939             for(;aPosIter != aPosEnd;++aPosIter,++aIter2,++nPos)
940                 setParameter(nPos,xParameter,*aIter2,aPosIter->second.nType,aPosIter->second.nScale);
941 
942             m_xSet = m_xStatement->executeQuery();
943             OSL_ENSURE(m_xSet.is(),"No resultset form statement!");
944             bRefetch = m_xSet->next();
945         }
946         catch(Exception)
947         {
948             bRefetch = false;
949         }
950     }
951     if ( !bRefetch )
952     {
953         m_aKeyIter->second.second.second = new OPrivateRow(_rInsertRow->get());
954     }
955 }
956 // -----------------------------------------------------------------------------
957 void OKeySet::copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark)
958 {
959     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::copyRowValue" );
960     connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = _rKeyRow->get().begin();
961 
962     // check the if the parameter values have been changed
963     OSL_ENSURE((m_aParameterValueForCache.get().size()-1) == m_pParameterNames->size(),"OKeySet::copyRowValue: Parameter values and names differ!");
964     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaValuesIter = m_aParameterValueForCache.get().begin() +1;
965 
966     bool bChanged = false;
967     SelectColumnsMetaData::const_iterator aParaIter = (*m_pParameterNames).begin();
968     SelectColumnsMetaData::const_iterator aParaEnd = (*m_pParameterNames).end();
969     for(sal_Int32 i = 1;aParaIter != aParaEnd;++aParaIter,++aParaValuesIter,++i)
970     {
971         ORowSetValue aValue(*aParaValuesIter);
972         aValue.setSigned(m_aSignedFlags[aParaIter->second.nPosition]);
973         if ( (_rInsertRow->get())[aParaIter->second.nPosition] != aValue )
974         {
975             ORowSetValueVector aCopy(m_aParameterValueForCache);
976             (aCopy.get())[i] = (_rInsertRow->get())[aParaIter->second.nPosition];
977             m_aUpdatedParameter[i_nBookmark] = aCopy;
978             bChanged = true;
979         }
980     }
981     if ( !bChanged )
982     {
983         m_aUpdatedParameter.erase(i_nBookmark);
984     }
985 
986     // update the key values
987     SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
988     SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
989     for(;aPosIter != aPosEnd;++aPosIter,++aIter)
990     {
991         impl_convertValue_throw(_rInsertRow,aPosIter->second);
992         *aIter = (_rInsertRow->get())[aPosIter->second.nPosition];
993         aIter->setTypeKind(aPosIter->second.nType);
994     }
995 }
996 // -------------------------------------------------------------------------
997 void SAL_CALL OKeySet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable   ) throw(SQLException, RuntimeException)
998 {
999     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::deleteRow" );
1000     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
1001     fillTableName(xSet);
1002 
1003     ::rtl::OUStringBuffer aSql = ::rtl::OUString::createFromAscii("DELETE FROM ");
1004     aSql.append(m_aComposedTableName);
1005     aSql.append(::rtl::OUString::createFromAscii(" WHERE "));
1006 
1007     // list all cloumns that should be set
1008     ::rtl::OUString aQuote  = getIdentifierQuoteString();
1009     static ::rtl::OUString aAnd     = ::rtl::OUString::createFromAscii(" AND ");
1010 
1011     // use keys and indexes for excat postioning
1012     Reference<XNameAccess> xKeyColumns = getKeyColumns();
1013     // second the indexes
1014     Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
1015     Reference<XIndexAccess> xIndexes;
1016     if ( xIndexSup.is() )
1017         xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
1018 
1019     //  Reference<XColumnsSupplier>
1020     ::std::vector< Reference<XNameAccess> > aAllIndexColumns;
1021     lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
1022 
1023     ::rtl::OUString aColumnName;
1024     ::rtl::OUStringBuffer sIndexCondition;
1025     ::std::vector<sal_Int32> aIndexColumnPositions;
1026     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
1027     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
1028 
1029     sal_Int32 i = 1;
1030     for(i = 1;aIter != aEnd;++aIter,++i)
1031     {
1032         if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
1033         {
1034             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
1035             if((_rDeleteRow->get())[aIter->second.nPosition].isNull())
1036             {
1037                 OSL_ENSURE(0,"can a primary key be null");
1038                 aSql.append(::rtl::OUString::createFromAscii(" IS NULL"));
1039             }
1040             else
1041                 aSql.append(::rtl::OUString::createFromAscii(" = ?"));
1042             aSql.append(aAnd);
1043         }
1044         else
1045         {
1046             ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end();
1047             for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin();
1048                     aIndexIter != aIndexEnd;++aIndexIter)
1049             {
1050                 if((*aIndexIter)->hasByName(aIter->first))
1051                 {
1052                     sIndexCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
1053                     if((_rDeleteRow->get())[aIter->second.nPosition].isNull())
1054                         sIndexCondition.append(::rtl::OUString::createFromAscii(" IS NULL"));
1055                     else
1056                     {
1057                         sIndexCondition.append(::rtl::OUString::createFromAscii(" = ?"));
1058                         aIndexColumnPositions.push_back(aIter->second.nPosition);
1059                     }
1060                     sIndexCondition.append(aAnd);
1061 
1062                     break;
1063                 }
1064             }
1065         }
1066     }
1067     aSql.append(sIndexCondition.makeStringAndClear());
1068     aSql.setLength(aSql.getLength()-5);
1069 
1070     // now create end execute the prepared statement
1071     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
1072     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
1073 
1074     aIter = (*m_pKeyColumnNames).begin();
1075     aEnd = (*m_pKeyColumnNames).end();
1076     i = 1;
1077     for(;aIter != aEnd;++aIter,++i)
1078     {
1079         setParameter(i,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale);
1080     }
1081 
1082     // now we have to set the index values
1083     ::std::vector<sal_Int32>::iterator aIdxColIter = aIndexColumnPositions.begin();
1084     ::std::vector<sal_Int32>::iterator aIdxColEnd = aIndexColumnPositions.end();
1085     aIter = m_pColumnNames->begin();
1086     for(;aIdxColIter != aIdxColEnd;++aIdxColIter,++i,++aIter)
1087     {
1088         setParameter(i,xParameter,(_rDeleteRow->get())[*aIdxColIter],(_rDeleteRow->get())[*aIdxColIter].getTypeKind(),aIter->second.nScale);
1089     }
1090 
1091     m_bDeleted = xPrep->executeUpdate() > 0;
1092 
1093     if(m_bDeleted)
1094     {
1095         sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny());
1096         if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end())
1097             ++m_aKeyIter;
1098         m_aKeyMap.erase(nBookmark);
1099         m_bDeleted = sal_True;
1100     }
1101 }
1102 // -------------------------------------------------------------------------
1103 void SAL_CALL OKeySet::cancelRowUpdates(  ) throw(SQLException, RuntimeException)
1104 {
1105     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::cancelRowUpdates" );
1106     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1107 }
1108 // -------------------------------------------------------------------------
1109 void SAL_CALL OKeySet::moveToInsertRow(  ) throw(SQLException, RuntimeException)
1110 {
1111     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToInsertRow" );
1112 }
1113 // -------------------------------------------------------------------------
1114 void SAL_CALL OKeySet::moveToCurrentRow(  ) throw(SQLException, RuntimeException)
1115 {
1116     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::moveToCurrentRow" );
1117 }
1118 // -------------------------------------------------------------------------
1119 Reference<XNameAccess> OKeySet::getKeyColumns() const
1120 {
1121     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getKeyColumns" );
1122     // use keys and indexes for excat postioning
1123     // first the keys
1124 
1125     Reference<XIndexAccess> xKeys = m_xTableKeys;
1126     if ( !xKeys.is() )
1127     {
1128         Reference<XPropertySet> xSet(m_xTable,UNO_QUERY);
1129         const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet);
1130         return xPrimaryKeyColumns;
1131     }
1132 
1133     Reference<XColumnsSupplier> xKeyColsSup;
1134     Reference<XNameAccess> xKeyColumns;
1135     if(xKeys.is())
1136     {
1137         Reference<XPropertySet> xProp;
1138         sal_Int32 nCount = xKeys->getCount();
1139         for(sal_Int32 i = 0;i< nCount;++i)
1140         {
1141             xProp.set(xKeys->getByIndex(i),UNO_QUERY);
1142             if ( xProp.is() )
1143             {
1144                 sal_Int32 nKeyType = 0;
1145                 xProp->getPropertyValue(PROPERTY_TYPE) >>= nKeyType;
1146                 if(KeyType::PRIMARY == nKeyType)
1147                 {
1148                     xKeyColsSup.set(xProp,UNO_QUERY);
1149                     OSL_ENSURE(xKeyColsSup.is(),"Columnsupplier is null!");
1150                     xKeyColumns = xKeyColsSup->getColumns();
1151                     break;
1152                 }
1153             }
1154         }
1155     }
1156 
1157     return xKeyColumns;
1158 }
1159 // -----------------------------------------------------------------------------
1160 sal_Bool SAL_CALL OKeySet::next(  ) throw(SQLException, RuntimeException)
1161 {
1162     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::next" );
1163     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1164 
1165     if(isAfterLast())
1166         return sal_False;
1167     if(!m_bRowCountFinal) // not yet all records fetched
1168     {
1169         ++m_aKeyIter; // this is possible because we stand on begin() and this is the "beforefirst" row
1170         if(m_aKeyIter == m_aKeyMap.end() && !fetchRow())
1171             m_aKeyIter = m_aKeyMap.end();
1172         else
1173         {
1174             //m_aKeyIter->second.second.second = new OPrivateRow(_rInsertRow->get());
1175             m_xRow.set(m_xDriverRow,UNO_QUERY_THROW);
1176             return !isAfterLast();
1177         }
1178     }
1179     else if(!isAfterLast())
1180         ++m_aKeyIter;
1181 
1182     refreshRow();
1183     return !isAfterLast();
1184 }
1185 // -----------------------------------------------------------------------------
1186 sal_Bool SAL_CALL OKeySet::isBeforeFirst(  ) throw(SQLException, RuntimeException)
1187 {
1188     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isBeforeFirst" );
1189     return m_aKeyIter == m_aKeyMap.begin();
1190 }
1191 // -----------------------------------------------------------------------------
1192 sal_Bool SAL_CALL OKeySet::isAfterLast(  ) throw(SQLException, RuntimeException)
1193 {
1194     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isAfterLast" );
1195     return  m_bRowCountFinal && m_aKeyIter == m_aKeyMap.end();
1196 }
1197 // -----------------------------------------------------------------------------
1198 sal_Bool SAL_CALL OKeySet::isFirst(  ) throw(SQLException, RuntimeException)
1199 {
1200     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isFirst" );
1201     OKeySetMatrix::iterator aTemp = m_aKeyMap.begin();
1202     ++aTemp;
1203     return m_aKeyIter == aTemp && m_aKeyIter != m_aKeyMap.end();
1204 }
1205 // -----------------------------------------------------------------------------
1206 sal_Bool SAL_CALL OKeySet::isLast(  ) throw(SQLException, RuntimeException)
1207 {
1208     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::isLast" );
1209     if(!m_bRowCountFinal)
1210         return sal_False;
1211 
1212     OKeySetMatrix::iterator aTemp = m_aKeyMap.end();
1213     --aTemp;
1214     return m_aKeyIter == aTemp;
1215 }
1216 // -----------------------------------------------------------------------------
1217 void SAL_CALL OKeySet::beforeFirst(  ) throw(SQLException, RuntimeException)
1218 {
1219     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::beforeFirst" );
1220     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1221     m_aKeyIter = m_aKeyMap.begin();
1222     m_xRow = NULL;
1223     ::comphelper::disposeComponent(m_xSet);
1224 }
1225 // -----------------------------------------------------------------------------
1226 void SAL_CALL OKeySet::afterLast(  ) throw(SQLException, RuntimeException)
1227 {
1228     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::afterLast" );
1229     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1230     fillAllRows();
1231     m_aKeyIter = m_aKeyMap.end();
1232     m_xRow = NULL;
1233     ::comphelper::disposeComponent(m_xSet);
1234 }
1235 // -----------------------------------------------------------------------------
1236 sal_Bool SAL_CALL OKeySet::first(  ) throw(SQLException, RuntimeException)
1237 {
1238     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::first" );
1239     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1240     m_aKeyIter = m_aKeyMap.begin();
1241     ++m_aKeyIter;
1242     if(m_aKeyIter == m_aKeyMap.end() && !fetchRow())
1243         m_aKeyIter = m_aKeyMap.end();
1244     else
1245         refreshRow();
1246     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
1247 }
1248 // -----------------------------------------------------------------------------
1249 sal_Bool SAL_CALL OKeySet::last(  ) throw(SQLException, RuntimeException)
1250 {
1251     return last_checked(sal_True);
1252 }
1253 
1254 sal_Bool OKeySet::last_checked( sal_Bool i_bFetchRow)
1255 {
1256     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::last_checked" );
1257     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1258     fillAllRows();
1259 
1260     m_aKeyIter = m_aKeyMap.end();
1261     --m_aKeyIter;
1262     if ( i_bFetchRow )
1263         refreshRow();
1264     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
1265 }
1266 // -----------------------------------------------------------------------------
1267 sal_Int32 SAL_CALL OKeySet::getRow(  ) throw(SQLException, RuntimeException)
1268 {
1269     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRow" );
1270     OSL_ENSURE(!isAfterLast(),"getRow is not allowed when afterlast record!");
1271     OSL_ENSURE(!isBeforeFirst(),"getRow is not allowed when beforefirst record!");
1272 
1273     return ::std::distance(m_aKeyMap.begin(),m_aKeyIter);
1274 }
1275 // -----------------------------------------------------------------------------
1276 sal_Bool SAL_CALL OKeySet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException)
1277 {
1278     return absolute_checked(row,sal_True);
1279 }
1280 sal_Bool OKeySet::absolute_checked( sal_Int32 row,sal_Bool i_bFetchRow )
1281 {
1282     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::absolute" );
1283     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1284     OSL_ENSURE(row,"absolute(0) isn't allowed!");
1285     if(row < 0)
1286     {
1287         if(!m_bRowCountFinal)
1288             fillAllRows();
1289 
1290         for(;row < 0 && m_aKeyIter != m_aKeyMap.begin();++row)
1291             m_aKeyIter--;
1292     }
1293     else
1294     {
1295         if(row >= (sal_Int32)m_aKeyMap.size())
1296         {
1297             if(!m_bRowCountFinal)
1298             {
1299                 sal_Bool bNext = sal_True;
1300                 for(sal_Int32 i=m_aKeyMap.size()-1;i < row && bNext;++i)
1301                     bNext = fetchRow();
1302                 if ( bNext )
1303                 {
1304                     m_xRow.set(m_xDriverRow,UNO_QUERY_THROW);
1305                     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
1306                 }
1307             }
1308             else
1309                 m_aKeyIter = m_aKeyMap.end();
1310         }
1311         else
1312         {
1313             m_aKeyIter = m_aKeyMap.begin();
1314             for(;row > 0 && m_aKeyIter != m_aKeyMap.end();--row)
1315                 ++m_aKeyIter;
1316         }
1317     }
1318     if ( i_bFetchRow )
1319         refreshRow();
1320 
1321     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
1322 }
1323 // -----------------------------------------------------------------------------
1324 sal_Bool SAL_CALL OKeySet::relative( sal_Int32 rows ) throw(SQLException, RuntimeException)
1325 {
1326     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::relative" );
1327     if(!rows)
1328     {
1329         refreshRow();
1330         return sal_True;
1331     }
1332     return absolute(getRow()+rows);
1333 }
1334 // -----------------------------------------------------------------------------
1335 sal_Bool OKeySet::previous_checked( sal_Bool i_bFetchRow )
1336 {
1337     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::previous" );
1338     m_bInserted = m_bUpdated = m_bDeleted = sal_False;
1339     if(m_aKeyIter != m_aKeyMap.begin())
1340     {
1341         --m_aKeyIter;
1342         if ( i_bFetchRow )
1343             refreshRow();
1344     }
1345     return m_aKeyIter != m_aKeyMap.begin();
1346 }
1347 // -----------------------------------------------------------------------------
1348 sal_Bool SAL_CALL OKeySet::previous(  ) throw(SQLException, RuntimeException)
1349 {
1350     return previous_checked(sal_True);
1351 }
1352 
1353 // -----------------------------------------------------------------------------
1354 void SAL_CALL OKeySet::refreshRow() throw(SQLException, RuntimeException)
1355 {
1356     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::refreshRow" );
1357     if(isBeforeFirst() || isAfterLast() || !m_xStatement.is())
1358         return;
1359 
1360     m_xRow = NULL;
1361     ::comphelper::disposeComponent(m_xSet);
1362 
1363     if ( m_aKeyIter->second.second.second.is() )
1364     {
1365         m_xRow = m_aKeyIter->second.second.second;
1366         return;
1367     }
1368     // we just areassign the base members
1369     Reference< XParameters > xParameter(m_xStatement,UNO_QUERY);
1370     OSL_ENSURE(xParameter.is(),"No Parameter interface!");
1371     xParameter->clearParameters();
1372 
1373     sal_Int32 nPos=1;
1374     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter;
1375     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd;
1376     OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first);
1377     if ( aUpdateFind == m_aUpdatedParameter.end() )
1378     {
1379         aParaIter = m_aParameterValueForCache.get().begin();
1380         aParaEnd = m_aParameterValueForCache.get().end();
1381     }
1382     else
1383     {
1384         aParaIter = aUpdateFind->second.get().begin();
1385         aParaEnd = aUpdateFind->second.get().end();
1386     }
1387 
1388     for(++aParaIter;aParaIter != aParaEnd;++aParaIter,++nPos)
1389     {
1390         ::dbtools::setObjectWithInfo( xParameter, nPos, aParaIter->makeAny(), aParaIter->getTypeKind() );
1391     }
1392 
1393     // now set the primary key column values
1394     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin();
1395     SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
1396     SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
1397     for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos)
1398         setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale);
1399     aPosIter = (*m_pForeignColumnNames).begin();
1400     aPosEnd = (*m_pForeignColumnNames).end();
1401     for(;aPosIter != aPosEnd;++aPosIter,++aIter,++nPos)
1402         setParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale);
1403 
1404     m_xSet = m_xStatement->executeQuery();
1405     OSL_ENSURE(m_xSet.is(),"No resultset form statement!");
1406     sal_Bool bOK = m_xSet->next();
1407     if ( !bOK )
1408     {
1409         OKeySetMatrix::iterator aTemp = m_aKeyIter;
1410         ++m_aKeyIter;
1411         m_aKeyMap.erase(aTemp);
1412         --m_rRowCount;
1413         refreshRow();
1414     }
1415     else
1416     {
1417         m_xRow.set(m_xSet,UNO_QUERY);
1418         OSL_ENSURE(m_xRow.is(),"No row form statement!");
1419     }
1420 }
1421 // -----------------------------------------------------------------------------
1422 sal_Bool OKeySet::fetchRow()
1423 {
1424     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fetchRow" );
1425     // fetch the next row and append on the keyset
1426     sal_Bool bRet = sal_False;
1427     if ( !m_bRowCountFinal && (!m_nMaxRows || sal_Int32(m_aKeyMap.size()) < m_nMaxRows) )
1428         bRet = m_xDriverSet->next();
1429     if ( bRet )
1430     {
1431         ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >((*m_pKeyColumnNames).size() + m_pForeignColumnNames->size());
1432         connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = aKeyRow->get().begin();
1433         // first fetch the values needed for the key column
1434         SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
1435         SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
1436         for(;aPosIter != aPosEnd;++aPosIter,++aIter)
1437         {
1438             const SelectColumnDescription& rColDesc = aPosIter->second;
1439             aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow);
1440         }
1441         // now fetch the values from the missing columns from other tables
1442         aPosIter = (*m_pForeignColumnNames).begin();
1443         aPosEnd  = (*m_pForeignColumnNames).end();
1444         for(;aPosIter != aPosEnd;++aPosIter,++aIter)
1445         {
1446             const SelectColumnDescription& rColDesc = aPosIter->second;
1447             aIter->fill(rColDesc.nPosition,rColDesc.nType,rColDesc.bNullable,m_xDriverRow);
1448         }
1449         m_aKeyIter = m_aKeyMap.insert(OKeySetMatrix::value_type(m_aKeyMap.rbegin()->first+1,OKeySetValue(aKeyRow,::std::pair<sal_Int32,Reference<XRow> >(0,NULL)))).first;
1450     }
1451     else
1452         m_bRowCountFinal = sal_True;
1453     return bRet;
1454 }
1455 // -------------------------------------------------------------------------
1456 void OKeySet::fillAllRows()
1457 {
1458     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::fillAllRows" );
1459     if(!m_bRowCountFinal)
1460     {
1461         while(fetchRow())
1462             ;
1463     }
1464 }
1465 // XRow
1466 sal_Bool SAL_CALL OKeySet::wasNull(  ) throw(SQLException, RuntimeException)
1467 {
1468     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::wasNull" );
1469     return m_xRow->wasNull();
1470 }
1471 // -------------------------------------------------------------------------
1472 ::rtl::OUString SAL_CALL OKeySet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1473 {
1474     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getString" );
1475     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1476     return m_xRow->getString(columnIndex);
1477 }
1478 // -------------------------------------------------------------------------
1479 sal_Bool SAL_CALL OKeySet::getBoolean( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1480 {
1481     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBoolean" );
1482     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1483     return m_xRow->getBoolean(columnIndex);
1484 }
1485 // -------------------------------------------------------------------------
1486 sal_Int8 SAL_CALL OKeySet::getByte( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1487 {
1488     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getByte" );
1489     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1490     return m_xRow->getByte(columnIndex);
1491 }
1492 // -------------------------------------------------------------------------
1493 sal_Int16 SAL_CALL OKeySet::getShort( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1494 {
1495     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getShort" );
1496     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1497     return m_xRow->getShort(columnIndex);
1498 }
1499 // -------------------------------------------------------------------------
1500 sal_Int32 SAL_CALL OKeySet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1501 {
1502     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getInt" );
1503     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1504     return m_xRow->getInt(columnIndex);
1505 }
1506 // -------------------------------------------------------------------------
1507 sal_Int64 SAL_CALL OKeySet::getLong( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1508 {
1509     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getLong" );
1510     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1511     return m_xRow->getLong(columnIndex);
1512 }
1513 // -------------------------------------------------------------------------
1514 float SAL_CALL OKeySet::getFloat( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1515 {
1516     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getFloat" );
1517     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1518     return m_xRow->getFloat(columnIndex);
1519 }
1520 // -------------------------------------------------------------------------
1521 double SAL_CALL OKeySet::getDouble( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1522 {
1523     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDouble" );
1524     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1525     return m_xRow->getDouble(columnIndex);
1526 }
1527 // -------------------------------------------------------------------------
1528 Sequence< sal_Int8 > SAL_CALL OKeySet::getBytes( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1529 {
1530     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBytes" );
1531     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1532     return m_xRow->getBytes(columnIndex);
1533 }
1534 // -------------------------------------------------------------------------
1535 ::com::sun::star::util::Date SAL_CALL OKeySet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1536 {
1537     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getDate" );
1538     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1539     return m_xRow->getDate(columnIndex);
1540 }
1541 // -------------------------------------------------------------------------
1542 ::com::sun::star::util::Time SAL_CALL OKeySet::getTime( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1543 {
1544     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTime" );
1545     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1546     return m_xRow->getTime(columnIndex);
1547 }
1548 // -------------------------------------------------------------------------
1549 ::com::sun::star::util::DateTime SAL_CALL OKeySet::getTimestamp( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1550 {
1551     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getTimestamp" );
1552     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1553     return m_xRow->getTimestamp(columnIndex);
1554 }
1555 // -------------------------------------------------------------------------
1556 Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getBinaryStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1557 {
1558     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBinaryStream" );
1559     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1560     return m_xRow->getBinaryStream(columnIndex);
1561 }
1562 // -------------------------------------------------------------------------
1563 Reference< ::com::sun::star::io::XInputStream > SAL_CALL OKeySet::getCharacterStream( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1564 {
1565     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getCharacterStream" );
1566     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1567     return m_xRow->getCharacterStream(columnIndex);
1568 }
1569 // -------------------------------------------------------------------------
1570 Any SAL_CALL OKeySet::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& typeMap ) throw(SQLException, RuntimeException)
1571 {
1572     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getObject" );
1573     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1574     return m_xRow->getObject(columnIndex,typeMap);
1575 }
1576 // -------------------------------------------------------------------------
1577 Reference< XRef > SAL_CALL OKeySet::getRef( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1578 {
1579     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getRef" );
1580     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1581     return m_xRow->getRef(columnIndex);
1582 }
1583 // -------------------------------------------------------------------------
1584 Reference< XBlob > SAL_CALL OKeySet::getBlob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1585 {
1586     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getBlob" );
1587     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1588     return m_xRow->getBlob(columnIndex);
1589 }
1590 // -------------------------------------------------------------------------
1591 Reference< XClob > SAL_CALL OKeySet::getClob( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1592 {
1593     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getClob" );
1594     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1595     return m_xRow->getClob(columnIndex);
1596 }
1597 // -------------------------------------------------------------------------
1598 Reference< XArray > SAL_CALL OKeySet::getArray( sal_Int32 columnIndex ) throw(SQLException, RuntimeException)
1599 {
1600     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getArray" );
1601     OSL_ENSURE(m_xRow.is(),"m_xRow is null!");
1602     return m_xRow->getArray(columnIndex);
1603 }
1604 // -------------------------------------------------------------------------
1605 sal_Bool SAL_CALL OKeySet::rowUpdated(  ) throw(SQLException, RuntimeException)
1606 {
1607     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowUpdated" );
1608     return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 2;
1609 }
1610 // -------------------------------------------------------------------------
1611 sal_Bool SAL_CALL OKeySet::rowInserted(  ) throw(SQLException, RuntimeException)
1612 {
1613     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowInserted" );
1614     return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 1;
1615 }
1616 // -------------------------------------------------------------------------
1617 sal_Bool SAL_CALL OKeySet::rowDeleted(  ) throw(SQLException, RuntimeException)
1618 {
1619     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::rowDeleted" );
1620     sal_Bool bDeleted = m_bDeleted;
1621     m_bDeleted = sal_False;
1622     return bDeleted;
1623 }
1624 // -----------------------------------------------------------------------------
1625 ::rtl::OUString OKeySet::getComposedTableName(const ::rtl::OUString& _sCatalog,
1626                                               const ::rtl::OUString& _sSchema,
1627                                               const ::rtl::OUString& _sTable)
1628 {
1629     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OKeySet::getComposedTableName" );
1630     ::rtl::OUString aComposedName;
1631     Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
1632 
1633     if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() )
1634     {
1635         aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation );
1636         // first we have to check if the composed tablename is in the select clause or if an alias is used
1637         Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY);
1638         Reference<XNameAccess> xSelectTables = xTabSup->getTables();
1639         OSL_ENSURE(xSelectTables.is(),"No Select tables!");
1640         if(xSelectTables.is())
1641         {
1642             if(!xSelectTables->hasByName(aComposedName))
1643             { // the composed name isn't used in the select clause so we have to find out which name is used instead
1644                 ::rtl::OUString sCatalog,sSchema,sTable;
1645                 ::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
1646                 aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
1647             }
1648             else
1649                 aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable );
1650         }
1651     }
1652     else
1653         aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable );
1654 
1655     return aComposedName;
1656 }
1657 // -----------------------------------------------------------------------------
1658 namespace dbaccess
1659 {
1660 
1661 void getColumnPositions(const Reference<XNameAccess>& _rxQueryColumns,
1662                             const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _aColumnNames,
1663                             const ::rtl::OUString& _rsUpdateTableName,
1664                             SelectColumnsMetaData& o_rColumnNames,
1665                             bool i_bAppendTableName)
1666     {
1667         // get the real name of the columns
1668         Sequence< ::rtl::OUString> aSelNames(_rxQueryColumns->getElementNames());
1669         const ::rtl::OUString* pSelIter     = aSelNames.getConstArray();
1670         const ::rtl::OUString* pSelEnd      = pSelIter + aSelNames.getLength();
1671 
1672         const ::rtl::OUString* pTblColumnIter   = _aColumnNames.getConstArray();
1673         const ::rtl::OUString* pTblColumnEnd    = pTblColumnIter + _aColumnNames.getLength();
1674 
1675 
1676         ::comphelper::UStringMixLess aTmp(o_rColumnNames.key_comp());
1677         ::comphelper::UStringMixEqual bCase(static_cast< ::comphelper::UStringMixLess*>(&aTmp)->isCaseSensitive());
1678 
1679         for(sal_Int32 nPos = 1;pSelIter != pSelEnd;++pSelIter,++nPos)
1680         {
1681             Reference<XPropertySet> xQueryColumnProp(_rxQueryColumns->getByName(*pSelIter),UNO_QUERY_THROW);
1682             ::rtl::OUString sRealName,sTableName;
1683             OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_REALNAME),"Property REALNAME not available!");
1684             OSL_ENSURE(xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_TABLENAME),"Property TABLENAME not available!");
1685             xQueryColumnProp->getPropertyValue(PROPERTY_REALNAME)   >>= sRealName;
1686             xQueryColumnProp->getPropertyValue(PROPERTY_TABLENAME)  >>= sTableName;
1687 
1688             for(;pTblColumnIter != pTblColumnEnd;++pTblColumnIter)
1689             {
1690                 if(bCase(sRealName,*pTblColumnIter) && bCase(_rsUpdateTableName,sTableName) && o_rColumnNames.find(*pTblColumnIter) == o_rColumnNames.end())
1691                 {
1692                     sal_Int32 nType = 0;
1693                     xQueryColumnProp->getPropertyValue(PROPERTY_TYPE)   >>= nType;
1694                     sal_Int32 nScale = 0;
1695                     xQueryColumnProp->getPropertyValue(PROPERTY_SCALE)  >>= nScale;
1696                     ::rtl::OUString sColumnDefault;
1697                     if ( xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE) )
1698                         xQueryColumnProp->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sColumnDefault;
1699 
1700                     sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
1701                     OSL_VERIFY( xQueryColumnProp->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable );
1702 
1703                     if ( i_bAppendTableName )
1704                     {
1705                         ::rtl::OUStringBuffer sName;
1706                         sName.append(sTableName);
1707                         sName.appendAscii(".");
1708                         sName.append(sRealName);
1709                         SelectColumnDescription aColDesc( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault );
1710                         aColDesc.sRealName = sRealName;
1711                         aColDesc.sTableName = sTableName;
1712                         o_rColumnNames[sName.makeStringAndClear()] = aColDesc;
1713                     }
1714                     else
1715                         o_rColumnNames[sRealName] = SelectColumnDescription( nPos, nType,nScale,nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault );
1716 
1717                     break;
1718                 }
1719             }
1720             pTblColumnIter = _aColumnNames.getConstArray();
1721         }
1722     }
1723 }
1724 // -----------------------------------------------------------------------------
1725 void OKeySet::impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData)
1726 {
1727     ORowSetValue& aValue((_rInsertRow->get())[i_aMetaData.nPosition]);
1728     switch(i_aMetaData.nType)
1729     {
1730         case DataType::DECIMAL:
1731         case DataType::NUMERIC:
1732             {
1733                 ::rtl::OUString sValue = aValue.getString();
1734                 sal_Int32 nIndex = sValue.indexOf('.');
1735                 if ( nIndex != -1 )
1736                 {
1737                     aValue = sValue.copy(0,::std::min(sValue.getLength(),nIndex + (i_aMetaData.nScale > 0 ? i_aMetaData.nScale + 1 : 0)));
1738                 }
1739             }
1740             break;
1741         default:
1742             break;
1743     }
1744 }
1745 // -----------------------------------------------------------------------------
1746 
1747