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