LCOV - code coverage report
Current view: top level - dbaccess/source/core/api - KeySet.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 0 888 0.0 %
Date: 2014-11-03 Functions: 0 81 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10