1*96de5490SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*96de5490SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*96de5490SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*96de5490SAndrew Rist  * distributed with this work for additional information
6*96de5490SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*96de5490SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*96de5490SAndrew Rist  * "License"); you may not use this file except in compliance
9*96de5490SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*96de5490SAndrew Rist  *
11*96de5490SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*96de5490SAndrew Rist  *
13*96de5490SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*96de5490SAndrew Rist  * software distributed under the License is distributed on an
15*96de5490SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*96de5490SAndrew Rist  * KIND, either express or implied.  See the License for the
17*96de5490SAndrew Rist  * specific language governing permissions and limitations
18*96de5490SAndrew Rist  * under the License.
19*96de5490SAndrew Rist  *
20*96de5490SAndrew Rist  *************************************************************/
21*96de5490SAndrew Rist 
22*96de5490SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_dbaccess.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "OptimisticSet.hxx"
28cdf0e10cSrcweir #include "core_resource.hxx"
29cdf0e10cSrcweir #include "core_resource.hrc"
30cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp>
31cdf0e10cSrcweir #include <com/sun/star/sdbc/XDatabaseMetaData.hpp>
32cdf0e10cSrcweir #include <com/sun/star/sdbc/ColumnValue.hpp>
33cdf0e10cSrcweir #include <com/sun/star/sdbc/XPreparedStatement.hpp>
34cdf0e10cSrcweir #include <com/sun/star/sdbc/XParameters.hpp>
35cdf0e10cSrcweir #include <com/sun/star/sdbc/XGeneratedResultSet.hpp>
36cdf0e10cSrcweir #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
37cdf0e10cSrcweir #include <com/sun/star/sdb/SQLFilterOperator.hpp>
38cdf0e10cSrcweir #include <com/sun/star/sdbc/XColumnLocate.hpp>
39cdf0e10cSrcweir #include <com/sun/star/container/XIndexAccess.hpp>
40cdf0e10cSrcweir #include "dbastrings.hrc"
41cdf0e10cSrcweir #include "apitools.hxx"
42cdf0e10cSrcweir #include <com/sun/star/sdbcx/XKeysSupplier.hpp>
43cdf0e10cSrcweir #include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp>
44cdf0e10cSrcweir #include <com/sun/star/sdbcx/XIndexesSupplier.hpp>
45cdf0e10cSrcweir #include <cppuhelper/typeprovider.hxx>
46cdf0e10cSrcweir #include <comphelper/types.hxx>
47cdf0e10cSrcweir #include <com/sun/star/sdbcx/KeyType.hpp>
48cdf0e10cSrcweir #include <connectivity/dbtools.hxx>
49cdf0e10cSrcweir #include <connectivity/dbexception.hxx>
50cdf0e10cSrcweir #include <list>
51cdf0e10cSrcweir #include <algorithm>
52cdf0e10cSrcweir #include <string.h>
53cdf0e10cSrcweir #include <com/sun/star/io/XInputStream.hpp>
54cdf0e10cSrcweir #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
55cdf0e10cSrcweir #include "querycomposer.hxx"
56cdf0e10cSrcweir #include "composertools.hxx"
57cdf0e10cSrcweir #include <tools/debug.hxx>
58cdf0e10cSrcweir #include <string.h>
59cdf0e10cSrcweir #include <rtl/logfile.hxx>
60cdf0e10cSrcweir 
61cdf0e10cSrcweir using namespace dbaccess;
62cdf0e10cSrcweir using namespace ::connectivity;
63cdf0e10cSrcweir using namespace ::dbtools;
64cdf0e10cSrcweir using namespace ::com::sun::star::uno;
65cdf0e10cSrcweir using namespace ::com::sun::star::beans;
66cdf0e10cSrcweir using namespace ::com::sun::star::sdbc;
67cdf0e10cSrcweir using namespace ::com::sun::star::sdb;
68cdf0e10cSrcweir using namespace ::com::sun::star::sdbcx;
69cdf0e10cSrcweir using namespace ::com::sun::star::container;
70cdf0e10cSrcweir using namespace ::com::sun::star::lang;
71cdf0e10cSrcweir using namespace ::com::sun::star::util;
72cdf0e10cSrcweir using namespace ::com::sun::star::io;
73cdf0e10cSrcweir using namespace ::com::sun::star;
74cdf0e10cSrcweir using namespace ::cppu;
75cdf0e10cSrcweir using namespace ::osl;
76cdf0e10cSrcweir 
77cdf0e10cSrcweir DECLARE_STL_USTRINGACCESS_MAP(::rtl::OUStringBuffer,TSQLStatements);
78cdf0e10cSrcweir namespace
79cdf0e10cSrcweir {
lcl_fillKeyCondition(const::rtl::OUString & i_sTableName,const::rtl::OUString & i_sQuotedColumnName,const ORowSetValue & i_aValue,TSQLStatements & io_aKeyConditions)80cdf0e10cSrcweir     void lcl_fillKeyCondition(const ::rtl::OUString& i_sTableName,const ::rtl::OUString& i_sQuotedColumnName,const ORowSetValue& i_aValue,TSQLStatements& io_aKeyConditions)
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir         ::rtl::OUStringBuffer& rKeyCondition = io_aKeyConditions[i_sTableName];
83cdf0e10cSrcweir         if ( rKeyCondition.getLength() )
84cdf0e10cSrcweir             rKeyCondition.appendAscii(" AND ");
85cdf0e10cSrcweir 		rKeyCondition.append(i_sQuotedColumnName);
86cdf0e10cSrcweir 		if ( i_aValue.isNull() )
87cdf0e10cSrcweir 			rKeyCondition.appendAscii(" IS NULL");
88cdf0e10cSrcweir 		else
89cdf0e10cSrcweir 			rKeyCondition.appendAscii(" = ?");
90cdf0e10cSrcweir     }
91cdf0e10cSrcweir }
92cdf0e10cSrcweir 
DBG_NAME(OptimisticSet)93cdf0e10cSrcweir DBG_NAME(OptimisticSet)
94cdf0e10cSrcweir // -------------------------------------------------------------------------
95cdf0e10cSrcweir OptimisticSet::OptimisticSet(const ::comphelper::ComponentContext& _rContext,
96cdf0e10cSrcweir                              const Reference< XConnection>& i_xConnection,
97cdf0e10cSrcweir                              const Reference< XSingleSelectQueryAnalyzer >& _xComposer,
98cdf0e10cSrcweir                              const ORowSetValueVector& _aParameterValueForCache,
99cdf0e10cSrcweir                              sal_Int32 i_nMaxRows,
100cdf0e10cSrcweir                              sal_Int32& o_nRowCount)
101cdf0e10cSrcweir             :OKeySet(NULL,NULL,::rtl::OUString(),_xComposer,_aParameterValueForCache,i_nMaxRows,o_nRowCount)
102cdf0e10cSrcweir             ,m_aSqlParser( _rContext.getLegacyServiceFactory() )
103cdf0e10cSrcweir             ,m_aSqlIterator( i_xConnection, Reference<XTablesSupplier>(_xComposer,UNO_QUERY)->getTables(), m_aSqlParser, NULL )
104cdf0e10cSrcweir             ,m_bResultSetChanged(false)
105cdf0e10cSrcweir {
106cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::OptimisticSet" );
107cdf0e10cSrcweir     DBG_CTOR(OptimisticSet,NULL);
108cdf0e10cSrcweir }
109cdf0e10cSrcweir // -----------------------------------------------------------------------------
~OptimisticSet()110cdf0e10cSrcweir OptimisticSet::~OptimisticSet()
111cdf0e10cSrcweir {
112cdf0e10cSrcweir     DBG_DTOR(OptimisticSet,NULL);
113cdf0e10cSrcweir }
114cdf0e10cSrcweir // -----------------------------------------------------------------------------
construct(const Reference<XResultSet> & _xDriverSet,const::rtl::OUString & i_sRowSetFilter)115cdf0e10cSrcweir void OptimisticSet::construct(const Reference< XResultSet>& _xDriverSet,const ::rtl::OUString& i_sRowSetFilter)
116cdf0e10cSrcweir {
117cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::construct" );
118cdf0e10cSrcweir 	OCacheSet::construct(_xDriverSet,i_sRowSetFilter);
119cdf0e10cSrcweir 	initColumns();
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     Reference<XDatabaseMetaData> xMeta = m_xConnection->getMetaData();
122cdf0e10cSrcweir     bool bCase = (xMeta.is() && xMeta->supportsMixedCaseQuotedIdentifiers()) ? true : false;
123cdf0e10cSrcweir     Reference<XColumnsSupplier> xQueryColSup(m_xComposer,UNO_QUERY);
124cdf0e10cSrcweir     const Reference<XNameAccess> xQueryColumns = xQueryColSup->getColumns();
125cdf0e10cSrcweir     const Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY);
126cdf0e10cSrcweir     const Reference<XNameAccess> xTables = xTabSup->getTables();
127cdf0e10cSrcweir     const Sequence< ::rtl::OUString> aTableNames = xTables->getElementNames();
128cdf0e10cSrcweir     const ::rtl::OUString* pTableNameIter = aTableNames.getConstArray();
129cdf0e10cSrcweir     const ::rtl::OUString* pTableNameEnd = pTableNameIter + aTableNames.getLength();
130cdf0e10cSrcweir     for( ; pTableNameIter != pTableNameEnd ; ++pTableNameIter)
131cdf0e10cSrcweir     {
132cdf0e10cSrcweir         ::std::auto_ptr<SelectColumnsMetaData> pKeyColumNames(new SelectColumnsMetaData(bCase));
133cdf0e10cSrcweir         findTableColumnsMatching_throw(xTables->getByName(*pTableNameIter),*pTableNameIter,xMeta,xQueryColumns,pKeyColumNames);
134cdf0e10cSrcweir         m_pKeyColumnNames->insert(pKeyColumNames->begin(),pKeyColumNames->end());
135cdf0e10cSrcweir     }
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 	// the first row is empty because it's now easier for us to distinguish	when we are beforefirst or first
138cdf0e10cSrcweir 	// without extra variable to be set
139cdf0e10cSrcweir     m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL))));
140cdf0e10cSrcweir 	m_aKeyIter = m_aKeyMap.begin();
141cdf0e10cSrcweir 
142cdf0e10cSrcweir 	::rtl::OUStringBuffer aFilter = createKeyFilter();
143cdf0e10cSrcweir 
144cdf0e10cSrcweir     Reference< XSingleSelectQueryComposer> xSourceComposer(m_xComposer,UNO_QUERY);
145cdf0e10cSrcweir 	Reference< XMultiServiceFactory >  xFactory(m_xConnection, UNO_QUERY_THROW);
146cdf0e10cSrcweir 	Reference<XSingleSelectQueryComposer> xAnalyzer(xFactory->createInstance(SERVICE_NAME_SINGLESELECTQUERYCOMPOSER),UNO_QUERY);
147cdf0e10cSrcweir     ::rtl::OUString sQuery = xSourceComposer->getQuery();
148cdf0e10cSrcweir 	xAnalyzer->setElementaryQuery(xSourceComposer->getElementaryQuery());
149cdf0e10cSrcweir     // check for joins
150cdf0e10cSrcweir     ::rtl::OUString aErrorMsg;
151cdf0e10cSrcweir     ::std::auto_ptr<OSQLParseNode> pStatementNode( m_aSqlParser.parseTree( aErrorMsg, sQuery ) );
152cdf0e10cSrcweir     m_aSqlIterator.setParseTree( pStatementNode.get() );
153cdf0e10cSrcweir 	m_aSqlIterator.traverseAll();
154cdf0e10cSrcweir     fillJoinedColumns_throw(m_aSqlIterator.getJoinConditions());
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     const ::rtl::OUString sComposerFilter = m_xComposer->getFilter();
157cdf0e10cSrcweir     if ( i_sRowSetFilter.getLength() || (sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter) )
158cdf0e10cSrcweir     {
159cdf0e10cSrcweir         FilterCreator aFilterCreator;
160cdf0e10cSrcweir         if ( sComposerFilter.getLength() && sComposerFilter != i_sRowSetFilter )
161cdf0e10cSrcweir             aFilterCreator.append( sComposerFilter );
162cdf0e10cSrcweir         aFilterCreator.append( i_sRowSetFilter );
163cdf0e10cSrcweir         aFilterCreator.append( aFilter.makeStringAndClear() );
164cdf0e10cSrcweir         aFilter = aFilterCreator.getComposedAndClear();
165cdf0e10cSrcweir     }
166cdf0e10cSrcweir     xAnalyzer->setFilter(aFilter.makeStringAndClear());
167cdf0e10cSrcweir 	m_xStatement = m_xConnection->prepareStatement(xAnalyzer->getQueryWithSubstitution());
168cdf0e10cSrcweir 	::comphelper::disposeComponent(xAnalyzer);
169cdf0e10cSrcweir }
170cdf0e10cSrcweir // -------------------------------------------------------------------------
171cdf0e10cSrcweir // ::com::sun::star::sdbcx::XDeleteRows
deleteRows(const Sequence<Any> &,const connectivity::OSQLTable &)172cdf0e10cSrcweir Sequence< sal_Int32 > SAL_CALL OptimisticSet::deleteRows( const Sequence< Any >& /*rows*/ ,const connectivity::OSQLTable& /*_xTable*/) throw(SQLException, RuntimeException)
173cdf0e10cSrcweir {
174cdf0e10cSrcweir 	Sequence< sal_Int32 > aRet;
175cdf0e10cSrcweir 	return aRet;
176cdf0e10cSrcweir }
177cdf0e10cSrcweir // -------------------------------------------------------------------------
updateRow(const ORowSetRow & _rInsertRow,const ORowSetRow & _rOrginalRow,const connectivity::OSQLTable &)178cdf0e10cSrcweir void SAL_CALL OptimisticSet::updateRow(const ORowSetRow& _rInsertRow ,const ORowSetRow& _rOrginalRow,const connectivity::OSQLTable& /*_xTable*/  ) throw(SQLException, RuntimeException)
179cdf0e10cSrcweir {
180cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::updateRow" );
181cdf0e10cSrcweir     if ( m_aJoinedKeyColumns.empty() )
182cdf0e10cSrcweir         throw SQLException();
183cdf0e10cSrcweir 	// list all cloumns that should be set
184cdf0e10cSrcweir 	static ::rtl::OUString s_sPara	= ::rtl::OUString::createFromAscii(" = ?");
185cdf0e10cSrcweir 	::rtl::OUString aQuote	= getIdentifierQuoteString();
186cdf0e10cSrcweir 	static ::rtl::OUString aAnd		= ::rtl::OUString::createFromAscii(" AND ");
187cdf0e10cSrcweir     ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL"));
188cdf0e10cSrcweir     ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
189cdf0e10cSrcweir 
190cdf0e10cSrcweir 	::rtl::OUString aColumnName;
191cdf0e10cSrcweir     ::rtl::OUStringBuffer sKeyCondition;
192cdf0e10cSrcweir     ::std::map< ::rtl::OUString,bool > aResultSetChanged;
193cdf0e10cSrcweir     TSQLStatements aKeyConditions;
194cdf0e10cSrcweir     TSQLStatements aIndexConditions;
195cdf0e10cSrcweir     TSQLStatements aSql;
196cdf0e10cSrcweir 
197cdf0e10cSrcweir 	// sal_Int32 i = 1;
198cdf0e10cSrcweir 	// here we build the condition part for the update statement
199cdf0e10cSrcweir 	SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
200cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
201cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
202cdf0e10cSrcweir 	{
203cdf0e10cSrcweir         if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() )
204cdf0e10cSrcweir             aResultSetChanged[aIter->second.sTableName] = false;
205cdf0e10cSrcweir         const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName);
206cdf0e10cSrcweir         if ( m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
207cdf0e10cSrcweir 		{
208cdf0e10cSrcweir             aResultSetChanged[aIter->second.sTableName] = m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end();
209cdf0e10cSrcweir             lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rOrginalRow->get())[aIter->second.nPosition],aKeyConditions);
210cdf0e10cSrcweir 		}
211cdf0e10cSrcweir 		if((_rInsertRow->get())[aIter->second.nPosition].isModified())
212cdf0e10cSrcweir 		{
213cdf0e10cSrcweir             if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() )
214cdf0e10cSrcweir                 throw SQLException();
215cdf0e10cSrcweir 
216cdf0e10cSrcweir             ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition);
217cdf0e10cSrcweir             if ( aJoinIter != m_aJoinedColumns.end() )
218cdf0e10cSrcweir             {
219cdf0e10cSrcweir                 (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition];
220cdf0e10cSrcweir             }
221cdf0e10cSrcweir             ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName];
222cdf0e10cSrcweir             if ( rPart.getLength() )
223cdf0e10cSrcweir                 rPart.appendAscii(", ");
224cdf0e10cSrcweir 			rPart.append(sQuotedColumnName);
225cdf0e10cSrcweir 			rPart.append(s_sPara);
226cdf0e10cSrcweir 		}
227cdf0e10cSrcweir 	}
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 	if( aSql.empty() )
230cdf0e10cSrcweir         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection );
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 	if( aKeyConditions.empty() )
233cdf0e10cSrcweir         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_CONDITION_FOR_PK ), SQL_GENERAL_ERROR, m_xConnection );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir     static const ::rtl::OUString s_sUPDATE(RTL_CONSTASCII_USTRINGPARAM("UPDATE "));
236cdf0e10cSrcweir     static const ::rtl::OUString s_sSET(RTL_CONSTASCII_USTRINGPARAM(" SET "));
237cdf0e10cSrcweir 
238cdf0e10cSrcweir     Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
239cdf0e10cSrcweir 
240cdf0e10cSrcweir     TSQLStatements::iterator aSqlIter = aSql.begin();
241cdf0e10cSrcweir     TSQLStatements::iterator aSqlEnd  = aSql.end();
242cdf0e10cSrcweir     for(;aSqlIter != aSqlEnd ; ++aSqlIter)
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir         if ( aSqlIter->second.getLength() )
245cdf0e10cSrcweir         {
246cdf0e10cSrcweir             m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first];
247cdf0e10cSrcweir 	        ::rtl::OUStringBuffer sSql(s_sUPDATE);
248cdf0e10cSrcweir             ::rtl::OUString sCatalog,sSchema,sTable;
249cdf0e10cSrcweir 			::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
250cdf0e10cSrcweir 			sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) );
251cdf0e10cSrcweir 	        sSql.append(s_sSET);
252cdf0e10cSrcweir             sSql.append(aSqlIter->second);
253cdf0e10cSrcweir             ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first];
254cdf0e10cSrcweir             bool bAddWhere = true;
255cdf0e10cSrcweir             if ( rCondition.getLength() )
256cdf0e10cSrcweir             {
257cdf0e10cSrcweir                 bAddWhere = false;
258cdf0e10cSrcweir                 sSql.appendAscii(" WHERE ");
259cdf0e10cSrcweir                 sSql.append( rCondition );
260cdf0e10cSrcweir             }
261cdf0e10cSrcweir             executeUpdate(_rInsertRow ,_rOrginalRow,sSql.makeStringAndClear(),aSqlIter->first);
262cdf0e10cSrcweir         }
263cdf0e10cSrcweir     }
264cdf0e10cSrcweir }
265cdf0e10cSrcweir // -------------------------------------------------------------------------
insertRow(const ORowSetRow & _rInsertRow,const connectivity::OSQLTable &)266cdf0e10cSrcweir void SAL_CALL OptimisticSet::insertRow( const ORowSetRow& _rInsertRow,const connectivity::OSQLTable& /*_xTable*/ ) throw(SQLException, RuntimeException)
267cdf0e10cSrcweir {
268cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::insertRow" );
269cdf0e10cSrcweir     TSQLStatements aSql;
270cdf0e10cSrcweir     TSQLStatements aParameter;
271cdf0e10cSrcweir     TSQLStatements aKeyConditions;
272cdf0e10cSrcweir     ::std::map< ::rtl::OUString,bool > aResultSetChanged;
273cdf0e10cSrcweir     ::rtl::OUString aQuote	= getIdentifierQuoteString();
274cdf0e10cSrcweir     static ::rtl::OUString aAnd		= ::rtl::OUString::createFromAscii(" AND ");
275cdf0e10cSrcweir     ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL"));
276cdf0e10cSrcweir     ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
277cdf0e10cSrcweir 
278cdf0e10cSrcweir 	// here we build the condition part for the update statement
279cdf0e10cSrcweir 	SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
280cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
281cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
282cdf0e10cSrcweir 	{
283cdf0e10cSrcweir         if ( aResultSetChanged.find( aIter->second.sTableName ) == aResultSetChanged.end() )
284cdf0e10cSrcweir             aResultSetChanged[aIter->second.sTableName] = false;
285cdf0e10cSrcweir 
286cdf0e10cSrcweir         const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName);
287cdf0e10cSrcweir         if ( (_rInsertRow->get())[aIter->second.nPosition].isModified() )
288cdf0e10cSrcweir 		{
289cdf0e10cSrcweir             if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) != m_aJoinedKeyColumns.end() )
290cdf0e10cSrcweir 		    {
291cdf0e10cSrcweir                 lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rInsertRow->get())[aIter->second.nPosition],aKeyConditions);
292cdf0e10cSrcweir                 aResultSetChanged[aIter->second.sTableName] = true;
293cdf0e10cSrcweir             }
294cdf0e10cSrcweir             ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(aIter->second.nPosition);
295cdf0e10cSrcweir             if ( aJoinIter != m_aJoinedColumns.end() )
296cdf0e10cSrcweir             {
297cdf0e10cSrcweir                 (_rInsertRow->get())[aJoinIter->second] = (_rInsertRow->get())[aIter->second.nPosition];
298cdf0e10cSrcweir             }
299cdf0e10cSrcweir             ::rtl::OUStringBuffer& rPart = aSql[aIter->second.sTableName];
300cdf0e10cSrcweir             if ( rPart.getLength() )
301cdf0e10cSrcweir                 rPart.appendAscii(", ");
302cdf0e10cSrcweir 			rPart.append(sQuotedColumnName);
303cdf0e10cSrcweir             ::rtl::OUStringBuffer& rParam = aParameter[aIter->second.sTableName];
304cdf0e10cSrcweir             if ( rParam.getLength() )
305cdf0e10cSrcweir                 rParam.appendAscii(", ");
306cdf0e10cSrcweir 			rParam.appendAscii("?");
307cdf0e10cSrcweir         }
308cdf0e10cSrcweir     }
309cdf0e10cSrcweir     if ( aParameter.empty() )
310cdf0e10cSrcweir         ::dbtools::throwSQLException( DBACORE_RESSTRING( RID_STR_NO_VALUE_CHANGED ), SQL_GENERAL_ERROR, m_xConnection );
311cdf0e10cSrcweir 
312cdf0e10cSrcweir     Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
313cdf0e10cSrcweir     static const ::rtl::OUString s_sINSERT(RTL_CONSTASCII_USTRINGPARAM("INSERT INTO "));
314cdf0e10cSrcweir     static const ::rtl::OUString s_sVALUES(RTL_CONSTASCII_USTRINGPARAM(") VALUES ( "));
315cdf0e10cSrcweir     TSQLStatements::iterator aSqlIter = aSql.begin();
316cdf0e10cSrcweir     TSQLStatements::iterator aSqlEnd  = aSql.end();
317cdf0e10cSrcweir     for(;aSqlIter != aSqlEnd ; ++aSqlIter)
318cdf0e10cSrcweir     {
319cdf0e10cSrcweir         if ( aSqlIter->second.getLength() )
320cdf0e10cSrcweir         {
321cdf0e10cSrcweir             m_bResultSetChanged = m_bResultSetChanged || aResultSetChanged[aSqlIter->first];
322cdf0e10cSrcweir             ::rtl::OUStringBuffer sSql(s_sINSERT);
323cdf0e10cSrcweir             ::rtl::OUString sCatalog,sSchema,sTable;
324cdf0e10cSrcweir 			::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
325cdf0e10cSrcweir             ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
326cdf0e10cSrcweir             sSql.append(sComposedTableName);
327cdf0e10cSrcweir             sSql.appendAscii(" ( ");
328cdf0e10cSrcweir             sSql.append(aSqlIter->second);
329cdf0e10cSrcweir             sSql.append(s_sVALUES);
330cdf0e10cSrcweir             sSql.append(aParameter[aSqlIter->first]);
331cdf0e10cSrcweir             sSql.appendAscii(" )");
332cdf0e10cSrcweir 
333cdf0e10cSrcweir             ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first];
334cdf0e10cSrcweir             if ( rCondition.getLength() )
335cdf0e10cSrcweir             {
336cdf0e10cSrcweir                 ::rtl::OUStringBuffer sQuery;
337cdf0e10cSrcweir                 sQuery.appendAscii("SELECT ");
338cdf0e10cSrcweir                 sQuery.append(aSqlIter->second);
339cdf0e10cSrcweir                 sQuery.appendAscii(" FROM ");
340cdf0e10cSrcweir                 sQuery.append(sComposedTableName);
341cdf0e10cSrcweir                 sQuery.appendAscii(" WHERE ");
342cdf0e10cSrcweir                 sQuery.append(rCondition);
343cdf0e10cSrcweir 
344cdf0e10cSrcweir                 try
345cdf0e10cSrcweir                 {
346cdf0e10cSrcweir                     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear()));
347cdf0e10cSrcweir 	                Reference< XParameters > xParameter(xPrep,UNO_QUERY);
348cdf0e10cSrcweir                     // and then the values of the where condition
349cdf0e10cSrcweir 	                SelectColumnsMetaData::iterator aKeyCol = m_pKeyColumnNames->begin();
350cdf0e10cSrcweir                     SelectColumnsMetaData::iterator aKeysEnd = m_pKeyColumnNames->end();
351cdf0e10cSrcweir                     sal_Int32 i = 1;
352cdf0e10cSrcweir 	                for(;aKeyCol != aKeysEnd;++aKeyCol)
353cdf0e10cSrcweir 	                {
354cdf0e10cSrcweir                         if ( aKeyCol->second.sTableName == aSqlIter->first )
355cdf0e10cSrcweir                         {
356cdf0e10cSrcweir 		                    setParameter(i++,xParameter,(_rInsertRow->get())[aKeyCol->second.nPosition],aKeyCol->second.nType,aKeyCol->second.nScale);
357cdf0e10cSrcweir                         }
358cdf0e10cSrcweir 	                }
359cdf0e10cSrcweir                     Reference<XResultSet> xRes = xPrep->executeQuery();
360cdf0e10cSrcweir 				    Reference<XRow> xRow(xRes,UNO_QUERY);
361cdf0e10cSrcweir 				    if ( xRow.is() && xRes->next() )
362cdf0e10cSrcweir 				    {
363cdf0e10cSrcweir                         m_bResultSetChanged = true;
364cdf0e10cSrcweir                         continue;
365cdf0e10cSrcweir                     }
366cdf0e10cSrcweir                 }
367cdf0e10cSrcweir                 catch(const SQLException&)
368cdf0e10cSrcweir                 {
369cdf0e10cSrcweir                 }
370cdf0e10cSrcweir             }
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 			executeInsert(_rInsertRow,sSql.makeStringAndClear(),aSqlIter->first);
373cdf0e10cSrcweir         }
374cdf0e10cSrcweir     }
375cdf0e10cSrcweir }
376cdf0e10cSrcweir // -------------------------------------------------------------------------
deleteRow(const ORowSetRow & _rDeleteRow,const connectivity::OSQLTable &)377cdf0e10cSrcweir void SAL_CALL OptimisticSet::deleteRow(const ORowSetRow& _rDeleteRow,const connectivity::OSQLTable& /*_xTable*/   ) throw(SQLException, RuntimeException)
378cdf0e10cSrcweir {
379cdf0e10cSrcweir     ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
380cdf0e10cSrcweir     ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL"));
381cdf0e10cSrcweir     static const ::rtl::OUString s_sAnd(RTL_CONSTASCII_USTRINGPARAM(" AND "));
382cdf0e10cSrcweir     ::rtl::OUString aQuote	= getIdentifierQuoteString();
383cdf0e10cSrcweir     ::rtl::OUString aColumnName;
384cdf0e10cSrcweir     ::rtl::OUStringBuffer sKeyCondition,sIndexCondition;
385cdf0e10cSrcweir 	::std::vector<sal_Int32> aIndexColumnPositions;
386cdf0e10cSrcweir     TSQLStatements aKeyConditions;
387cdf0e10cSrcweir     TSQLStatements aIndexConditions;
388cdf0e10cSrcweir     TSQLStatements aSql;
389cdf0e10cSrcweir 
390cdf0e10cSrcweir 	// sal_Int32 i = 1;
391cdf0e10cSrcweir 	// here we build the condition part for the update statement
392cdf0e10cSrcweir 	SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
393cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
394cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
395cdf0e10cSrcweir 	{
396cdf0e10cSrcweir         if ( m_aJoinedKeyColumns.find(aIter->second.nPosition) == m_aJoinedKeyColumns.end() && m_pKeyColumnNames->find(aIter->first) != m_pKeyColumnNames->end() )
397cdf0e10cSrcweir 		{
398cdf0e10cSrcweir             // only delete rows which aren't the key in the join
399cdf0e10cSrcweir             const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aIter->second.sRealName);
400cdf0e10cSrcweir             lcl_fillKeyCondition(aIter->second.sTableName,sQuotedColumnName,(_rDeleteRow->get())[aIter->second.nPosition],aKeyConditions);
401cdf0e10cSrcweir 		}
402cdf0e10cSrcweir     }
403cdf0e10cSrcweir     Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
404cdf0e10cSrcweir     TSQLStatements::iterator aSqlIter = aKeyConditions.begin();
405cdf0e10cSrcweir     TSQLStatements::iterator aSqlEnd  = aKeyConditions.end();
406cdf0e10cSrcweir     for(;aSqlIter != aSqlEnd ; ++aSqlIter)
407cdf0e10cSrcweir     {
408cdf0e10cSrcweir         ::rtl::OUStringBuffer& rCondition = aSqlIter->second;
409cdf0e10cSrcweir         if ( rCondition.getLength() )
410cdf0e10cSrcweir         {
411cdf0e10cSrcweir 	        ::rtl::OUStringBuffer sSql;
412cdf0e10cSrcweir             sSql.appendAscii("DELETE FROM ");
413cdf0e10cSrcweir             ::rtl::OUString sCatalog,sSchema,sTable;
414cdf0e10cSrcweir 			::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
415cdf0e10cSrcweir 			sSql.append( ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable ) );
416cdf0e10cSrcweir 	        sSql.appendAscii(" WHERE ");
417cdf0e10cSrcweir             sSql.append( rCondition );
418cdf0e10cSrcweir             executeDelete(_rDeleteRow,sSql.makeStringAndClear(),aSqlIter->first);
419cdf0e10cSrcweir         }
420cdf0e10cSrcweir     }
421cdf0e10cSrcweir }
422cdf0e10cSrcweir // -------------------------------------------------------------------------
executeDelete(const ORowSetRow & _rDeleteRow,const::rtl::OUString & i_sSQL,const::rtl::OUString & i_sTableName)423cdf0e10cSrcweir void OptimisticSet::executeDelete(const ORowSetRow& _rDeleteRow,const ::rtl::OUString& i_sSQL,const ::rtl::OUString& i_sTableName)
424cdf0e10cSrcweir {
425cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::executeDelete" );
426cdf0e10cSrcweir 
427cdf0e10cSrcweir 	// now create end execute the prepared statement
428cdf0e10cSrcweir 	Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(i_sSQL));
429cdf0e10cSrcweir 	Reference< XParameters > xParameter(xPrep,UNO_QUERY);
430cdf0e10cSrcweir 
431cdf0e10cSrcweir 	SelectColumnsMetaData::const_iterator aIter = m_pKeyColumnNames->begin();
432cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aEnd = m_pKeyColumnNames->end();
433cdf0e10cSrcweir 	sal_Int32 i = 1;
434cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
435cdf0e10cSrcweir 	{
436cdf0e10cSrcweir         if ( aIter->second.sTableName == i_sTableName )
437cdf0e10cSrcweir 		    setParameter(i++,xParameter,(_rDeleteRow->get())[aIter->second.nPosition],aIter->second.nType,aIter->second.nScale);
438cdf0e10cSrcweir 	}
439cdf0e10cSrcweir 	m_bDeleted = xPrep->executeUpdate() > 0;
440cdf0e10cSrcweir 
441cdf0e10cSrcweir 	if(m_bDeleted)
442cdf0e10cSrcweir 	{
443cdf0e10cSrcweir 		sal_Int32 nBookmark = ::comphelper::getINT32((_rDeleteRow->get())[0].getAny());
444cdf0e10cSrcweir 		if(m_aKeyIter == m_aKeyMap.find(nBookmark) && m_aKeyIter != m_aKeyMap.end())
445cdf0e10cSrcweir 			++m_aKeyIter;
446cdf0e10cSrcweir 		m_aKeyMap.erase(nBookmark);
447cdf0e10cSrcweir 		m_bDeleted = sal_True;
448cdf0e10cSrcweir 	}
449cdf0e10cSrcweir }
450cdf0e10cSrcweir // -----------------------------------------------------------------------------
getComposedTableName(const::rtl::OUString &,const::rtl::OUString &,const::rtl::OUString &)451cdf0e10cSrcweir ::rtl::OUString OptimisticSet::getComposedTableName(const ::rtl::OUString& /*_sCatalog*/,
452cdf0e10cSrcweir 											  const ::rtl::OUString& /*_sSchema*/,
453cdf0e10cSrcweir 											  const ::rtl::OUString& /*_sTable*/)
454cdf0e10cSrcweir {
455cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "dbaccess", "Ocke.Janssen@sun.com", "OptimisticSet::getComposedTableName" );
456cdf0e10cSrcweir 	::rtl::OUString aComposedName;
457cdf0e10cSrcweir /*
458cdf0e10cSrcweir 	Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 	if( xMetaData.is() && xMetaData->supportsTableCorrelationNames() )
461cdf0e10cSrcweir 	{
462cdf0e10cSrcweir 		aComposedName = ::dbtools::composeTableName( xMetaData, _sCatalog, _sSchema, _sTable, sal_False, ::dbtools::eInDataManipulation );
463cdf0e10cSrcweir 		// first we have to check if the composed tablename is in the select clause or if an alias is used
464cdf0e10cSrcweir 		Reference<XTablesSupplier> xTabSup(m_xComposer,UNO_QUERY);
465cdf0e10cSrcweir 		Reference<XNameAccess> xSelectTables = xTabSup->getTables();
466cdf0e10cSrcweir 		OSL_ENSURE(xSelectTables.is(),"No Select tables!");
467cdf0e10cSrcweir 		if(xSelectTables.is())
468cdf0e10cSrcweir 		{
469cdf0e10cSrcweir 			if(!xSelectTables->hasByName(aComposedName))
470cdf0e10cSrcweir 			{ // the composed name isn't used in the select clause so we have to find out which name is used instead
471cdf0e10cSrcweir 				::rtl::OUString sCatalog,sSchema,sTable;
472cdf0e10cSrcweir 				::dbtools::qualifiedNameComponents(xMetaData,m_sUpdateTableName,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
473cdf0e10cSrcweir 				aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
474cdf0e10cSrcweir 			}
475cdf0e10cSrcweir 			else
476cdf0e10cSrcweir 				aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable );
477cdf0e10cSrcweir 		}
478cdf0e10cSrcweir 	}
479cdf0e10cSrcweir 	else
480cdf0e10cSrcweir 		aComposedName = ::dbtools::composeTableNameForSelect( m_xConnection, _sCatalog, _sSchema, _sTable );
481cdf0e10cSrcweir */
482cdf0e10cSrcweir 	return aComposedName;
483cdf0e10cSrcweir }
484cdf0e10cSrcweir // -----------------------------------------------------------------------------
fillJoinedColumns_throw(const::std::vector<TNodePair> & i_aJoinColumns)485cdf0e10cSrcweir void OptimisticSet::fillJoinedColumns_throw(const ::std::vector< TNodePair >& i_aJoinColumns)
486cdf0e10cSrcweir {
487cdf0e10cSrcweir     ::std::vector< TNodePair >::const_iterator aIter = i_aJoinColumns.begin();
488cdf0e10cSrcweir     for(;aIter != i_aJoinColumns.end();++aIter)
489cdf0e10cSrcweir     {
490cdf0e10cSrcweir         ::rtl::OUString sColumnName,sTableName;
491cdf0e10cSrcweir         m_aSqlIterator.getColumnRange(aIter->first,sColumnName,sTableName);
492cdf0e10cSrcweir         ::rtl::OUStringBuffer sLeft,sRight;
493cdf0e10cSrcweir         sLeft.append(sTableName);
494cdf0e10cSrcweir         sLeft.appendAscii(".");
495cdf0e10cSrcweir         sLeft.append(sColumnName);
496cdf0e10cSrcweir         m_aSqlIterator.getColumnRange(aIter->second,sColumnName,sTableName);
497cdf0e10cSrcweir         sRight.append(sTableName);
498cdf0e10cSrcweir         sRight.appendAscii(".");
499cdf0e10cSrcweir         sRight.append(sColumnName);
500cdf0e10cSrcweir         fillJoinedColumns_throw(sLeft.makeStringAndClear(),sRight.makeStringAndClear());
501cdf0e10cSrcweir     }
502cdf0e10cSrcweir }
503cdf0e10cSrcweir // -----------------------------------------------------------------------------
fillJoinedColumns_throw(const::rtl::OUString & i_sLeftColumn,const::rtl::OUString & i_sRightColumn)504cdf0e10cSrcweir void OptimisticSet::fillJoinedColumns_throw(const ::rtl::OUString& i_sLeftColumn,const ::rtl::OUString& i_sRightColumn)
505cdf0e10cSrcweir {
506cdf0e10cSrcweir     sal_Int32 nLeft = 0,nRight = 0;
507cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aLeftIter  = m_pKeyColumnNames->find(i_sLeftColumn);
508cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aRightIter = m_pKeyColumnNames->find(i_sRightColumn);
509cdf0e10cSrcweir 
510cdf0e10cSrcweir     bool bLeftKey = aLeftIter != m_pKeyColumnNames->end();
511cdf0e10cSrcweir     if ( bLeftKey )
512cdf0e10cSrcweir     {
513cdf0e10cSrcweir         nLeft = aLeftIter->second.nPosition;
514cdf0e10cSrcweir     }
515cdf0e10cSrcweir     else
516cdf0e10cSrcweir     {
517cdf0e10cSrcweir         aLeftIter = m_pColumnNames->find(i_sLeftColumn);
518cdf0e10cSrcweir         if ( aLeftIter != m_pColumnNames->end() )
519cdf0e10cSrcweir             nLeft = aLeftIter->second.nPosition;
520cdf0e10cSrcweir     }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir     bool bRightKey = aRightIter != m_pKeyColumnNames->end();
523cdf0e10cSrcweir     if ( bRightKey )
524cdf0e10cSrcweir     {
525cdf0e10cSrcweir         nRight = aRightIter->second.nPosition;
526cdf0e10cSrcweir     }
527cdf0e10cSrcweir     else
528cdf0e10cSrcweir     {
529cdf0e10cSrcweir         aRightIter = m_pColumnNames->find(i_sRightColumn);
530cdf0e10cSrcweir         if ( aRightIter != m_pColumnNames->end() )
531cdf0e10cSrcweir             nRight = aRightIter->second.nPosition;
532cdf0e10cSrcweir     }
533cdf0e10cSrcweir 
534cdf0e10cSrcweir     if (bLeftKey)
535cdf0e10cSrcweir         m_aJoinedKeyColumns[nLeft] = nRight;
536cdf0e10cSrcweir     else
537cdf0e10cSrcweir         m_aJoinedColumns[nLeft] = nRight;
538cdf0e10cSrcweir     if (bRightKey)
539cdf0e10cSrcweir         m_aJoinedKeyColumns[nRight] = nLeft;
540cdf0e10cSrcweir     else
541cdf0e10cSrcweir         m_aJoinedColumns[nRight] = nLeft;
542cdf0e10cSrcweir }
543cdf0e10cSrcweir // -----------------------------------------------------------------------------
isResultSetChanged() const544cdf0e10cSrcweir bool OptimisticSet::isResultSetChanged() const
545cdf0e10cSrcweir {
546cdf0e10cSrcweir     bool bOld = m_bResultSetChanged;
547cdf0e10cSrcweir     m_bResultSetChanged = false;
548cdf0e10cSrcweir     return bOld;
549cdf0e10cSrcweir }
550cdf0e10cSrcweir // -----------------------------------------------------------------------------
reset(const Reference<XResultSet> & _xDriverSet)551cdf0e10cSrcweir void OptimisticSet::reset(const Reference< XResultSet>& _xDriverSet)
552cdf0e10cSrcweir {
553cdf0e10cSrcweir     OCacheSet::construct(_xDriverSet,::rtl::OUString());
554cdf0e10cSrcweir     m_bRowCountFinal = sal_False;
555cdf0e10cSrcweir     m_aKeyMap.clear();
556cdf0e10cSrcweir     m_aKeyMap.insert(OKeySetMatrix::value_type(0,OKeySetValue(NULL,::std::pair<sal_Int32,Reference<XRow> >(0,NULL))));
557cdf0e10cSrcweir 	m_aKeyIter = m_aKeyMap.begin();
558cdf0e10cSrcweir }
559cdf0e10cSrcweir // -----------------------------------------------------------------------------
mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector & io_aInsertRow,ORowSetValueVector::Vector & io_aRow,::std::vector<sal_Int32> & o_aChangedColumns)560cdf0e10cSrcweir void OptimisticSet::mergeColumnValues(sal_Int32 i_nColumnIndex,ORowSetValueVector::Vector& io_aInsertRow,ORowSetValueVector::Vector& io_aRow,::std::vector<sal_Int32>& o_aChangedColumns)
561cdf0e10cSrcweir {
562cdf0e10cSrcweir     o_aChangedColumns.push_back(i_nColumnIndex);
563cdf0e10cSrcweir     ::std::map<sal_Int32,sal_Int32>::const_iterator aJoinIter = m_aJoinedColumns.find(i_nColumnIndex);
564cdf0e10cSrcweir     if ( aJoinIter != m_aJoinedColumns.end() )
565cdf0e10cSrcweir     {
566cdf0e10cSrcweir         io_aRow[aJoinIter->second] = io_aRow[i_nColumnIndex];
567cdf0e10cSrcweir         io_aInsertRow[aJoinIter->second] = io_aInsertRow[i_nColumnIndex];
568cdf0e10cSrcweir         io_aRow[aJoinIter->second].setModified();
569cdf0e10cSrcweir         o_aChangedColumns.push_back(aJoinIter->second);
570cdf0e10cSrcweir     }
571cdf0e10cSrcweir }
572cdf0e10cSrcweir namespace
573cdf0e10cSrcweir {
574cdf0e10cSrcweir     struct PositionFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool>
575cdf0e10cSrcweir     {
576cdf0e10cSrcweir 	    sal_Int32 m_nPos;
PositionFunctor__anone097dfb10211::PositionFunctor577cdf0e10cSrcweir 	    PositionFunctor(sal_Int32 i_nPos)
578cdf0e10cSrcweir 		    : m_nPos(i_nPos)
579cdf0e10cSrcweir 	    {
580cdf0e10cSrcweir 	    }
581cdf0e10cSrcweir 
operator ()__anone097dfb10211::PositionFunctor582cdf0e10cSrcweir 	    inline bool operator()(const SelectColumnsMetaData::value_type& _aType)
583cdf0e10cSrcweir 	    {
584cdf0e10cSrcweir             return m_nPos == _aType.second.nPosition;
585cdf0e10cSrcweir 	    }
586cdf0e10cSrcweir     };
587cdf0e10cSrcweir     struct TableNameFunctor : ::std::unary_function<SelectColumnsMetaData::value_type,bool>
588cdf0e10cSrcweir     {
589cdf0e10cSrcweir 	    ::rtl::OUString m_sTableName;
TableNameFunctor__anone097dfb10211::TableNameFunctor590cdf0e10cSrcweir 	    TableNameFunctor(const ::rtl::OUString& i_sTableName)
591cdf0e10cSrcweir 		    : m_sTableName(i_sTableName)
592cdf0e10cSrcweir 	    {
593cdf0e10cSrcweir 	    }
594cdf0e10cSrcweir 
operator ()__anone097dfb10211::TableNameFunctor595cdf0e10cSrcweir 	    inline bool operator()(const SelectColumnsMetaData::value_type& _aType)
596cdf0e10cSrcweir 	    {
597cdf0e10cSrcweir             return m_sTableName == _aType.second.sTableName;
598cdf0e10cSrcweir 	    }
599cdf0e10cSrcweir     };
600cdf0e10cSrcweir }
601cdf0e10cSrcweir // -----------------------------------------------------------------------------
updateColumnValues(const ORowSetValueVector::Vector & io_aCachedRow,ORowSetValueVector::Vector & io_aRow,const::std::vector<sal_Int32> & i_aChangedColumns)602cdf0e10cSrcweir bool OptimisticSet::updateColumnValues(const ORowSetValueVector::Vector& io_aCachedRow,ORowSetValueVector::Vector& io_aRow,const ::std::vector<sal_Int32>& i_aChangedColumns)
603cdf0e10cSrcweir {
604cdf0e10cSrcweir     bool bRet = false;
605cdf0e10cSrcweir     ::std::vector<sal_Int32>::const_iterator aColIdxIter = i_aChangedColumns.begin();
606cdf0e10cSrcweir 	for(;aColIdxIter != i_aChangedColumns.end();++aColIdxIter)
607cdf0e10cSrcweir 	{
608cdf0e10cSrcweir         SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(*aColIdxIter));
609cdf0e10cSrcweir         if ( aFind != m_pKeyColumnNames->end() )
610cdf0e10cSrcweir         {
611cdf0e10cSrcweir             const ::rtl::OUString sTableName = aFind->second.sTableName;
612cdf0e10cSrcweir             aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName));
613cdf0e10cSrcweir             while( aFind != m_pKeyColumnNames->end() )
614cdf0e10cSrcweir             {
615cdf0e10cSrcweir                 io_aRow[aFind->second.nPosition].setSigned(io_aCachedRow[aFind->second.nPosition].isSigned());
616cdf0e10cSrcweir                 if ( io_aCachedRow[aFind->second.nPosition] != io_aRow[aFind->second.nPosition] )
617cdf0e10cSrcweir                     break;
618cdf0e10cSrcweir                 ++aFind;
619cdf0e10cSrcweir             }
620cdf0e10cSrcweir             if ( aFind == m_pKeyColumnNames->end() )
621cdf0e10cSrcweir             {
622cdf0e10cSrcweir                 bRet = true;
623cdf0e10cSrcweir                 SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
624cdf0e10cSrcweir                 SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
625cdf0e10cSrcweir 	            for ( ;aIter != aEnd;++aIter )
626cdf0e10cSrcweir 	            {
627cdf0e10cSrcweir                     if ( aIter->second.sTableName == sTableName )
628cdf0e10cSrcweir                     {
629cdf0e10cSrcweir                         io_aRow[aIter->second.nPosition] = io_aCachedRow[aIter->second.nPosition];
630cdf0e10cSrcweir                         io_aRow[aIter->second.nPosition].setModified();
631cdf0e10cSrcweir                     }
632cdf0e10cSrcweir                 }
633cdf0e10cSrcweir             }
634cdf0e10cSrcweir         }
635cdf0e10cSrcweir     }
636cdf0e10cSrcweir     return bRet;
637cdf0e10cSrcweir }
638cdf0e10cSrcweir // -----------------------------------------------------------------------------
columnValuesUpdated(ORowSetValueVector::Vector & o_aCachedRow,const ORowSetValueVector::Vector & i_aRow)639cdf0e10cSrcweir bool OptimisticSet::columnValuesUpdated(ORowSetValueVector::Vector& o_aCachedRow,const ORowSetValueVector::Vector& i_aRow)
640cdf0e10cSrcweir {
641cdf0e10cSrcweir     bool bRet = false;
642cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aIter = m_pColumnNames->begin();
643cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aEnd = m_pColumnNames->end();
644cdf0e10cSrcweir 	for(;aIter != aEnd;++aIter)
645cdf0e10cSrcweir 	{
646cdf0e10cSrcweir         SelectColumnsMetaData::const_iterator aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),PositionFunctor(aIter->second.nPosition));
647cdf0e10cSrcweir         if ( aFind != m_pKeyColumnNames->end() )
648cdf0e10cSrcweir         {
649cdf0e10cSrcweir             const ::rtl::OUString sTableName = aFind->second.sTableName;
650cdf0e10cSrcweir             aFind = ::std::find_if(m_pKeyColumnNames->begin(),m_pKeyColumnNames->end(),TableNameFunctor(sTableName));
651cdf0e10cSrcweir             while( aFind != m_pKeyColumnNames->end() )
652cdf0e10cSrcweir             {
653cdf0e10cSrcweir                 o_aCachedRow[aFind->second.nPosition].setSigned(i_aRow[aFind->second.nPosition].isSigned());
654cdf0e10cSrcweir                 if ( o_aCachedRow[aFind->second.nPosition] != i_aRow[aFind->second.nPosition] )
655cdf0e10cSrcweir                     break;
656cdf0e10cSrcweir                 ++aFind;
657cdf0e10cSrcweir             }
658cdf0e10cSrcweir             if ( aFind == m_pKeyColumnNames->end() )
659cdf0e10cSrcweir             {
660cdf0e10cSrcweir                 bRet = true;
661cdf0e10cSrcweir                 SelectColumnsMetaData::const_iterator aIter2 = m_pColumnNames->begin();
662cdf0e10cSrcweir                 SelectColumnsMetaData::const_iterator aEnd2 = m_pColumnNames->end();
663cdf0e10cSrcweir 	            for ( ;aIter2 != aEnd2;++aIter2 )
664cdf0e10cSrcweir 	            {
665cdf0e10cSrcweir                     if ( aIter2->second.sTableName == sTableName )
666cdf0e10cSrcweir                     {
667cdf0e10cSrcweir                         o_aCachedRow[aIter2->second.nPosition] = i_aRow[aIter2->second.nPosition];
668cdf0e10cSrcweir                         o_aCachedRow[aIter2->second.nPosition].setModified();
669cdf0e10cSrcweir                     }
670cdf0e10cSrcweir                 }
671cdf0e10cSrcweir                 fillMissingValues(o_aCachedRow);
672cdf0e10cSrcweir             }
673cdf0e10cSrcweir         }
674cdf0e10cSrcweir     }
675cdf0e10cSrcweir     return bRet;
676cdf0e10cSrcweir }
677cdf0e10cSrcweir // -----------------------------------------------------------------------------
fillMissingValues(ORowSetValueVector::Vector & io_aRow) const678cdf0e10cSrcweir void OptimisticSet::fillMissingValues(ORowSetValueVector::Vector& io_aRow) const
679cdf0e10cSrcweir {
680cdf0e10cSrcweir     TSQLStatements aSql;
681cdf0e10cSrcweir     TSQLStatements aKeyConditions;
682cdf0e10cSrcweir     ::std::map< ::rtl::OUString,bool > aResultSetChanged;
683cdf0e10cSrcweir     ::rtl::OUString aQuote	= getIdentifierQuoteString();
684cdf0e10cSrcweir     static ::rtl::OUString aAnd		= ::rtl::OUString::createFromAscii(" AND ");
685cdf0e10cSrcweir     ::rtl::OUString sIsNull(RTL_CONSTASCII_USTRINGPARAM(" IS NULL"));
686cdf0e10cSrcweir     ::rtl::OUString sParam(RTL_CONSTASCII_USTRINGPARAM(" = ?"));
687cdf0e10cSrcweir     // here we build the condition part for the update statement
688cdf0e10cSrcweir 	SelectColumnsMetaData::const_iterator aColIter = m_pColumnNames->begin();
689cdf0e10cSrcweir     SelectColumnsMetaData::const_iterator aColEnd = m_pColumnNames->end();
690cdf0e10cSrcweir 	for(;aColIter != aColEnd;++aColIter)
691cdf0e10cSrcweir 	{
692cdf0e10cSrcweir         const ::rtl::OUString sQuotedColumnName = ::dbtools::quoteName( aQuote,aColIter->second.sRealName);
693cdf0e10cSrcweir         if ( m_aJoinedKeyColumns.find(aColIter->second.nPosition) != m_aJoinedKeyColumns.end() )
694cdf0e10cSrcweir 	    {
695cdf0e10cSrcweir             lcl_fillKeyCondition(aColIter->second.sTableName,sQuotedColumnName,io_aRow[aColIter->second.nPosition],aKeyConditions);
696cdf0e10cSrcweir         }
697cdf0e10cSrcweir         ::rtl::OUStringBuffer& rPart = aSql[aColIter->second.sTableName];
698cdf0e10cSrcweir         if ( rPart.getLength() )
699cdf0e10cSrcweir             rPart.appendAscii(", ");
700cdf0e10cSrcweir 		rPart.append(sQuotedColumnName);
701cdf0e10cSrcweir     }
702cdf0e10cSrcweir     Reference<XDatabaseMetaData> xMetaData = m_xConnection->getMetaData();
703cdf0e10cSrcweir     TSQLStatements::iterator aSqlIter = aSql.begin();
704cdf0e10cSrcweir     TSQLStatements::iterator aSqlEnd  = aSql.end();
705cdf0e10cSrcweir     for(;aSqlIter != aSqlEnd ; ++aSqlIter)
706cdf0e10cSrcweir     {
707cdf0e10cSrcweir         if ( aSqlIter->second.getLength() )
708cdf0e10cSrcweir         {
709cdf0e10cSrcweir             ::rtl::OUStringBuffer& rCondition = aKeyConditions[aSqlIter->first];
710cdf0e10cSrcweir             if ( rCondition.getLength() )
711cdf0e10cSrcweir             {
712cdf0e10cSrcweir                 ::rtl::OUString sCatalog,sSchema,sTable;
713cdf0e10cSrcweir 			    ::dbtools::qualifiedNameComponents(xMetaData,aSqlIter->first,sCatalog,sSchema,sTable,::dbtools::eInDataManipulation);
714cdf0e10cSrcweir                 ::rtl::OUString sComposedTableName = ::dbtools::composeTableNameForSelect( m_xConnection, sCatalog, sSchema, sTable );
715cdf0e10cSrcweir                 ::rtl::OUStringBuffer sQuery;
716cdf0e10cSrcweir                 sQuery.appendAscii("SELECT ");
717cdf0e10cSrcweir                 sQuery.append(aSqlIter->second);
718cdf0e10cSrcweir                 sQuery.appendAscii(" FROM ");
719cdf0e10cSrcweir                 sQuery.append(sComposedTableName);
720cdf0e10cSrcweir                 sQuery.appendAscii(" WHERE ");
721cdf0e10cSrcweir                 sQuery.append(rCondition.makeStringAndClear());
722cdf0e10cSrcweir 
723cdf0e10cSrcweir                 try
724cdf0e10cSrcweir                 {
725cdf0e10cSrcweir                     Reference< XPreparedStatement > xPrep(m_xConnection->prepareStatement(sQuery.makeStringAndClear()));
726cdf0e10cSrcweir                     Reference< XParameters > xParameter(xPrep,UNO_QUERY);
727cdf0e10cSrcweir                     // and then the values of the where condition
728cdf0e10cSrcweir                     SelectColumnsMetaData::iterator aKeyIter = m_pKeyColumnNames->begin();
729cdf0e10cSrcweir                     SelectColumnsMetaData::iterator aKeyEnd = m_pKeyColumnNames->end();
730cdf0e10cSrcweir                     sal_Int32 i = 1;
731cdf0e10cSrcweir                     for(;aKeyIter != aKeyEnd;++aKeyIter)
732cdf0e10cSrcweir                     {
733cdf0e10cSrcweir                         if ( aKeyIter->second.sTableName == aSqlIter->first )
734cdf0e10cSrcweir                         {
735cdf0e10cSrcweir 	                        setParameter(i++,xParameter,io_aRow[aKeyIter->second.nPosition],aKeyIter->second.nType,aKeyIter->second.nScale);
736cdf0e10cSrcweir                         }
737cdf0e10cSrcweir                     }
738cdf0e10cSrcweir                     Reference<XResultSet> xRes = xPrep->executeQuery();
739cdf0e10cSrcweir 			        Reference<XRow> xRow(xRes,UNO_QUERY);
740cdf0e10cSrcweir 			        if ( xRow.is() && xRes->next() )
741cdf0e10cSrcweir 			        {
742cdf0e10cSrcweir                         i = 1;
743cdf0e10cSrcweir                         aColIter = m_pColumnNames->begin();
744cdf0e10cSrcweir 	                    for(;aColIter != aColEnd;++aColIter)
745cdf0e10cSrcweir 	                    {
746cdf0e10cSrcweir                             if ( aColIter->second.sTableName == aSqlIter->first )
747cdf0e10cSrcweir                             {
748cdf0e10cSrcweir                                 io_aRow[aColIter->second.nPosition].fill(i++,aColIter->second.nType,aColIter->second.bNullable,xRow);
749cdf0e10cSrcweir                                 io_aRow[aColIter->second.nPosition].setModified();
750cdf0e10cSrcweir                             }
751cdf0e10cSrcweir                         }
752cdf0e10cSrcweir                     }
753cdf0e10cSrcweir                 }
754cdf0e10cSrcweir                 catch(const SQLException&)
755cdf0e10cSrcweir                 {
756cdf0e10cSrcweir                 }
757cdf0e10cSrcweir             }
758cdf0e10cSrcweir         }
759cdf0e10cSrcweir     }
760cdf0e10cSrcweir }
761cdf0e10cSrcweir // -----------------------------------------------------------------------------
762cdf0e10cSrcweir 
763