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