1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or 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 _DBAUI_INDEXCOLLECTION_HXX_ 32 #include "indexcollection.hxx" 33 #endif 34 #ifndef TOOLS_DIAGNOSE_EX_H 35 #include <tools/diagnose_ex.h> 36 #endif 37 #ifndef _COM_SUN_STAR_SDBCX_XAPPEND_HPP_ 38 #include <com/sun/star/sdbcx/XAppend.hpp> 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_SDBCX_XCOLUMNSSUPPLIER_HPP_ 44 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 45 #endif 46 #ifndef _COM_SUN_STAR_SDBCX_XDATADESCRIPTORFACTORY_HPP_ 47 #include <com/sun/star/sdbcx/XDataDescriptorFactory.hpp> 48 #endif 49 #ifndef _COMPHELPER_EXTRACT_HXX_ 50 #include <comphelper/extract.hxx> 51 #endif 52 #ifndef _COM_SUN_STAR_SDBCX_XDROP_HPP_ 53 #include <com/sun/star/sdbcx/XDrop.hpp> 54 #endif 55 #ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_ 56 #include <com/sun/star/container/XNameContainer.hpp> 57 #endif 58 59 //...................................................................... 60 namespace dbaui 61 { 62 //...................................................................... 63 64 using namespace ::com::sun::star::uno; 65 using namespace ::com::sun::star::container; 66 using namespace ::com::sun::star::beans; 67 using namespace ::com::sun::star::sdbcx; 68 using namespace ::com::sun::star::sdbc; 69 70 //================================================================== 71 //= OIndexCollection 72 //================================================================== 73 //------------------------------------------------------------------ 74 OIndexCollection::OIndexCollection() 75 { 76 } 77 78 //------------------------------------------------------------------ 79 OIndexCollection::OIndexCollection(const OIndexCollection& _rSource) 80 { 81 *this = _rSource; 82 } 83 84 //------------------------------------------------------------------ 85 // OIndexCollection::OIndexCollection(const Reference< XNameAccess >& _rxIndexes) 86 // { 87 // implConstructFrom(_rxIndexes); 88 // } 89 90 //------------------------------------------------------------------ 91 const OIndexCollection& OIndexCollection::operator=(const OIndexCollection& _rSource) 92 { 93 detach(); 94 m_xIndexes = _rSource.m_xIndexes; 95 m_aIndexes = _rSource.m_aIndexes; 96 return *this; 97 } 98 99 //------------------------------------------------------------------ 100 void OIndexCollection::attach(const Reference< XNameAccess >& _rxIndexes) 101 { 102 implConstructFrom(_rxIndexes); 103 } 104 105 //------------------------------------------------------------------ 106 void OIndexCollection::detach() 107 { 108 m_xIndexes.clear(); 109 m_aIndexes.clear(); 110 } 111 112 //------------------------------------------------------------------ 113 Indexes::const_iterator OIndexCollection::find(const String& _rName) const 114 { 115 ::rtl::OUString sNameCompare(_rName); 116 117 // loop'n'compare 118 Indexes::const_iterator aSearch = m_aIndexes.begin(); 119 Indexes::const_iterator aEnd = m_aIndexes.end(); 120 for (; aSearch != aEnd; ++aSearch) 121 if (aSearch->sName == sNameCompare) 122 break; 123 124 return aSearch; 125 } 126 127 //------------------------------------------------------------------ 128 Indexes::iterator OIndexCollection::find(const String& _rName) 129 { 130 ::rtl::OUString sNameCompare(_rName); 131 132 // loop'n'compare 133 Indexes::iterator aSearch = m_aIndexes.begin(); 134 Indexes::iterator aEnd = m_aIndexes.end(); 135 for (; aSearch != aEnd; ++aSearch) 136 if (aSearch->sName == sNameCompare) 137 break; 138 139 return aSearch; 140 } 141 142 //------------------------------------------------------------------ 143 Indexes::const_iterator OIndexCollection::findOriginal(const String& _rName) const 144 { 145 ::rtl::OUString sNameCompare(_rName); 146 147 // loop'n'compare 148 Indexes::const_iterator aSearch = m_aIndexes.begin(); 149 Indexes::const_iterator aEnd = m_aIndexes.end(); 150 for (; aSearch != aEnd; ++aSearch) 151 if (aSearch->getOriginalName() == sNameCompare) 152 break; 153 154 return aSearch; 155 } 156 157 //------------------------------------------------------------------ 158 Indexes::iterator OIndexCollection::findOriginal(const String& _rName) 159 { 160 ::rtl::OUString sNameCompare(_rName); 161 162 // loop'n'compare 163 Indexes::iterator aSearch = m_aIndexes.begin(); 164 Indexes::iterator aEnd = m_aIndexes.end(); 165 for (; aSearch != aEnd; ++aSearch) 166 if (aSearch->getOriginalName() == sNameCompare) 167 break; 168 169 return aSearch; 170 } 171 172 //------------------------------------------------------------------ 173 void OIndexCollection::commitNewIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) 174 { 175 OSL_ENSURE(_rPos->isNew(), "OIndexCollection::commitNewIndex: index must be new!"); 176 177 try 178 { 179 Reference< XDataDescriptorFactory > xIndexFactory(m_xIndexes, UNO_QUERY); 180 Reference< XAppend > xAppendIndex(xIndexFactory, UNO_QUERY); 181 if (!xAppendIndex.is()) 182 { 183 OSL_ENSURE(sal_False, "OIndexCollection::commitNewIndex: missing an interface of the index container!"); 184 return; 185 } 186 187 Reference< XPropertySet > xIndexDescriptor = xIndexFactory->createDataDescriptor(); 188 Reference< XColumnsSupplier > xColsSupp(xIndexDescriptor, UNO_QUERY); 189 Reference< XNameAccess > xCols; 190 if (xColsSupp.is()) 191 xCols = xColsSupp->getColumns(); 192 193 Reference< XDataDescriptorFactory > xColumnFactory(xCols, UNO_QUERY); 194 Reference< XAppend > xAppendCols(xColumnFactory, UNO_QUERY); 195 if (!xAppendCols.is()) 196 { 197 OSL_ENSURE(sal_False, "OIndexCollection::commitNewIndex: invalid index descriptor returned!"); 198 return; 199 } 200 201 // set the properties 202 static const ::rtl::OUString s_sUniquePropertyName = ::rtl::OUString::createFromAscii("IsUnique"); 203 static const ::rtl::OUString s_sSortPropertyName = ::rtl::OUString::createFromAscii("IsAscending"); 204 static const ::rtl::OUString s_sNamePropertyName = ::rtl::OUString::createFromAscii("Name"); 205 // the index' own props 206 xIndexDescriptor->setPropertyValue(s_sUniquePropertyName, ::cppu::bool2any(_rPos->bUnique)); 207 xIndexDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(_rPos->sName)); 208 209 // the fields 210 for ( ConstIndexFieldsIterator aFieldLoop = _rPos->aFields.begin(); 211 aFieldLoop != _rPos->aFields.end(); 212 ++aFieldLoop 213 ) 214 { 215 OSL_ENSURE(!xCols->hasByName(aFieldLoop->sFieldName), "OIndexCollection::commitNewIndex: double column name (need to prevent this outside)!"); 216 217 Reference< XPropertySet > xColDescriptor = xColumnFactory->createDataDescriptor(); 218 OSL_ENSURE(xColDescriptor.is(), "OIndexCollection::commitNewIndex: invalid column descriptor!"); 219 if (xColDescriptor.is()) 220 { 221 xColDescriptor->setPropertyValue(s_sSortPropertyName, ::cppu::bool2any(aFieldLoop->bSortAscending)); 222 xColDescriptor->setPropertyValue(s_sNamePropertyName, makeAny(::rtl::OUString(aFieldLoop->sFieldName))); 223 xAppendCols->appendByDescriptor(xColDescriptor); 224 } 225 } 226 227 xAppendIndex->appendByDescriptor(xIndexDescriptor); 228 229 _rPos->flagAsCommitted(GrantIndexAccess()); 230 _rPos->clearModified(); 231 } 232 catch(SQLException&) 233 { // allowed to pass 234 throw; 235 } 236 catch( const Exception& ) 237 { 238 DBG_UNHANDLED_EXCEPTION(); 239 } 240 } 241 242 //------------------------------------------------------------------ 243 sal_Bool OIndexCollection::dropNoRemove(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) 244 { 245 try 246 { 247 OSL_ENSURE(m_xIndexes->hasByName(_rPos->getOriginalName()), "OIndexCollection::drop: invalid name!"); 248 249 Reference< XDrop > xDropIndex(m_xIndexes, UNO_QUERY); 250 if (!xDropIndex.is()) 251 { 252 OSL_ENSURE(sal_False, "OIndexCollection::drop: no XDrop interface!"); 253 return sal_False; 254 } 255 256 xDropIndex->dropByName(_rPos->getOriginalName()); 257 } 258 catch(SQLException&) 259 { // allowed to pass 260 throw; 261 } 262 catch( const Exception& ) 263 { 264 DBG_UNHANDLED_EXCEPTION(); 265 return sal_False; 266 } 267 268 // adjust the OIndex structure 269 Indexes::iterator aDropped = findOriginal(_rPos->getOriginalName()); 270 OSL_ENSURE(aDropped != m_aIndexes.end(), "OIndexCollection::drop: invalid original name, but successfull commit?!"); 271 aDropped->flagAsNew(GrantIndexAccess()); 272 273 return sal_True; 274 } 275 276 //------------------------------------------------------------------ 277 sal_Bool OIndexCollection::drop(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) 278 { 279 OSL_ENSURE((_rPos >= m_aIndexes.begin()) && (_rPos < m_aIndexes.end()), 280 "OIndexCollection::drop: invalid position (fasten your seatbelt .... this will crash)!"); 281 282 if (!_rPos->isNew()) 283 if (!dropNoRemove(_rPos)) 284 return sal_False; 285 286 // adjust the index array 287 m_aIndexes.erase(_rPos); 288 return sal_True; 289 } 290 291 //------------------------------------------------------------------ 292 void OIndexCollection::implFillIndexInfo(OIndex& _rIndex) SAL_THROW((Exception)) 293 { 294 // get the UNO descriptor for the index 295 Reference< XPropertySet > xIndex; 296 m_xIndexes->getByName(_rIndex.getOriginalName()) >>= xIndex; 297 if (!xIndex.is()) 298 { 299 OSL_ENSURE(sal_False, "OIndexCollection::implFillIndexInfo: got an invalid index object!"); 300 } 301 else 302 implFillIndexInfo(_rIndex, xIndex); 303 } 304 305 //------------------------------------------------------------------ 306 void OIndexCollection::implFillIndexInfo(OIndex& _rIndex, Reference< XPropertySet > _rxDescriptor) SAL_THROW((Exception)) 307 { 308 static const ::rtl::OUString s_sPrimaryIndexPropertyName = ::rtl::OUString::createFromAscii("IsPrimaryKeyIndex"); 309 static const ::rtl::OUString s_sUniquePropertyName = ::rtl::OUString::createFromAscii("IsUnique"); 310 static const ::rtl::OUString s_sSortPropertyName = ::rtl::OUString::createFromAscii("IsAscending"); 311 static const ::rtl::OUString s_sCatalogPropertyName = ::rtl::OUString::createFromAscii("Catalog"); 312 313 _rIndex.bPrimaryKey = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sPrimaryIndexPropertyName)); 314 _rIndex.bUnique = ::cppu::any2bool(_rxDescriptor->getPropertyValue(s_sUniquePropertyName)); 315 _rxDescriptor->getPropertyValue(s_sCatalogPropertyName) >>= _rIndex.sDescription; 316 317 // the columns 318 Reference< XColumnsSupplier > xSuppCols(_rxDescriptor, UNO_QUERY); 319 Reference< XNameAccess > xCols; 320 if (xSuppCols.is()) 321 xCols = xSuppCols->getColumns(); 322 OSL_ENSURE(xCols.is(), "OIndexCollection::implFillIndexInfo: the index does not have columns!"); 323 if (xCols.is()) 324 { 325 Sequence< ::rtl::OUString > aFieldNames = xCols->getElementNames(); 326 _rIndex.aFields.resize(aFieldNames.getLength()); 327 328 const ::rtl::OUString* pFieldNames = aFieldNames.getConstArray(); 329 const ::rtl::OUString* pFieldNamesEnd = pFieldNames + aFieldNames.getLength(); 330 IndexFields::iterator aCopyTo = _rIndex.aFields.begin(); 331 332 Reference< XPropertySet > xIndexColumn; 333 for (;pFieldNames < pFieldNamesEnd; ++pFieldNames, ++aCopyTo) 334 { 335 // extract the column 336 xIndexColumn.clear(); 337 xCols->getByName(*pFieldNames) >>= xIndexColumn; 338 if (!xIndexColumn.is()) 339 { 340 OSL_ENSURE(sal_False, "OIndexCollection::implFillIndexInfo: invalid index column!"); 341 --aCopyTo; 342 continue; 343 } 344 345 // get the relevant properties 346 aCopyTo->sFieldName = *pFieldNames; 347 aCopyTo->bSortAscending = ::cppu::any2bool(xIndexColumn->getPropertyValue(s_sSortPropertyName)); 348 } 349 350 _rIndex.aFields.resize(aCopyTo - _rIndex.aFields.begin()); 351 // (just in case some fields were invalid ...) 352 } 353 } 354 355 //------------------------------------------------------------------ 356 void OIndexCollection::resetIndex(const Indexes::iterator& _rPos) SAL_THROW((SQLException)) 357 { 358 OSL_ENSURE(_rPos >= m_aIndexes.begin() && _rPos < m_aIndexes.end(), 359 "OIndexCollection::resetIndex: invalid position!"); 360 361 try 362 { 363 _rPos->sName = _rPos->getOriginalName(); 364 implFillIndexInfo(*_rPos); 365 366 _rPos->clearModified(); 367 _rPos->flagAsCommitted(GrantIndexAccess()); 368 } 369 catch(SQLException&) 370 { // allowed to pass 371 throw; 372 } 373 catch( const Exception& ) 374 { 375 DBG_UNHANDLED_EXCEPTION(); 376 } 377 } 378 379 //------------------------------------------------------------------ 380 Indexes::iterator OIndexCollection::insert(const String& _rName) 381 { 382 OSL_ENSURE(end() == find(_rName), "OIndexCollection::insert: invalid new name!"); 383 String tmpName; 384 OIndex aNewIndex(tmpName); // the empty string indicates the index is a new one 385 aNewIndex.sName = _rName; 386 m_aIndexes.push_back(aNewIndex); 387 return m_aIndexes.end() - 1; // the last element is the new one ... 388 } 389 390 //------------------------------------------------------------------ 391 void OIndexCollection::implConstructFrom(const Reference< XNameAccess >& _rxIndexes) 392 { 393 detach(); 394 395 m_xIndexes = _rxIndexes; 396 if (m_xIndexes.is()) 397 { 398 // loop through all the indexes 399 Sequence< ::rtl::OUString > aNames = m_xIndexes->getElementNames(); 400 const ::rtl::OUString* pNames = aNames.getConstArray(); 401 const ::rtl::OUString* pEnd = pNames + aNames.getLength(); 402 for (; pNames < pEnd; ++pNames) 403 { 404 // extract the index object 405 Reference< XPropertySet > xIndex; 406 m_xIndexes->getByName(*pNames) >>= xIndex; 407 if (!xIndex.is()) 408 { 409 OSL_ENSURE(sal_False, "OIndexCollection::implConstructFrom: got an invalid index object ... ignoring!"); 410 continue; 411 } 412 413 // fill the OIndex structure 414 OIndex aCurrentIndex(*pNames); 415 implFillIndexInfo(aCurrentIndex); 416 m_aIndexes.push_back(aCurrentIndex); 417 } 418 } 419 } 420 421 //...................................................................... 422 } // namespace dbaui 423 //...................................................................... 424 425