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