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

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

Generated by: LCOV version 1.10