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_connectivity.hxx" 30 #include "dbase/DIndex.hxx" 31 #include "dbase/DIndexColumns.hxx" 32 #include <com/sun/star/lang/DisposedException.hpp> 33 #include "connectivity/sdbcx/VColumn.hxx" 34 #include <comphelper/sequence.hxx> 35 #include "dbase/DTable.hxx" 36 #include "dbase/DIndexIter.hxx" 37 #include <tools/config.hxx> 38 #include "connectivity/CommonTools.hxx" 39 #include <com/sun/star/sdbc/XResultSetMetaData.hpp> 40 #include <com/sun/star/sdbc/XResultSet.hpp> 41 #include <com/sun/star/sdbcx/XRowLocate.hpp> 42 #include <com/sun/star/sdbc/XRow.hpp> 43 #include <comphelper/extract.hxx> 44 #include <unotools/localfilehelper.hxx> 45 #include <unotools/ucbhelper.hxx> 46 #include <comphelper/types.hxx> 47 #include <connectivity/dbexception.hxx> 48 #include "dbase/DResultSet.hxx" 49 #include "diagnose_ex.h" 50 #include <comphelper/types.hxx> 51 #include "resource/dbase_res.hrc" 52 #include <unotools/sharedunocomponent.hxx> 53 54 using namespace ::comphelper; 55 // ------------------------------------------------------------------------- 56 using namespace connectivity; 57 using namespace utl; 58 using namespace ::cppu; 59 using namespace connectivity::file; 60 using namespace connectivity::sdbcx; 61 using namespace connectivity::dbase; 62 using namespace com::sun::star::sdbc; 63 using namespace com::sun::star::sdbcx; 64 using namespace com::sun::star::uno; 65 using namespace com::sun::star::beans; 66 using namespace com::sun::star::lang; 67 68 IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index"); 69 // ------------------------------------------------------------------------- 70 ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable) : OIndex(sal_True/*_pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()*/) 71 ,m_pFileStream(NULL) 72 ,m_nCurNode(NODE_NOTFOUND) 73 ,m_pTable(_pTable) 74 { 75 m_aHeader.db_pagecount = m_aHeader.db_rootpage = m_aHeader.db_keytype = m_aHeader.db_maxkeys = m_aHeader.db_keylen = 0; 76 m_aHeader.db_name[0] = '\0'; 77 construct(); 78 } 79 // ------------------------------------------------------------------------- 80 ODbaseIndex::ODbaseIndex( ODbaseTable* _pTable, 81 const NDXHeader& _rHeader, 82 const ::rtl::OUString& _rName) 83 :OIndex(_rName,::rtl::OUString(),_rHeader.db_unique,sal_False,sal_False,sal_True) // _pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers() 84 ,m_pFileStream(NULL) 85 ,m_aHeader(_rHeader) 86 ,m_nCurNode(NODE_NOTFOUND) 87 ,m_pTable(_pTable) 88 { 89 construct(); 90 } 91 // ----------------------------------------------------------------------------- 92 ODbaseIndex::~ODbaseIndex() 93 { 94 closeImpl(); 95 } 96 // ------------------------------------------------------------------------- 97 void ODbaseIndex::refreshColumns() 98 { 99 ::osl::MutexGuard aGuard( m_aMutex ); 100 101 TStringVector aVector; 102 if(!isNew()) 103 { 104 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 105 OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!"); 106 aVector.push_back(::rtl::OUString::createFromAscii(m_aHeader.db_name)); 107 } 108 109 if(m_pColumns) 110 m_pColumns->reFill(aVector); 111 else 112 m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector); 113 } 114 //-------------------------------------------------------------------------- 115 Sequence< sal_Int8 > ODbaseIndex::getUnoTunnelImplementationId() 116 { 117 static ::cppu::OImplementationId * pId = 0; 118 if (! pId) 119 { 120 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); 121 if (! pId) 122 { 123 static ::cppu::OImplementationId aId; 124 pId = &aId; 125 } 126 } 127 return pId->getImplementationId(); 128 } 129 130 // XUnoTunnel 131 //------------------------------------------------------------------ 132 sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException) 133 { 134 return (rId.getLength() == 16 && 0 == rtl_compareMemory(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) ) 135 ? reinterpret_cast< sal_Int64 >( this ) 136 : ODbaseIndex_BASE::getSomething(rId); 137 } 138 //------------------------------------------------------------------ 139 ONDXPagePtr ODbaseIndex::getRoot() 140 { 141 openIndexFile(); 142 if (!m_aRoot.Is()) 143 { 144 m_nRootPage = m_aHeader.db_rootpage; 145 m_nPageCount = m_aHeader.db_pagecount; 146 m_aRoot = CreatePage(m_nRootPage,NULL,sal_True); 147 } 148 return m_aRoot; 149 } 150 //------------------------------------------------------------------ 151 sal_Bool ODbaseIndex::openIndexFile() 152 { 153 if(!m_pFileStream) 154 { 155 ::rtl::OUString sFile = getCompletePath(); 156 if(UCBContentHelper::Exists(sFile)) 157 { 158 m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | STREAM_NOCREATE | STREAM_SHARE_DENYWRITE); 159 if (!m_pFileStream) 160 m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READ | STREAM_NOCREATE | STREAM_SHARE_DENYNONE); 161 if(m_pFileStream) 162 { 163 m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); 164 m_pFileStream->SetBufferSize(PAGE_SIZE); 165 (*m_pFileStream) >> *this; 166 } 167 } 168 if(!m_pFileStream) 169 { 170 const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 171 STR_COULD_NOT_LOAD_FILE, 172 "$filename$", sFile 173 ) ); 174 ::dbtools::throwGenericSQLException( sError, *this ); 175 } 176 } 177 178 return m_pFileStream != NULL; 179 } 180 //------------------------------------------------------------------ 181 OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp, 182 const OOperand* pOperand) 183 { 184 openIndexFile(); 185 return new OIndexIterator(this, pOp, pOperand); 186 } 187 //------------------------------------------------------------------ 188 sal_Bool ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue) 189 { 190 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 191 // Sucht ein bestimmten Wert im Index 192 // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja 193 try 194 { 195 if (m_aHeader.db_keytype == 0) 196 { 197 *rKey = ONDXKey(rValue.getString(), nRec ); 198 } 199 else 200 { 201 if (rValue.isNull()) 202 *rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec ); 203 else 204 *rKey = ONDXKey(rValue.getDouble(), nRec ); 205 } 206 } 207 catch (Exception&) 208 { 209 OSL_ASSERT(0); 210 return sal_False; 211 } 212 return sal_True; 213 } 214 215 //------------------------------------------------------------------ 216 sal_Bool ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue) 217 { 218 openIndexFile(); 219 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 220 // Sucht ein bestimmten Wert im Index 221 // Wenn der Index Unique ist, interssiert der Key nicht, sonst ja 222 ONDXKey aKey; 223 return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey); 224 } 225 226 //------------------------------------------------------------------ 227 sal_Bool ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue) 228 { 229 openIndexFile(); 230 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 231 ONDXKey aKey; 232 233 // Existiert der Wert bereits 234 // Find immer verwenden um das aktuelle Blatt zu bestimmen 235 if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique())) 236 return sal_False; 237 238 ONDXNode aNewNode(aKey); 239 240 // einfuegen in das aktuelle Blatt 241 if (!m_aCurLeaf.Is()) 242 return sal_False; 243 244 sal_Bool bResult = m_aCurLeaf->Insert(aNewNode); 245 Release(bResult); 246 247 return bResult; 248 } 249 250 //------------------------------------------------------------------ 251 sal_Bool ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue, 252 const ORowSetValue& rNewValue) 253 { 254 openIndexFile(); 255 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 256 ONDXKey aKey; 257 if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey))) 258 return sal_False; 259 else 260 return Delete(nRec, rOldValue) && Insert(nRec,rNewValue); 261 } 262 263 //------------------------------------------------------------------ 264 sal_Bool ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue) 265 { 266 openIndexFile(); 267 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 268 // Existiert der Wert bereits 269 // Find immer verwenden um das aktuelle Blatt zu bestimmen 270 ONDXKey aKey; 271 if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey)) 272 return sal_False; 273 274 ONDXNode aNewNode(aKey); 275 276 // einfuegen in das aktuelle Blatt 277 if (!m_aCurLeaf.Is()) 278 return sal_False; 279 #if OSL_DEBUG_LEVEL > 1 280 m_aRoot->PrintPage(); 281 #endif 282 283 return m_aCurLeaf->Delete(m_nCurNode); 284 } 285 //------------------------------------------------------------------ 286 void ODbaseIndex::Collect(ONDXPage* pPage) 287 { 288 if (pPage) 289 m_aCollector.push_back(pPage); 290 } 291 //------------------------------------------------------------------ 292 void ODbaseIndex::Release(sal_Bool bSave) 293 { 294 // Freigeben der Indexressourcen 295 m_bUseCollector = sal_False; 296 297 if (m_aCurLeaf.Is()) 298 { 299 m_aCurLeaf->Release(bSave); 300 m_aCurLeaf.Clear(); 301 } 302 303 // Wurzel freigeben 304 if (m_aRoot.Is()) 305 { 306 m_aRoot->Release(bSave); 307 m_aRoot.Clear(); 308 } 309 // alle Referenzen freigeben, bevor der FileStream geschlossen wird 310 for (sal_uIntPtr i = 0; i < m_aCollector.size(); i++) 311 m_aCollector[i]->QueryDelete(); 312 313 m_aCollector.clear(); 314 315 // Header modifiziert ? 316 if (bSave && (m_aHeader.db_rootpage != m_nRootPage || 317 m_aHeader.db_pagecount != m_nPageCount)) 318 { 319 m_aHeader.db_rootpage = m_nRootPage; 320 m_aHeader.db_pagecount = m_nPageCount; 321 (*m_pFileStream) << *this; 322 } 323 m_nRootPage = m_nPageCount = 0; 324 m_nCurNode = NODE_NOTFOUND; 325 326 closeImpl(); 327 } 328 // ----------------------------------------------------------------------------- 329 void ODbaseIndex::closeImpl() 330 { 331 if(m_pFileStream) 332 { 333 delete m_pFileStream; 334 m_pFileStream = NULL; 335 } 336 } 337 //------------------------------------------------------------------ 338 ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, sal_Bool bLoad) 339 { 340 OSL_ENSURE(m_pFileStream,"FileStream is not opened!"); 341 342 ONDXPage* pPage; 343 if ( !m_aCollector.empty() ) 344 { 345 pPage = *(m_aCollector.rbegin()); 346 m_aCollector.pop_back(); 347 pPage->SetPagePos(nPagePos); 348 pPage->SetParent(pParent); 349 } 350 else 351 pPage = new ONDXPage(*this, nPagePos, pParent); 352 353 if (bLoad) 354 (*m_pFileStream) >> *pPage; 355 356 return pPage; 357 } 358 359 //------------------------------------------------------------------ 360 SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex) 361 { 362 rStream.Seek(0); 363 rStream.Read(&rIndex.m_aHeader,PAGE_SIZE); 364 365 /* OJ: no longer needed 366 // Text convertierung 367 ByteString aText(rIndex.m_aHeader.db_name); 368 // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); 369 // aText.Convert(rIndex.m_pTable->getConnection()->GetCharacterSet(), m_pTable->getConnection()->getTextEncoding()); 370 strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); 371 */ 372 rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage; 373 rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount; 374 return rStream; 375 } 376 //------------------------------------------------------------------ 377 SvStream& connectivity::dbase::operator << (SvStream &rStream, ODbaseIndex& rIndex) 378 { 379 rStream.Seek(0); 380 /* OJ: no longer needed 381 ByteString aText(rIndex.m_aHeader.db_name); 382 // aText.Convert(m_pTable->getConnection()->getTextEncoding(), rIndex.m_pTable->getConnection()->GetCharacterSet()); 383 strcpy(rIndex.m_aHeader.db_name,aText.GetBuffer()); 384 */ 385 OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,PAGE_SIZE), PAGE_SIZE, "Write not successful: Wrong header size for dbase index!"); 386 return rStream; 387 } 388 // ------------------------------------------------------------------------- 389 ::rtl::OUString ODbaseIndex::getCompletePath() 390 { 391 ::rtl::OUString sDir = m_pTable->getConnection()->getURL(); 392 sDir += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 393 sDir += m_Name; 394 sDir += ::rtl::OUString::createFromAscii(".ndx"); 395 return sDir; 396 } 397 //------------------------------------------------------------------ 398 void ODbaseIndex::createINFEntry() 399 { 400 // inf Datei abgleichen 401 String sEntry = m_Name; 402 sEntry += String::CreateFromAscii(".ndx"); 403 404 ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); 405 sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 406 sCfgFile += m_pTable->getName(); 407 sCfgFile += ::rtl::OUString::createFromAscii(".inf"); 408 409 String sPhysicalPath; 410 LocalFileHelper::ConvertURLToPhysicalName(sCfgFile,sPhysicalPath); 411 412 Config aInfFile(sPhysicalPath); 413 aInfFile.SetGroup(dBASE_III_GROUP); 414 415 sal_uInt16 nSuffix = aInfFile.GetKeyCount(); 416 ByteString aNewEntry,aKeyName; 417 sal_Bool bCase = isCaseSensitive(); 418 while (!aNewEntry.Len()) 419 { 420 aNewEntry = "NDX"; 421 aNewEntry += ByteString::CreateFromInt32(++nSuffix); 422 for (sal_uInt16 i = 0; i < aInfFile.GetKeyCount(); i++) 423 { 424 aKeyName = aInfFile.GetKeyName(i); 425 if (bCase ? aKeyName == aNewEntry : aKeyName.EqualsIgnoreCaseAscii(aNewEntry)) 426 { 427 aNewEntry.Erase(); 428 break; 429 } 430 } 431 } 432 aInfFile.WriteKey(aNewEntry,ByteString(sEntry,m_pTable->getConnection()->getTextEncoding())); 433 } 434 // ------------------------------------------------------------------------- 435 sal_Bool ODbaseIndex::DropImpl() 436 { 437 closeImpl(); 438 439 ::rtl::OUString sPath = getCompletePath(); 440 if(UCBContentHelper::Exists(sPath)) 441 { 442 if(!UCBContentHelper::Kill(sPath)) 443 m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable); 444 } 445 446 // InfDatei abgleichen 447 448 ::rtl::OUString sCfgFile(m_pTable->getConnection()->getURL()); 449 sCfgFile += OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER); 450 sCfgFile += m_pTable->getName(); 451 sCfgFile += ::rtl::OUString::createFromAscii(".inf"); 452 453 String sPhysicalPath; 454 String sNDX(sCfgFile); 455 OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sNDX,sPhysicalPath),"Can not convert Config Filename into Physical Name!"); 456 457 Config aInfFile(sPhysicalPath); 458 aInfFile.SetGroup(dBASE_III_GROUP); 459 sal_uInt16 nKeyCnt = aInfFile.GetKeyCount(); 460 ByteString aKeyName; 461 String sEntry = m_Name; 462 sEntry += String::CreateFromAscii(".ndx"); 463 464 // delete entries from the inf file 465 for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++) 466 { 467 // Verweist der Key auf ein Indexfile?... 468 aKeyName = aInfFile.GetKeyName( nKey ); 469 if (aKeyName.Copy(0,3) == "NDX") 470 { 471 if(sEntry == String(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding())) 472 { 473 aInfFile.DeleteKey(aKeyName); 474 break; 475 } 476 } 477 } 478 return sal_True; 479 } 480 // ------------------------------------------------------------------------- 481 void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const ::rtl::OUString& _sFile) 482 { 483 closeImpl(); 484 if(UCBContentHelper::Exists(_sFile)) 485 UCBContentHelper::Kill(_sFile); 486 m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this); 487 } 488 //------------------------------------------------------------------ 489 sal_Bool ODbaseIndex::CreateImpl() 490 { 491 // Anlegen des Index 492 const ::rtl::OUString sFile = getCompletePath(); 493 if(UCBContentHelper::Exists(sFile)) 494 { 495 const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 496 STR_COULD_NOT_CREATE_INDEX_NAME, 497 "$filename$", sFile 498 ) ); 499 ::dbtools::throwGenericSQLException( sError, *this ); 500 } 501 // Index ist nur einstufig 502 if (m_pColumns->getCount() > 1) 503 m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this); 504 505 Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY); 506 507 // ist die Spalte schon indiziert ? 508 if ( !xCol.is() ) 509 ::dbtools::throwFunctionSequenceException(*this); 510 // else if (pColumn && pColumn->IsIndexed()) 511 // { 512 // String aText = String(OResId(STR_STAT_INDEX_COLUMN_ALREADY_INDEXED)); 513 // aText.SearchAndReplace(String::CreateFromAscii("#"),pColumn->GetName()); 514 // aStatus.Set(SDB_STAT_ERROR, 515 // String::CreateFromAscii("01000"), 516 // aStatus.CreateErrorMessage(aText), 517 // 0, String() ); 518 // return sal_False; 519 // } 520 521 // create the index file 522 m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | STREAM_SHARE_DENYWRITE | STREAM_TRUNC); 523 if (!m_pFileStream) 524 { 525 const ::rtl::OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution( 526 STR_COULD_NOT_LOAD_FILE, 527 "$filename$", sFile 528 ) ); 529 ::dbtools::throwGenericSQLException( sError, *this ); 530 } 531 532 m_pFileStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN); 533 m_pFileStream->SetBufferSize(PAGE_SIZE); 534 m_pFileStream->SetFiller('\0'); 535 536 // Zunaechst muss das Ergebnis sortiert sein 537 utl::SharedUNOComponent<XStatement> xStmt; 538 utl::SharedUNOComponent<XResultSet> xSet; 539 String aName; 540 try 541 { 542 xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW); 543 544 aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME)); 545 546 const String aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString()); 547 String aStatement; 548 aStatement.AssignAscii("SELECT "); 549 aStatement += aQuote; 550 aStatement += aName; 551 aStatement += aQuote; 552 aStatement.AppendAscii(" FROM "); 553 aStatement += aQuote; 554 aStatement += m_pTable->getName().getStr(); 555 aStatement += aQuote; 556 aStatement.AppendAscii(" ORDER BY "); 557 aStatement += aQuote; 558 aStatement += aName; 559 aStatement += aQuote; 560 561 // if (!m_IsUnique) // zusaetzlich sortierung mit der bookmarkspalte 562 // { 563 // aStatement.AppendAscii(" ,"); 564 // aStatement += aQuote; 565 // aStatement.AppendAscii("[BOOKMARK]"); // this is a special column 566 // aStatement += aQuote; 567 // } 568 569 xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW ); 570 } 571 catch(const Exception& ) 572 { 573 impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 574 } 575 if (!xSet.is()) 576 { 577 impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 578 } 579 580 // Setzen der Headerinfo 581 memset(&m_aHeader,0,sizeof(m_aHeader)); 582 sal_Int32 nType = 0; 583 ::vos::ORef<OSQLColumns> aCols = m_pTable->getTableColumns(); 584 const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive()))); 585 586 xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType; 587 588 m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1; 589 m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : (sal_uInt16)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION))); 590 m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4; 591 m_aHeader.db_maxkeys = (PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen); 592 if ( m_aHeader.db_maxkeys < 3 ) 593 { 594 impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile); 595 } 596 597 m_pFileStream->SetStreamSize(PAGE_SIZE); 598 599 ByteString aCol(aName,m_pTable->getConnection()->getTextEncoding()); 600 strncpy(m_aHeader.db_name,aCol.GetBuffer(),std::min((sal_uInt16)sizeof(m_aHeader.db_name), aCol.Len())); 601 m_aHeader.db_unique = m_IsUnique ? 1: 0; 602 m_aHeader.db_keyrec = m_aHeader.db_keylen + 8; 603 604 // modifizierung am Header werden ueber Unterschiede zw. HeaderInfo und nRootPage 605 // bzw. nPageCout erkannt 606 607 m_nRootPage = 1; 608 m_nPageCount = 2; 609 610 // ODatabaseType eType = m_aHeader.db_keytype == 0 ? DataType::VARCHAR : DataType::DOUBLE; 611 m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage); 612 m_aRoot->SetModified(sal_True); 613 614 m_bUseCollector = sal_True; 615 616 // sal_uIntPtr nRowsLeft = pCursor->RowCount(); 617 sal_Int32 nRowsLeft = 0; 618 Reference<XRow> xRow(xSet,UNO_QUERY); 619 620 if(xSet->last()) 621 { 622 Reference< XUnoTunnel> xTunnel(xSet,UNO_QUERY); 623 ODbaseResultSet* pDbaseRes = NULL; 624 if(xTunnel.is()) 625 pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) ); 626 OSL_ENSURE(pDbaseRes,"No dbase resultset found? What's going on here!"); 627 Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY); 628 nRowsLeft = xSet->getRow(); 629 630 xSet->beforeFirst(); 631 ORowSetValue atmpValue=ORowSetValue(); 632 ONDXKey aKey(atmpValue, nType, 0); 633 ONDXKey aInsertKey(atmpValue, nType, 0); 634 // Erzeugen der Indexstruktur 635 while (xSet->next()) 636 { 637 // ODbRow& rRow = *pCursor->GetRow(); 638 ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1))); 639 // ueberpruefen auf doppelten eintrag 640 if (m_IsUnique && m_nCurNode != NODE_NOTFOUND) 641 { 642 aKey.setValue(aValue); 643 if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey()) 644 { 645 impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile); 646 } 647 } 648 aInsertKey.setValue(aValue); 649 aInsertKey.setRecord(pDbaseRes->getCurrentFilePos()); 650 651 ONDXNode aNewNode(aInsertKey); 652 if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft)) 653 break; 654 } 655 } 656 657 if(nRowsLeft) 658 { 659 impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile); 660 } 661 Release(); 662 createINFEntry(); 663 return sal_True; 664 } 665 // ----------------------------------------------------------------------------- 666 // ----------------------------------------------------------------------------- 667 void SAL_CALL ODbaseIndex::acquire() throw() 668 { 669 ODbaseIndex_BASE::acquire(); 670 } 671 // ----------------------------------------------------------------------------- 672 void SAL_CALL ODbaseIndex::release() throw() 673 { 674 ODbaseIndex_BASE::release(); 675 } 676 // ----------------------------------------------------------------------------- 677 678 679 680