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: */
|