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