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