LCOV - code coverage report
Current view: top level - dbaccess/source/core/api - KeySet.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 570 880 64.8 %
Date: 2015-06-13 12:38:46 Functions: 52 81 64.2 %
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          21 :     void lcl_fillIndexColumns(const Reference<XIndexAccess>& _xIndexes, ::std::vector< Reference<XNameAccess> >& _rAllIndexColumns)
      71             :     {
      72          21 :         if ( _xIndexes.is() )
      73             :         {
      74          21 :             Reference<XPropertySet> xIndexColsSup;
      75          21 :             sal_Int32 nCount = _xIndexes->getCount();
      76          42 :             for(sal_Int32 j = 0 ; j < nCount ; ++j)
      77             :             {
      78          21 :                 xIndexColsSup.set(_xIndexes->getByIndex(j),UNO_QUERY);
      79          63 :                 if( xIndexColsSup.is()
      80          63 :                     && comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISUNIQUE))
      81          84 :                     && !comphelper::getBOOL(xIndexColsSup->getPropertyValue(PROPERTY_ISPRIMARYKEYINDEX))
      82             :                 )
      83          21 :                     _rAllIndexColumns.push_back(Reference<XColumnsSupplier>(xIndexColsSup,UNO_QUERY)->getColumns());
      84          21 :             }
      85             :         }
      86          21 :     }
      87             : 
      88          14 :     template < typename T > inline void tryDispose( Reference<T> &r )
      89             :     {
      90             :         try
      91             :         {
      92          14 :             ::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          14 :     }
     103             : }
     104             : 
     105             : 
     106           9 : 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           9 :             ,m_bRowCountFinal(false)
     121             : {
     122           9 : }
     123             : 
     124          27 : OKeySet::~OKeySet()
     125             : {
     126           9 :     tryDispose(m_xSet);
     127             :     // m_xStatement is necessarily one of those
     128           9 :     const vStatements_t::const_iterator end(m_vStatements.end());
     129          14 :     for(vStatements_t::iterator i(m_vStatements.begin());
     130             :         i != end;
     131             :         ++i)
     132             :     {
     133           5 :         tryDispose(i->second);
     134             :     }
     135             : 
     136           9 :     m_xComposer = NULL;
     137             : 
     138          18 : }
     139             : 
     140           9 : void OKeySet::initColumns()
     141             : {
     142           9 :     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
     143           9 :     bool bCase = xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers();
     144           9 :     m_pKeyColumnNames.reset( new SelectColumnsMetaData(bCase) );
     145           9 :     m_pColumnNames.reset( new SelectColumnsMetaData(bCase) );
     146           9 :     m_pParameterNames.reset( new SelectColumnsMetaData(bCase) );
     147           9 :     m_pForeignColumnNames.reset( new SelectColumnsMetaData(bCase) );
     148           9 : }
     149             : 
     150           9 : 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           9 :     Sequence< OUString> aBestColumnNames;
     158          18 :     Reference<XNameAccess> xKeyColumns  = getPrimaryKeyColumns_throw(i_aTable);
     159           9 :     if ( xKeyColumns.is() )
     160           9 :         aBestColumnNames = xKeyColumns->getElementNames();
     161             : 
     162          18 :     const Reference<XColumnsSupplier> xTblColSup(i_aTable,UNO_QUERY_THROW);
     163          18 :     const Reference<XNameAccess> xTblColumns = xTblColSup->getColumns();
     164             :     // locate parameter in select columns
     165          18 :     Reference<XParametersSupplier> xParaSup(m_xComposer,UNO_QUERY);
     166          18 :     Reference<XIndexAccess> xQueryParameters = xParaSup->getParameters();
     167           9 :     const sal_Int32 nParaCount = xQueryParameters->getCount();
     168          18 :     Sequence< OUString> aParameterColumns(nParaCount);
     169          11 :     for(sal_Int32 i = 0; i< nParaCount;++i)
     170             :     {
     171           2 :         Reference<XPropertySet> xPara(xQueryParameters->getByIndex(i),UNO_QUERY_THROW);
     172           2 :         xPara->getPropertyValue(PROPERTY_REALNAME) >>= aParameterColumns[i];
     173           2 :     }
     174             : 
     175          18 :     OUString sUpdateTableName( i_rUpdateTableName );
     176           9 :     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           9 :     ::dbaccess::getColumnPositions(i_xQueryColumns,aBestColumnNames,sUpdateTableName,(*o_pKeyColumnNames),true);
     197           9 :     ::dbaccess::getColumnPositions(i_xQueryColumns,xTblColumns->getElementNames(),sUpdateTableName,(*m_pColumnNames),true);
     198           9 :     ::dbaccess::getColumnPositions(i_xQueryColumns,aParameterColumns,sUpdateTableName,(*m_pParameterNames),true);
     199             : 
     200           9 :     if ( o_pKeyColumnNames->empty() )
     201             :     {
     202           0 :         ::dbtools::throwGenericSQLException("Could not find any key column.", *this );
     203             :     }
     204             : 
     205          54 :     for (   SelectColumnsMetaData::const_iterator keyColumn = o_pKeyColumnNames->begin();
     206          36 :             keyColumn != o_pKeyColumnNames->end();
     207             :             ++keyColumn
     208             :         )
     209             :     {
     210           9 :         if ( !xTblColumns->hasByName( keyColumn->second.sRealName ) )
     211           0 :             continue;
     212             : 
     213           9 :         Reference<XPropertySet> xProp( xTblColumns->getByName( keyColumn->second.sRealName ), UNO_QUERY );
     214           9 :         bool bAuto = false;
     215           9 :         if ( ( xProp->getPropertyValue( PROPERTY_ISAUTOINCREMENT ) >>= bAuto ) && bAuto )
     216           1 :             m_aAutoColumns.push_back( keyColumn->first );
     217          18 :     }
     218           9 : }
     219             : 
     220             : namespace
     221             : {
     222           5 :     void appendOneKeyColumnClause( const OUString &tblName, const OUString &colName, const connectivity::ORowSetValue &_rValue, OUStringBuffer &o_buf )
     223             :     {
     224             :         static const char s_sDot[] = ".";
     225           5 :         OUString fullName;
     226           5 :         if (tblName.isEmpty())
     227           0 :             fullName = colName;
     228             :         else
     229           5 :             fullName = tblName + s_sDot + colName;
     230           5 :         if ( _rValue.isNull() )
     231             :         {
     232           0 :             o_buf.append(fullName + " IS NULL ");
     233             :         }
     234             :         else
     235             :         {
     236           5 :             o_buf.append(fullName + " = ? ");
     237           5 :         }
     238           5 :     }
     239             : }
     240             : 
     241       13478 : void OKeySet::setOneKeyColumnParameter( sal_Int32 &nPos, const Reference< XParameters > &_xParameter, const connectivity::ORowSetValue &_rValue, sal_Int32 _nType, sal_Int32 _nScale )
     242             : {
     243       13478 :     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       13478 :         setParameter( nPos++, _xParameter, _rValue, _nType, _nScale );
     251             :     }
     252       13478 : }
     253             : 
     254           5 : OUStringBuffer OKeySet::createKeyFilter()
     255             : {
     256           5 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin();
     257             : 
     258             :     static const char aAnd[] = " AND ";
     259           5 :     const OUString aQuote    = getIdentifierQuoteString();
     260           5 :     OUStringBuffer aFilter;
     261             :     // create the where clause
     262          10 :     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
     263           5 :     SelectColumnsMetaData::const_iterator aPosEnd = m_pKeyColumnNames->end();
     264          10 :     for(SelectColumnsMetaData::const_iterator aPosIter = m_pKeyColumnNames->begin();aPosIter != aPosEnd; ++aPosIter)
     265             :     {
     266           5 :         if ( ! aFilter.isEmpty() )
     267           0 :             aFilter.append(aAnd);
     268           5 :         appendOneKeyColumnClause(::dbtools::quoteTableName(xMeta, aPosIter->second.sTableName, ::dbtools::eInDataManipulation),
     269           5 :                                  ::dbtools::quoteName(aQuote, aPosIter->second.sRealName),
     270          10 :                                  *aIter++,
     271          10 :                                  aFilter);
     272             :     }
     273           5 :     aPosEnd = m_pForeignColumnNames->end();
     274           5 :     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          10 :     return aFilter;
     284             : }
     285             : 
     286           9 : void OKeySet::construct(const Reference< XResultSet>& _xDriverSet, const OUString& i_sRowSetFilter)
     287             : {
     288           9 :     OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
     289             : 
     290           9 :     initColumns();
     291             : 
     292           9 :     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
     293          18 :     Reference<XColumnsSupplier> xQueryColSup(m_xComposer, UNO_QUERY);
     294          18 :     const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns();
     295           9 :     findTableColumnsMatching_throw( makeAny(m_xTable), m_sUpdateTableName, xMeta, xQueryColumns, m_pKeyColumnNames );
     296             : 
     297          18 :     Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
     298          18 :     Reference< XMultiServiceFactory >  xFactory(m_xConnection, UNO_QUERY_THROW);
     299          18 :     Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
     300           9 :     xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
     301          18 :     Reference<XTablesSupplier> xTabSup(xAnalyzer,uno::UNO_QUERY);
     302          18 :     Reference<XNameAccess> xSelectTables(xTabSup->getTables(),uno::UNO_QUERY);
     303          18 :     const Sequence< OUString> aSeq = xSelectTables->getElementNames();
     304           9 :     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          18 :     OKeySetValue keySetValue(nullptr,::std::pair<sal_Int32,Reference<XRow> >(0,Reference<XRow>()));
     327           9 :     m_aKeyMap.insert(OKeySetMatrix::value_type(0, keySetValue));
     328          18 :     m_aKeyIter = m_aKeyMap.begin();
     329           9 : }
     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(nullptr,::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       13478 : void OKeySet::ensureStatement( )
     342             : {
     343             :     // do we already have a statement for the current combination of NULLness
     344             :     // of key & foreign columns?
     345       13478 :     FilterColumnsNULL_t FilterColumnsNULL;
     346       13478 :     FilterColumnsNULL.reserve(m_aKeyIter->second.first->get().size());
     347       13478 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin();
     348       13478 :     const connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aEnd  = m_aKeyIter->second.first->get().end();
     349       40434 :     for( ; aIter != aEnd; ++aIter )
     350       26956 :         FilterColumnsNULL.push_back(aIter->isNull());
     351       13478 :     vStatements_t::iterator pNewStatement(m_vStatements.find(FilterColumnsNULL));
     352       13478 :     if(pNewStatement == m_vStatements.end())
     353             :     {
     354             :         // no: make a new one
     355           5 :         makeNewStatement();
     356             :         std::pair< vStatements_t::iterator, bool > insert_result
     357           5 :             (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       13473 :         m_xStatement = pNewStatement->second;
     364       13478 : }
     365             : 
     366           5 : void OKeySet::makeNewStatement()
     367             : {
     368           5 :     Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
     369          10 :     Reference< XMultiServiceFactory >  xFactory(m_xConnection, UNO_QUERY_THROW);
     370          10 :     Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
     371           5 :     xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
     372             : 
     373          10 :     OUStringBuffer aFilter(createKeyFilter());
     374          10 :     executeStatement(aFilter, xAnalyzer);
     375           5 : }
     376             : 
     377           5 : void OKeySet::executeStatement(OUStringBuffer& io_aFilter, Reference<XSingleSelectQueryComposer>& io_xAnalyzer)
     378             : {
     379           5 :     bool bFilterSet = !m_sRowSetFilter.isEmpty();
     380           5 :     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           5 :     io_xAnalyzer->setFilter(io_aFilter.makeStringAndClear());
     388           5 :     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.startsWith( ":" ) ) )
     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           5 :     m_xStatement = m_xConnection->prepareStatement(io_xAnalyzer->getQueryWithSubstitution());
     408           5 :     ::comphelper::disposeComponent(io_xAnalyzer);
     409           5 : }
     410             : 
     411       33337 : void OKeySet::invalidateRow()
     412             : {
     413       33337 :     m_xRow = NULL;
     414       33337 :     ::comphelper::disposeComponent(m_xSet);
     415       33337 : }
     416             : 
     417       13603 : 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       13603 :     return makeAny(m_aKeyIter->first);
     422             : }
     423             : 
     424        4516 : bool SAL_CALL OKeySet::moveToBookmark( const Any& bookmark ) throw(SQLException, RuntimeException)
     425             : {
     426        4516 :     m_bInserted = m_bUpdated = m_bDeleted = false;
     427        4516 :     m_aKeyIter = m_aKeyMap.find(::comphelper::getINT32(bookmark));
     428        4516 :     invalidateRow();
     429        4516 :     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        5904 : sal_Int32 SAL_CALL OKeySet::compareBookmarks( const Any& _first, const Any& _second ) throw(SQLException, RuntimeException)
     446             : {
     447        5904 :     sal_Int32 nFirst = 0, nSecond = 0;
     448        5904 :     _first >>= nFirst;
     449        5904 :     _second >>= nSecond;
     450             : 
     451        5904 :     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             :     static const char aAnd[] = " AND ";
     475             :     static const char aOr[] = " OR ";
     476             :     static const char 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() - strlen(aAnd));
     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           1 : void SAL_CALL OKeySet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOriginalRow,const connectivity::OSQLTable& _xTable  ) throw(SQLException, RuntimeException)
     553             : {
     554           1 :     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
     555           1 :     fillTableName(xSet);
     556             : 
     557           2 :     OUStringBuffer aSql = "UPDATE " + m_aComposedTableName + " SET ";
     558             :     // list all columns that should be set
     559           1 :     static OUString aPara(" = ?,");
     560           2 :     OUString aQuote  = getIdentifierQuoteString();
     561           1 :     static OUString aAnd(" AND ");
     562           2 :     OUString sIsNull(" IS NULL");
     563           2 :     OUString sParam(" = ?");
     564             : 
     565             :     // use keys and indexes for exact positioning
     566             :     // first the keys
     567           2 :     Reference<XNameAccess> xKeyColumns = getKeyColumns();
     568             : 
     569             :     // second the indexes
     570           2 :     Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
     571           2 :     Reference<XIndexAccess> xIndexes;
     572           1 :     if ( xIndexSup.is() )
     573           1 :         xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
     574             : 
     575           2 :     ::std::vector< Reference<XNameAccess> > aAllIndexColumns;
     576           1 :     lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
     577             : 
     578           2 :     OUStringBuffer sKeyCondition,sIndexCondition;
     579           2 :     ::std::vector<sal_Int32> aIndexColumnPositions;
     580             : 
     581           1 :     const sal_Int32 nOldLength = aSql.getLength();
     582           1 :     sal_Int32 i = 1;
     583             :     // here we build the condition part for the update statement
     584           1 :     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
     585           1 :     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
     586           3 :     for(;aIter != aEnd;++aIter,++i)
     587             :     {
     588           2 :         if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
     589             :         {
     590           1 :             sKeyCondition.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
     591           1 :             if((_rOriginalRow->get())[aIter->second.nPosition].isNull())
     592           0 :                 sKeyCondition.append(sIsNull);
     593             :             else
     594           1 :                 sKeyCondition.append(sParam);
     595           1 :             sKeyCondition.append(aAnd);
     596             :         }
     597             :         else
     598             :         {
     599           1 :             ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end();
     600           2 :             for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin();
     601             :                 aIndexIter != aIndexEnd;++aIndexIter)
     602             :             {
     603           1 :                 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           2 :         if((_rInsertRow->get())[aIter->second.nPosition].isModified())
     619             :         {
     620           2 :             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName) + aPara);
     621             :         }
     622             :     }
     623             : 
     624           1 :     if( aSql.getLength() != nOldLength )
     625             :     {
     626           1 :         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           1 :     if(!sKeyCondition.isEmpty() || !sIndexCondition.isEmpty())
     632             :     {
     633           1 :         aSql.append(" WHERE ");
     634           1 :         if(!sKeyCondition.isEmpty() && !sIndexCondition.isEmpty())
     635             :         {
     636           0 :             aSql.append(sKeyCondition.makeStringAndClear() + sIndexCondition.makeStringAndClear());
     637             :         }
     638           1 :         else if(!sKeyCondition.isEmpty())
     639             :         {
     640           1 :             aSql.append(sKeyCondition.makeStringAndClear());
     641             :         }
     642           0 :         else if(!sIndexCondition.isEmpty())
     643             :         {
     644           0 :             aSql.append(sIndexCondition.makeStringAndClear());
     645             :         }
     646           1 :         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           2 :     OUString sEmpty;
     653           2 :     executeUpdate(_rInsertRow ,_rOriginalRow,aSql.makeStringAndClear(),sEmpty,aIndexColumnPositions);
     654           1 : }
     655             : 
     656           1 : 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           1 :     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
     660           2 :     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
     661             : 
     662           1 :     bool bRefetch = true;
     663           2 :     Reference<XRow> xRow;
     664           1 :     sal_Int32 i = 1;
     665             :     // first the set values
     666           1 :     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
     667           1 :     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
     668           1 :     sal_uInt16 j = 0;
     669           3 :     for(;aIter != aEnd;++aIter,++j)
     670             :     {
     671           2 :         if ( i_sTableName.isEmpty() || aIter->second.sTableName == i_sTableName )
     672             :         {
     673           2 :             sal_Int32 nPos = aIter->second.nPosition;
     674           2 :             if((_rInsertRow->get())[nPos].isModified())
     675             :             {
     676           2 :                 if ( bRefetch )
     677             :                 {
     678           2 :                     bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end();
     679             :                 }
     680           2 :                 impl_convertValue_throw(_rInsertRow,aIter->second);
     681           2 :                 (_rInsertRow->get())[nPos].setSigned((_rOriginalRow->get())[nPos].isSigned());
     682           2 :                 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           1 :     aIter = m_pKeyColumnNames->begin();
     688           1 :     aEnd = m_pKeyColumnNames->end();
     689           1 :     j = 0;
     690           2 :     for(;aIter != aEnd;++aIter,++j)
     691             :     {
     692           1 :         if ( i_sTableName.isEmpty() || aIter->second.sTableName == i_sTableName )
     693             :         {
     694           1 :             setParameter(i++,xParameter,(_rOriginalRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale);
     695             :         }
     696             :     }
     697           1 :     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           1 :     const sal_Int32 nRowsUpdated = xPrep->executeUpdate();
     710           1 :      m_bUpdated =  nRowsUpdated > 0;
     711           1 :     if(m_bUpdated)
     712             :     {
     713           1 :         const sal_Int32 nBookmark = ::comphelper::getINT32((_rInsertRow->get())[0].getAny());
     714           1 :         m_aKeyIter = m_aKeyMap.find(nBookmark);
     715           1 :         m_aKeyIter->second.second.first = 2;
     716           1 :         m_aKeyIter->second.second.second = xRow;
     717           1 :         copyRowValue(_rInsertRow,m_aKeyIter->second.first,nBookmark);
     718           1 :         tryRefetch(_rInsertRow,bRefetch);
     719           1 :     }
     720           1 : }
     721             : 
     722           1 : void SAL_CALL OKeySet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& _xTable ) throw(SQLException, RuntimeException)
     723             : {
     724           1 :     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
     725           1 :     fillTableName(xSet);
     726             : 
     727           2 :     OUStringBuffer aSql( "INSERT INTO " + m_aComposedTableName + " ( ");
     728             : 
     729             :     // set values and column names
     730           2 :     OUStringBuffer aValues(" VALUES ( ");
     731             :     static const char aPara[] = "?,";
     732           2 :     OUString aQuote = getIdentifierQuoteString();
     733             :     static const char aComma[] = ",";
     734             : 
     735           1 :     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
     736           1 :     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
     737           1 :     sal_Int32 j = 1;
     738           1 :     bool bRefetch = true;
     739           1 :     bool bModified = false;
     740           3 :     for(;aIter != aEnd;++aIter,++j)
     741             :     {
     742           2 :         if((_rInsertRow->get())[aIter->second.nPosition].isModified())
     743             :         {
     744           2 :             if ( bRefetch )
     745             :             {
     746           2 :                 bRefetch = ::std::find(m_aFilterColumns.begin(),m_aFilterColumns.end(),aIter->second.sRealName) == m_aFilterColumns.end();
     747             :             }
     748           2 :             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName) + aComma);
     749           2 :             aValues.append(aPara);
     750           2 :             bModified = true;
     751             :         }
     752             :     }
     753           1 :     if ( !bModified )
     754           0 :         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection );
     755             : 
     756           1 :     aSql[aSql.getLength() - 1] = ')';
     757           1 :     aValues[aValues.getLength() - 1] = ')';
     758           1 :     aSql.append(aValues.makeStringAndClear());
     759             :     // now create,fill and execute the prepared statement
     760           2 :     OUString sEmpty;
     761           2 :     executeInsert(_rInsertRow,aSql.makeStringAndClear(),sEmpty,bRefetch);
     762           1 : }
     763             : 
     764           1 : 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           1 :     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
     768           2 :     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
     769             : 
     770           1 :     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
     771           1 :     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
     772           3 :     for(sal_Int32 i = 1;aIter != aEnd;++aIter)
     773             :     {
     774           2 :         if ( i_sTableName.isEmpty() || aIter->second.sTableName == i_sTableName )
     775             :         {
     776           2 :             const sal_Int32 nPos = aIter->second.nPosition;
     777           2 :             if((_rInsertRow->get())[nPos].isModified())
     778             :             {
     779           2 :                 if((_rInsertRow->get())[nPos].isNull())
     780           0 :                     xParameter->setNull(i++,(_rInsertRow->get())[nPos].getTypeKind());
     781             :                 else
     782             :                 {
     783           2 :                     impl_convertValue_throw(_rInsertRow,aIter->second);
     784           2 :                     (_rInsertRow->get())[nPos].setSigned(m_aSignedFlags[nPos-1]);
     785           2 :                     setParameter(i++,xParameter,(_rInsertRow->get())[nPos],aIter->second.nType,aIter->second.nScale);
     786             :                 }
     787             :             }
     788             :         }
     789             :     }
     790             : 
     791           1 :     m_bInserted = xPrep->executeUpdate() > 0;
     792           1 :     bool bAutoValuesFetched = false;
     793           1 :     if ( m_bInserted )
     794             :     {
     795             :         // first insert the default values into the insertrow
     796           1 :         aIter = m_pColumnNames->begin();
     797           3 :         for(;aIter != aEnd;++aIter)
     798             :         {
     799           2 :             if ( !(_rInsertRow->get())[aIter->second.nPosition].isModified() )
     800           0 :                 (_rInsertRow->get())[aIter->second.nPosition] = aIter->second.sDefaultValue;
     801             :         }
     802             :         try
     803             :         {
     804           1 :             Reference< XGeneratedResultSet > xGRes(xPrep, UNO_QUERY);
     805           1 :             if ( xGRes.is() )
     806             :             {
     807           1 :                 Reference< XResultSet > xRes = xGRes->getGeneratedValues();
     808           2 :                 Reference< XRow > xRow(xRes,UNO_QUERY);
     809           1 :                 if ( xRow.is() && xRes->next() )
     810             :                 {
     811           1 :                     Reference< XResultSetMetaDataSupplier > xMdSup(xRes,UNO_QUERY);
     812           2 :                     Reference< XResultSetMetaData > xMd = xMdSup->getMetaData();
     813           1 :                     sal_Int32 nColumnCount = xMd->getColumnCount();
     814           1 :                     ::std::vector< OUString >::iterator aAutoIter = m_aAutoColumns.begin();
     815           1 :                     ::std::vector< OUString >::iterator aAutoEnd = m_aAutoColumns.end();
     816           1 :                     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           2 :                     bAutoValuesFetched = true;
     823           1 :                 }
     824           1 :             }
     825             :         }
     826           0 :         catch(const Exception&)
     827             :         {
     828             :             SAL_WARN("dbaccess", "Could not execute GeneratedKeys() stmt");
     829             :         }
     830             :     }
     831             : 
     832           1 :     ::comphelper::disposeComponent(xPrep);
     833             : 
     834           1 :     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           1 :     if ( m_bInserted )
     890             :     {
     891           1 :         OKeySetMatrix::iterator aKeyIter = m_aKeyMap.end();
     892           1 :         --aKeyIter;
     893           1 :         ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >(m_pKeyColumnNames->size());
     894           1 :         copyRowValue(_rInsertRow,aKeyRow,aKeyIter->first + 1);
     895             : 
     896           1 :         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           1 :         (_rInsertRow->get())[0] = makeAny((sal_Int32)m_aKeyIter->first);
     899           1 :         tryRefetch(_rInsertRow,bRefetch);
     900           1 :     }
     901           1 : }
     902             : 
     903           2 : void OKeySet::tryRefetch(const ORowSetRow& _rInsertRow,bool bRefetch)
     904             : {
     905           2 :     if ( bRefetch )
     906             :     {
     907             :         try
     908             :         {
     909           2 :             bRefetch = doTryRefetch_throw();
     910             :         }
     911           0 :         catch(const Exception&)
     912             :         {
     913           0 :             bRefetch = false;
     914             :         }
     915             :     }
     916           2 :     if ( !bRefetch )
     917             :     {
     918           0 :         m_aKeyIter->second.second.second = new OPrivateRow(_rInsertRow->get());
     919             :     }
     920           2 : }
     921             : 
     922           2 : void OKeySet::copyRowValue(const ORowSetRow& _rInsertRow,ORowSetRow& _rKeyRow,sal_Int32 i_nBookmark)
     923             : {
     924           2 :     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           2 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaValuesIter = m_aParameterValueForCache.get().begin() +1;
     929             : 
     930           2 :     bool bChanged = false;
     931           2 :     SelectColumnsMetaData::const_iterator aParaIter = (*m_pParameterNames).begin();
     932           2 :     SelectColumnsMetaData::const_iterator aParaEnd = (*m_pParameterNames).end();
     933           2 :     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           2 :     if ( !bChanged )
     946             :     {
     947           2 :         m_aUpdatedParameter.erase(i_nBookmark);
     948             :     }
     949             : 
     950             :     // update the key values
     951           2 :     SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
     952           2 :     const SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
     953           4 :     for(;aPosIter != aPosEnd;++aPosIter,++aIter)
     954             :     {
     955           2 :         impl_convertValue_throw(_rInsertRow,aPosIter->second);
     956           2 :         *aIter = (_rInsertRow->get())[aPosIter->second.nPosition];
     957           2 :         aIter->setTypeKind(aPosIter->second.nType);
     958             :     }
     959           2 : }
     960             : 
     961          20 : void SAL_CALL OKeySet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& _xTable   ) throw(SQLException, RuntimeException)
     962             : {
     963          20 :     Reference<XPropertySet> xSet(_xTable,UNO_QUERY);
     964          20 :     fillTableName(xSet);
     965             : 
     966          40 :     OUStringBuffer aSql("DELETE FROM " + m_aComposedTableName + " WHERE ");
     967             : 
     968             :     // list all columns that should be set
     969          40 :     OUString aQuote  = getIdentifierQuoteString();
     970             :     static const char aAnd[] = " AND ";
     971             : 
     972             :     // use keys and indexes for exact positioning
     973          40 :     Reference<XNameAccess> xKeyColumns = getKeyColumns();
     974             :     // second the indexes
     975          40 :     Reference<XIndexesSupplier> xIndexSup(_xTable,UNO_QUERY);
     976          40 :     Reference<XIndexAccess> xIndexes;
     977          20 :     if ( xIndexSup.is() )
     978          20 :         xIndexes.set(xIndexSup->getIndexes(),UNO_QUERY);
     979             : 
     980             :     //  Reference<XColumnsSupplier>
     981          40 :     ::std::vector< Reference<XNameAccess> > aAllIndexColumns;
     982          20 :     lcl_fillIndexColumns(xIndexes,aAllIndexColumns);
     983             : 
     984          40 :     OUStringBuffer sIndexCondition;
     985          40 :     ::std::vector<sal_Int32> aIndexColumnPositions;
     986          20 :     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
     987          20 :     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
     988             : 
     989          20 :     sal_Int32 i = 1;
     990          60 :     for(i = 1;aIter != aEnd;++aIter,++i)
     991             :     {
     992          40 :         if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
     993             :         {
     994          20 :             aSql.append(::dbtools::quoteName( aQuote,aIter->second.sRealName));
     995          20 :             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          20 :                 aSql.append(" = ?");
    1002          20 :             aSql.append(aAnd);
    1003             :         }
    1004             :         else
    1005             :         {
    1006          20 :             ::std::vector< Reference<XNameAccess> >::const_iterator aIndexEnd = aAllIndexColumns.end();
    1007          40 :             for( ::std::vector< Reference<XNameAccess> >::const_iterator aIndexIter = aAllIndexColumns.begin();
    1008             :                     aIndexIter != aIndexEnd;++aIndexIter)
    1009             :             {
    1010          20 :                 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          20 :     aSql.append(sIndexCondition.makeStringAndClear());
    1028          20 :     aSql.setLength(aSql.getLength()-5);
    1029             : 
    1030             :     // now create end execute the prepared statement
    1031          40 :     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(aSql.makeStringAndClear()));
    1032          40 :     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
    1033             : 
    1034          20 :     aIter = (*m_pKeyColumnNames).begin();
    1035          20 :     aEnd = (*m_pKeyColumnNames).end();
    1036          20 :     i = 1;
    1037          40 :     for(;aIter != aEnd;++aIter,++i)
    1038             :     {
    1039          20 :         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          20 :     ::std::vector<sal_Int32>::iterator aIdxColIter = aIndexColumnPositions.begin();
    1044          20 :     ::std::vector<sal_Int32>::iterator aIdxColEnd = aIndexColumnPositions.end();
    1045          20 :     aIter = m_pColumnNames->begin();
    1046          20 :     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          20 :     m_bDeleted = xPrep->executeUpdate() > 0;
    1052             : 
    1053          20 :     if(m_bDeleted)
    1054             :     {
    1055          20 :         sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny());
    1056          20 :         if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end())
    1057          10 :             ++m_aKeyIter;
    1058          20 :         m_aKeyMap.erase(nBookmark);
    1059          20 :         m_bDeleted = true;
    1060          20 :     }
    1061          20 : }
    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          21 : Reference<XNameAccess> OKeySet::getKeyColumns() const
    1077             : {
    1078             :     // use keys and indexes for exact positioning
    1079             :     // first the keys
    1080             : 
    1081          21 :     Reference<XIndexAccess> xKeys = m_xTableKeys;
    1082          21 :     if ( !xKeys.is() )
    1083             :     {
    1084          21 :         Reference<XPropertySet> xSet(m_xTable,UNO_QUERY);
    1085          42 :         const Reference<XNameAccess> xPrimaryKeyColumns = getPrimaryKeyColumns_throw(xSet);
    1086          42 :         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          21 :     return xKeyColumns;
    1114             : }
    1115             : 
    1116       13617 : bool SAL_CALL OKeySet::next(  ) throw(SQLException, RuntimeException)
    1117             : {
    1118       13617 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1119             : 
    1120       13617 :     if(isAfterLast())
    1121           0 :         return false;
    1122       13617 :     ++m_aKeyIter;
    1123       13617 :     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         161 :         if (fetchRow())
    1128             :         {
    1129             :             OSL_ENSURE(!isAfterLast(), "fetchRow succeeded, but isAfterLast()");
    1130         157 :             return true;
    1131             :         }
    1132             :         else
    1133             :         {
    1134             :             // nope, we arrived at end of data
    1135           4 :             m_aKeyIter = m_aKeyMap.end();
    1136             :             OSL_ENSURE(isAfterLast(), "fetchRow failed, but not end of data");
    1137             :         }
    1138             :     }
    1139             : 
    1140       13460 :     invalidateRow();
    1141       13460 :     return !isAfterLast();
    1142             : }
    1143             : 
    1144       13476 : bool SAL_CALL OKeySet::isBeforeFirst(  ) throw(SQLException, RuntimeException)
    1145             : {
    1146       13476 :     return m_aKeyIter == m_aKeyMap.begin();
    1147             : }
    1148             : 
    1149       40553 : bool SAL_CALL OKeySet::isAfterLast(  ) throw(SQLException, RuntimeException)
    1150             : {
    1151       40553 :     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          12 : void SAL_CALL OKeySet::beforeFirst(  ) throw(SQLException, RuntimeException)
    1172             : {
    1173          12 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1174          12 :     m_aKeyIter = m_aKeyMap.begin();
    1175          12 :     invalidateRow();
    1176          12 : }
    1177             : 
    1178           2 : void SAL_CALL OKeySet::afterLast(  ) throw(SQLException, RuntimeException)
    1179             : {
    1180           2 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1181           2 :     fillAllRows();
    1182           2 :     m_aKeyIter = m_aKeyMap.end();
    1183           2 :     invalidateRow();
    1184           2 : }
    1185             : 
    1186          14 : bool SAL_CALL OKeySet::first(  ) throw(SQLException, RuntimeException)
    1187             : {
    1188          14 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1189          14 :     m_aKeyIter = m_aKeyMap.begin();
    1190          14 :     ++m_aKeyIter;
    1191          14 :     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          14 :         invalidateRow();
    1201          14 :     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
    1202             : }
    1203             : 
    1204          20 : bool SAL_CALL OKeySet::last(  ) throw(SQLException, RuntimeException)
    1205             : {
    1206          20 :     return last_checked(true);
    1207             : }
    1208             : 
    1209          21 : bool OKeySet::last_checked( bool /* i_bFetchRow */ )
    1210             : {
    1211          21 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1212          21 :     bool fetchedRow = fillAllRows();
    1213             : 
    1214          21 :     m_aKeyIter = m_aKeyMap.end();
    1215          21 :     --m_aKeyIter;
    1216          21 :     if ( !fetchedRow )
    1217             :     {
    1218          17 :         invalidateRow();
    1219             :     }
    1220          21 :     return m_aKeyIter != m_aKeyMap.end() && m_aKeyIter != m_aKeyMap.begin();
    1221             : }
    1222             : 
    1223        4533 : 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        4533 :     return ::std::distance(m_aKeyMap.begin(),m_aKeyIter);
    1229             : }
    1230             : 
    1231        1845 : bool SAL_CALL OKeySet::absolute( sal_Int32 row ) throw(SQLException, RuntimeException)
    1232             : {
    1233        1845 :     return absolute_checked(row,true);
    1234             : }
    1235             : 
    1236        1845 : bool OKeySet::absolute_checked( sal_Int32 row, bool /* i_bFetchRow */ )
    1237             : {
    1238        1845 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1239             :     OSL_ENSURE(row,"absolute(0) isn't allowed!");
    1240        1845 :     bool fetchedRow = false;
    1241        1845 :     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        1845 :         if(row >= (sal_Int32)m_aKeyMap.size())
    1252             :         {
    1253             :             // we don't have this row
    1254          10 :             if(!m_bRowCountFinal)
    1255             :             {
    1256             :                 // but there may still be rows to fetch.
    1257           9 :                 bool bNext = true;
    1258          18 :                 for(sal_Int32 i=m_aKeyMap.size()-1;i < row && bNext;++i)
    1259           9 :                     bNext = fetchRow();
    1260             :                 // it is guaranteed that the above loop has executed at least once,
    1261             :                 // that is fetchRow called at least once.
    1262           9 :                 if ( bNext )
    1263             :                 {
    1264           8 :                     fetchedRow = true;
    1265             :                 }
    1266             :                 else
    1267             :                 {
    1268             :                     // reached end of data before desired row
    1269           1 :                     m_aKeyIter = m_aKeyMap.end();
    1270           1 :                     return false;
    1271             :                 }
    1272             :             }
    1273             :             else
    1274             :             {
    1275             :                 // no more rows to fetch -> fail
    1276           1 :                 m_aKeyIter = m_aKeyMap.end();
    1277           1 :                 return false;
    1278             :             }
    1279             :         }
    1280             :         else
    1281             :         {
    1282        1835 :             m_aKeyIter = m_aKeyMap.begin();
    1283      105030 :             for(;row > 0 && m_aKeyIter != m_aKeyMap.end();--row)
    1284      103195 :                 ++m_aKeyIter;
    1285             :         }
    1286             :     }
    1287        1843 :     if ( !fetchedRow )
    1288             :     {
    1289        1835 :         invalidateRow();
    1290             :     }
    1291             : 
    1292        1843 :     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           5 : bool OKeySet::previous_checked( bool /* i_bFetchRow */ )
    1306             : {
    1307           5 :     m_bInserted = m_bUpdated = m_bDeleted = false;
    1308           5 :     if(m_aKeyIter != m_aKeyMap.begin())
    1309             :     {
    1310           5 :         --m_aKeyIter;
    1311           5 :         invalidateRow();
    1312             :     }
    1313           5 :     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       13478 : bool OKeySet::doTryRefetch_throw()  throw(SQLException, RuntimeException)
    1322             : {
    1323       13478 :     ensureStatement( );
    1324             :     // we just reassign the base members
    1325       13478 :     Reference< XParameters > xParameter(m_xStatement,UNO_QUERY);
    1326             :     OSL_ENSURE(xParameter.is(),"No Parameter interface!");
    1327       13478 :     xParameter->clearParameters();
    1328             : 
    1329       13478 :     sal_Int32 nPos=1;
    1330       13478 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaIter;
    1331       13478 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aParaEnd;
    1332       13478 :     OUpdatedParameter::iterator aUpdateFind = m_aUpdatedParameter.find(m_aKeyIter->first);
    1333       13478 :     if ( aUpdateFind == m_aUpdatedParameter.end() )
    1334             :     {
    1335       13478 :         aParaIter = m_aParameterValueForCache.get().begin();
    1336       13478 :         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       13478 :     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       13478 :     connectivity::ORowVector< ORowSetValue >::Vector::const_iterator aIter = m_aKeyIter->second.first->get().begin();
    1351       13478 :     SelectColumnsMetaData::const_iterator aPosIter = m_pKeyColumnNames->begin();
    1352       13478 :     SelectColumnsMetaData::const_iterator aPosEnd = m_pKeyColumnNames->end();
    1353       26956 :     for(;aPosIter != aPosEnd;++aPosIter,++aIter)
    1354       13478 :         setOneKeyColumnParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale);
    1355       13478 :     aPosIter = m_pForeignColumnNames->begin();
    1356       13478 :     aPosEnd = m_pForeignColumnNames->end();
    1357       13478 :     for(;aPosIter != aPosEnd;++aPosIter,++aIter)
    1358           0 :         setOneKeyColumnParameter(nPos,xParameter,*aIter,aPosIter->second.nType,aPosIter->second.nScale);
    1359             : 
    1360       13478 :     m_xSet = m_xStatement->executeQuery();
    1361             :     OSL_ENSURE(m_xSet.is(),"No resultset from statement!");
    1362       13478 :     return m_xSet->next();
    1363             : }
    1364             : 
    1365       13476 : void SAL_CALL OKeySet::refreshRow() throw(SQLException, RuntimeException)
    1366             : {
    1367       13476 :     invalidateRow();
    1368             : 
    1369       13476 :     if(isBeforeFirst() || isAfterLast())
    1370           0 :         return;
    1371             : 
    1372       13476 :     if ( m_aKeyIter->second.second.second.is() )
    1373             :     {
    1374           0 :         m_xRow = m_aKeyIter->second.second.second;
    1375           0 :         return;
    1376             :     }
    1377             : 
    1378       13476 :     bool bOK = doTryRefetch_throw();
    1379       13476 :     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       13476 :         m_xRow.set(m_xSet,UNO_QUERY);
    1417             :         OSL_ENSURE(m_xRow.is(),"No row from statement!");
    1418             :     }
    1419             : }
    1420             : 
    1421         526 : bool OKeySet::fetchRow()
    1422             : {
    1423             :     // fetch the next row and append on the keyset
    1424         526 :     bool bRet = false;
    1425         526 :     if ( !m_bRowCountFinal && (!m_nMaxRows || sal_Int32(m_aKeyMap.size()) < m_nMaxRows) )
    1426         526 :         bRet = m_xDriverSet->next();
    1427         526 :     if ( bRet )
    1428             :     {
    1429         517 :         ORowSetRow aKeyRow = new connectivity::ORowVector< ORowSetValue >((*m_pKeyColumnNames).size() + m_pForeignColumnNames->size());
    1430             : 
    1431         517 :         ::comphelper::disposeComponent(m_xSet);
    1432         517 :         m_xRow.set(m_xDriverRow, UNO_QUERY_THROW);
    1433             : 
    1434         517 :         connectivity::ORowVector< ORowSetValue >::Vector::iterator aIter = aKeyRow->get().begin();
    1435             :         // copy key columns
    1436         517 :         SelectColumnsMetaData::const_iterator aPosIter = (*m_pKeyColumnNames).begin();
    1437         517 :         SelectColumnsMetaData::const_iterator aPosEnd = (*m_pKeyColumnNames).end();
    1438        1034 :         for(;aPosIter != aPosEnd;++aPosIter,++aIter)
    1439             :         {
    1440         517 :             const SelectColumnDescription& rColDesc = aPosIter->second;
    1441         517 :             aIter->fill(rColDesc.nPosition, rColDesc.nType, m_xRow);
    1442             :         }
    1443             :         // copy missing columns from other tables
    1444         517 :         aPosIter = (*m_pForeignColumnNames).begin();
    1445         517 :         aPosEnd  = (*m_pForeignColumnNames).end();
    1446         517 :         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         517 :         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           9 :         m_bRowCountFinal = true;
    1455         526 :     return bRet;
    1456             : }
    1457             : 
    1458          23 : bool OKeySet::fillAllRows()
    1459             : {
    1460          23 :     if(m_bRowCountFinal)
    1461             :     {
    1462          19 :         return false;
    1463             :     }
    1464             :     else
    1465             :     {
    1466           4 :         while(fetchRow())
    1467             :             ;
    1468           4 :         return true;
    1469             :     }
    1470             : }
    1471             : 
    1472             : // XRow
    1473       27451 : sal_Bool SAL_CALL OKeySet::wasNull(  ) throw(SQLException, RuntimeException, std::exception)
    1474             : {
    1475       27451 :     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       27451 :     return m_xRow->wasNull();
    1480             : }
    1481             : 
    1482       27451 : inline void OKeySet::ensureRowForData( ) throw(SQLException, RuntimeException)
    1483             : {
    1484       27451 :     if (! m_xRow.is() )
    1485       13475 :         refreshRow();
    1486       27451 :     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       27451 : }
    1491             : 
    1492       13739 : OUString SAL_CALL OKeySet::getString( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
    1493             : {
    1494       13739 :     ensureRowForData();
    1495       13739 :     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       13676 : sal_Int32 SAL_CALL OKeySet::getInt( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
    1517             : {
    1518       13676 :     ensureRowForData();
    1519       13676 :     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          36 : ::com::sun::star::util::Date SAL_CALL OKeySet::getDate( sal_Int32 columnIndex ) throw(SQLException, RuntimeException, std::exception)
    1547             : {
    1548          36 :     ensureRowForData();
    1549          36 :     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           1 : bool SAL_CALL OKeySet::rowInserted(  ) throw(SQLException, RuntimeException)
    1612             : {
    1613           1 :     return m_aKeyIter != m_aKeyMap.begin() && m_aKeyIter != m_aKeyMap.end() && m_aKeyIter->second.second.first == 1;
    1614             : }
    1615             : 
    1616          20 : bool SAL_CALL OKeySet::rowDeleted(  ) throw(SQLException, RuntimeException)
    1617             : {
    1618          20 :     bool bDeleted = m_bDeleted;
    1619          20 :     m_bDeleted = false;
    1620          20 :     return bDeleted;
    1621             : }
    1622             : 
    1623             : namespace dbaccess
    1624             : {
    1625             : 
    1626          45 : 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          45 :         Sequence< OUString> aSelNames(_rxQueryColumns->getElementNames());
    1634          45 :         const OUString* pSelIter     = aSelNames.getConstArray();
    1635          45 :         const OUString* pSelEnd      = pSelIter + aSelNames.getLength();
    1636             : 
    1637          45 :         const OUString* pTblColumnIter   = _aColumnNames.getConstArray();
    1638          45 :         const OUString* pTblColumnEnd    = pTblColumnIter + _aColumnNames.getLength();
    1639             : 
    1640          45 :         ::comphelper::UStringMixEqual bCase(o_rColumnNames.key_comp().isCaseSensitive());
    1641             : 
    1642         275 :         for(sal_Int32 nPos = 1;pSelIter != pSelEnd;++pSelIter,++nPos)
    1643             :         {
    1644         230 :             Reference<XPropertySet> xQueryColumnProp(_rxQueryColumns->getByName(*pSelIter),UNO_QUERY_THROW);
    1645         460 :             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         230 :             xQueryColumnProp->getPropertyValue(PROPERTY_REALNAME)   >>= sRealName;
    1649         230 :             xQueryColumnProp->getPropertyValue(PROPERTY_TABLENAME)  >>= sTableName;
    1650             : 
    1651         807 :             for(;pTblColumnIter != pTblColumnEnd;++pTblColumnIter)
    1652             :             {
    1653         689 :                 if(bCase(sRealName,*pTblColumnIter) && bCase(_rsUpdateTableName,sTableName) && o_rColumnNames.find(*pTblColumnIter) == o_rColumnNames.end())
    1654             :                 {
    1655         112 :                     sal_Int32 nType = 0;
    1656         112 :                     xQueryColumnProp->getPropertyValue(PROPERTY_TYPE)   >>= nType;
    1657         112 :                     sal_Int32 nScale = 0;
    1658         112 :                     xQueryColumnProp->getPropertyValue(PROPERTY_SCALE)  >>= nScale;
    1659         112 :                     OUString sColumnDefault;
    1660         112 :                     if ( xQueryColumnProp->getPropertySetInfo()->hasPropertyByName(PROPERTY_DEFAULTVALUE) )
    1661         112 :                         xQueryColumnProp->getPropertyValue(PROPERTY_DEFAULTVALUE) >>= sColumnDefault;
    1662             : 
    1663         112 :                     sal_Int32 nNullable = ColumnValue::NULLABLE_UNKNOWN;
    1664         112 :                     OSL_VERIFY( xQueryColumnProp->getPropertyValue( PROPERTY_ISNULLABLE ) >>= nNullable );
    1665             : 
    1666         224 :                     SelectColumnDescription aColDesc( nPos, nType, nScale, nNullable != sdbc::ColumnValue::NO_NULLS, sColumnDefault );
    1667         224 :                     OUString sName;
    1668         112 :                     if ( i_bAppendTableName )
    1669             :                     {
    1670          57 :                         sName = sTableName + "." + sRealName;
    1671          57 :                         aColDesc.sRealName = sRealName;
    1672          57 :                         aColDesc.sTableName = sTableName;
    1673             :                     }
    1674             :                     else
    1675             :                     {
    1676          55 :                         sName = sRealName;
    1677             :                     }
    1678         112 :                     o_rColumnNames[sName] = aColDesc;
    1679             : 
    1680         224 :                     break;
    1681             :                 }
    1682             :             }
    1683         230 :             pTblColumnIter = _aColumnNames.getConstArray();
    1684         275 :         }
    1685          45 :     }
    1686             : }
    1687             : 
    1688           6 : void OKeySet::impl_convertValue_throw(const ORowSetRow& _rInsertRow,const SelectColumnDescription& i_aMetaData)
    1689             : {
    1690           6 :     ORowSetValue& aValue((_rInsertRow->get())[i_aMetaData.nPosition]);
    1691           6 :     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           6 :             break;
    1706             :     }
    1707           6 : }
    1708             : 
    1709             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11