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