Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "dbase/DIndex.hxx"
21 : #include "dbase/DIndexColumns.hxx"
22 : #include <com/sun/star/lang/DisposedException.hpp>
23 : #include <connectivity/sdbcx/VColumn.hxx>
24 : #include <comphelper/sequence.hxx>
25 : #include "dbase/DTable.hxx"
26 : #include "dbase/DIndexIter.hxx"
27 : #include <tools/config.hxx>
28 : #include <connectivity/CommonTools.hxx>
29 : #include <com/sun/star/sdbc/XResultSetMetaData.hpp>
30 : #include <com/sun/star/sdbc/XResultSet.hpp>
31 : #include <com/sun/star/sdbcx/XRowLocate.hpp>
32 : #include <com/sun/star/sdbc/XRow.hpp>
33 : #include <comphelper/extract.hxx>
34 : #include <unotools/localfilehelper.hxx>
35 : #include <unotools/ucbhelper.hxx>
36 : #include <comphelper/types.hxx>
37 : #include <connectivity/dbexception.hxx>
38 : #include "dbase/DResultSet.hxx"
39 : #include "diagnose_ex.h"
40 : #include "resource/dbase_res.hrc"
41 : #include <unotools/sharedunocomponent.hxx>
42 :
43 : using namespace ::comphelper;
44 :
45 : using namespace connectivity;
46 : using namespace utl;
47 : using namespace ::cppu;
48 : using namespace connectivity::file;
49 : using namespace connectivity::sdbcx;
50 : using namespace connectivity::dbase;
51 : using namespace com::sun::star::sdbc;
52 : using namespace com::sun::star::sdbcx;
53 : using namespace com::sun::star::uno;
54 : using namespace com::sun::star::beans;
55 : using namespace com::sun::star::lang;
56 :
57 0 : IMPLEMENT_SERVICE_INFO(ODbaseIndex,"com.sun.star.sdbcx.driver.dbase.Index","com.sun.star.sdbcx.Index");
58 :
59 0 : ODbaseIndex::ODbaseIndex(ODbaseTable* _pTable)
60 : : OIndex(true/*_pTable->getConnection()->getMetaData()->supportsMixedCaseQuotedIdentifiers()*/)
61 : , m_pFileStream(NULL)
62 : , m_nCurNode(NODE_NOTFOUND)
63 : , m_nPageCount(0)
64 : , m_nRootPage(0)
65 : , m_pTable(_pTable)
66 0 : , m_bUseCollector(false)
67 : {
68 0 : memset(&m_aHeader, 0, sizeof(m_aHeader));
69 0 : construct();
70 0 : }
71 :
72 0 : ODbaseIndex::ODbaseIndex( ODbaseTable* _pTable,
73 : const NDXHeader& _rHeader,
74 : const OUString& _rName)
75 : : OIndex(_rName, OUString(), _rHeader.db_unique, false, false, true)
76 : , m_pFileStream(NULL)
77 : , m_aHeader(_rHeader)
78 : , m_nCurNode(NODE_NOTFOUND)
79 : , m_nPageCount(0)
80 : , m_nRootPage(0)
81 : , m_pTable(_pTable)
82 0 : , m_bUseCollector(false)
83 : {
84 0 : construct();
85 0 : }
86 :
87 0 : ODbaseIndex::~ODbaseIndex()
88 : {
89 0 : closeImpl();
90 0 : }
91 :
92 0 : void ODbaseIndex::refreshColumns()
93 : {
94 0 : ::osl::MutexGuard aGuard( m_aMutex );
95 :
96 0 : TStringVector aVector;
97 0 : if(!isNew())
98 : {
99 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
100 : OSL_ENSURE(m_aHeader.db_name[0] != '\0',"Invalid name for the column!");
101 0 : aVector.push_back(OUString::createFromAscii(m_aHeader.db_name));
102 : }
103 :
104 0 : if(m_pColumns)
105 0 : m_pColumns->reFill(aVector);
106 : else
107 0 : m_pColumns = new ODbaseIndexColumns(this,m_aMutex,aVector);
108 0 : }
109 :
110 0 : Sequence< sal_Int8 > ODbaseIndex::getUnoTunnelImplementationId()
111 : {
112 : static ::cppu::OImplementationId * pId = 0;
113 0 : if (! pId)
114 : {
115 0 : ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
116 0 : if (! pId)
117 : {
118 0 : static ::cppu::OImplementationId aId;
119 0 : pId = &aId;
120 0 : }
121 : }
122 0 : return pId->getImplementationId();
123 : }
124 :
125 : // XUnoTunnel
126 :
127 0 : sal_Int64 ODbaseIndex::getSomething( const Sequence< sal_Int8 > & rId ) throw (RuntimeException, std::exception)
128 : {
129 0 : return (rId.getLength() == 16 && 0 == memcmp(getUnoTunnelImplementationId().getConstArray(), rId.getConstArray(), 16 ) )
130 : ? reinterpret_cast< sal_Int64 >( this )
131 0 : : ODbaseIndex_BASE::getSomething(rId);
132 : }
133 :
134 0 : ONDXPagePtr ODbaseIndex::getRoot()
135 : {
136 0 : openIndexFile();
137 0 : if (!m_aRoot.Is())
138 : {
139 0 : m_nRootPage = m_aHeader.db_rootpage;
140 0 : m_nPageCount = m_aHeader.db_pagecount;
141 0 : m_aRoot = CreatePage(m_nRootPage,NULL,true);
142 : }
143 0 : return m_aRoot;
144 : }
145 :
146 0 : bool ODbaseIndex::openIndexFile()
147 : {
148 0 : if(!m_pFileStream)
149 : {
150 0 : OUString sFile = getCompletePath();
151 0 : if(UCBContentHelper::Exists(sFile))
152 : {
153 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile, STREAM_READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYWRITE);
154 0 : if (!m_pFileStream)
155 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile, StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYNONE);
156 0 : if(m_pFileStream)
157 : {
158 0 : m_pFileStream->SetEndian(SvStreamEndian::LITTLE);
159 0 : m_pFileStream->SetBufferSize(DINDEX_PAGE_SIZE);
160 0 : (*m_pFileStream) >> *this;
161 : }
162 : }
163 0 : if(!m_pFileStream)
164 : {
165 0 : const OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
166 : STR_COULD_NOT_LOAD_FILE,
167 : "$filename$", sFile
168 0 : ) );
169 0 : ::dbtools::throwGenericSQLException( sError, *this );
170 0 : }
171 : }
172 :
173 0 : return m_pFileStream != NULL;
174 : }
175 :
176 0 : OIndexIterator* ODbaseIndex::createIterator(OBoolOperator* pOp,
177 : const OOperand* pOperand)
178 : {
179 0 : openIndexFile();
180 0 : return new OIndexIterator(this, pOp, pOperand);
181 : }
182 :
183 0 : bool ODbaseIndex::ConvertToKey(ONDXKey* rKey, sal_uInt32 nRec, const ORowSetValue& rValue)
184 : {
185 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
186 : // Search a specific value in Index
187 : // If the Index is unique, the key doesn't matter
188 : try
189 : {
190 0 : if (m_aHeader.db_keytype == 0)
191 : {
192 0 : *rKey = ONDXKey(rValue.getString(), nRec );
193 : }
194 : else
195 : {
196 0 : if (rValue.isNull())
197 0 : *rKey = ONDXKey(rValue.getDouble(), DataType::DOUBLE, nRec );
198 : else
199 0 : *rKey = ONDXKey(rValue.getDouble(), nRec );
200 : }
201 : }
202 0 : catch (Exception&)
203 : {
204 : OSL_ASSERT(false);
205 0 : return false;
206 : }
207 0 : return true;
208 : }
209 :
210 :
211 0 : bool ODbaseIndex::Find(sal_uInt32 nRec, const ORowSetValue& rValue)
212 : {
213 0 : openIndexFile();
214 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
215 : // Search a specific value in Index
216 : // If the Index is unique, the key doesn't matter
217 0 : ONDXKey aKey;
218 0 : return ConvertToKey(&aKey, nRec, rValue) && getRoot()->Find(aKey);
219 : }
220 :
221 :
222 0 : bool ODbaseIndex::Insert(sal_uInt32 nRec, const ORowSetValue& rValue)
223 : {
224 0 : openIndexFile();
225 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
226 0 : ONDXKey aKey;
227 :
228 : // Does the value already exist
229 : // Use Find() always to determine the actual leaf
230 0 : if (!ConvertToKey(&aKey, nRec, rValue) || (getRoot()->Find(aKey) && isUnique()))
231 0 : return false;
232 :
233 0 : ONDXNode aNewNode(aKey);
234 :
235 : // insert in the current leaf
236 0 : if (!m_aCurLeaf.Is())
237 0 : return false;
238 :
239 0 : bool bResult = m_aCurLeaf->Insert(aNewNode);
240 0 : Release(bResult);
241 :
242 0 : return bResult;
243 : }
244 :
245 :
246 0 : bool ODbaseIndex::Update(sal_uInt32 nRec, const ORowSetValue& rOldValue,
247 : const ORowSetValue& rNewValue)
248 : {
249 0 : openIndexFile();
250 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
251 0 : ONDXKey aKey;
252 0 : if (!ConvertToKey(&aKey, nRec, rNewValue) || (isUnique() && getRoot()->Find(aKey)))
253 0 : return false;
254 : else
255 0 : return Delete(nRec, rOldValue) && Insert(nRec,rNewValue);
256 : }
257 :
258 :
259 0 : bool ODbaseIndex::Delete(sal_uInt32 nRec, const ORowSetValue& rValue)
260 : {
261 0 : openIndexFile();
262 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
263 : // Does the value already exist
264 : // Always use Find() to determine the actual leaf
265 0 : ONDXKey aKey;
266 0 : if (!ConvertToKey(&aKey, nRec, rValue) || !getRoot()->Find(aKey))
267 0 : return false;
268 :
269 0 : ONDXNode aNewNode(aKey);
270 :
271 : // insert in the current leaf
272 0 : if (!m_aCurLeaf.Is())
273 0 : return false;
274 : #if OSL_DEBUG_LEVEL > 1
275 : m_aRoot->PrintPage();
276 : #endif
277 :
278 0 : return m_aCurLeaf->Delete(m_nCurNode);
279 : }
280 :
281 0 : void ODbaseIndex::Collect(ONDXPage* pPage)
282 : {
283 0 : if (pPage)
284 0 : m_aCollector.push_back(pPage);
285 0 : }
286 :
287 0 : void ODbaseIndex::Release(bool bSave)
288 : {
289 : // Release the Index-recources
290 0 : m_bUseCollector = false;
291 :
292 0 : if (m_aCurLeaf.Is())
293 : {
294 0 : m_aCurLeaf->Release(bSave);
295 0 : m_aCurLeaf.Clear();
296 : }
297 :
298 : // Release the root
299 0 : if (m_aRoot.Is())
300 : {
301 0 : m_aRoot->Release(bSave);
302 0 : m_aRoot.Clear();
303 : }
304 : // Release all references, before the FileStream will be closed
305 0 : for (sal_uIntPtr i = 0; i < m_aCollector.size(); i++)
306 0 : m_aCollector[i]->QueryDelete();
307 :
308 0 : m_aCollector.clear();
309 :
310 : // Header modified?
311 0 : if (bSave && (m_aHeader.db_rootpage != m_nRootPage ||
312 0 : m_aHeader.db_pagecount != m_nPageCount))
313 : {
314 0 : m_aHeader.db_rootpage = m_nRootPage;
315 0 : m_aHeader.db_pagecount = m_nPageCount;
316 0 : WriteODbaseIndex( *m_pFileStream, *this );
317 : }
318 0 : m_nRootPage = m_nPageCount = 0;
319 0 : m_nCurNode = NODE_NOTFOUND;
320 :
321 0 : closeImpl();
322 0 : }
323 :
324 0 : void ODbaseIndex::closeImpl()
325 : {
326 0 : if(m_pFileStream)
327 : {
328 0 : delete m_pFileStream;
329 0 : m_pFileStream = NULL;
330 : }
331 0 : }
332 :
333 0 : ONDXPage* ODbaseIndex::CreatePage(sal_uInt32 nPagePos, ONDXPage* pParent, bool bLoad)
334 : {
335 : OSL_ENSURE(m_pFileStream,"FileStream is not opened!");
336 :
337 : ONDXPage* pPage;
338 0 : if ( !m_aCollector.empty() )
339 : {
340 0 : pPage = *(m_aCollector.rbegin());
341 0 : m_aCollector.pop_back();
342 0 : pPage->SetPagePos(nPagePos);
343 0 : pPage->SetParent(pParent);
344 : }
345 : else
346 0 : pPage = new ONDXPage(*this, nPagePos, pParent);
347 :
348 0 : if (bLoad)
349 0 : (*m_pFileStream) >> *pPage;
350 :
351 0 : return pPage;
352 : }
353 :
354 :
355 0 : SvStream& connectivity::dbase::operator >> (SvStream &rStream, ODbaseIndex& rIndex)
356 : {
357 0 : rStream.Seek(0);
358 0 : rStream.Read(&rIndex.m_aHeader,DINDEX_PAGE_SIZE);
359 :
360 0 : rIndex.m_nRootPage = rIndex.m_aHeader.db_rootpage;
361 0 : rIndex.m_nPageCount = rIndex.m_aHeader.db_pagecount;
362 0 : return rStream;
363 : }
364 :
365 0 : SvStream& connectivity::dbase::WriteODbaseIndex(SvStream &rStream, ODbaseIndex& rIndex)
366 : {
367 0 : rStream.Seek(0);
368 0 : OSL_VERIFY_EQUALS( rStream.Write(&rIndex.m_aHeader,DINDEX_PAGE_SIZE), DINDEX_PAGE_SIZE, "Write not successful: Wrong header size for dbase index!");
369 0 : return rStream;
370 : }
371 :
372 0 : OUString ODbaseIndex::getCompletePath()
373 : {
374 0 : OUString sDir = m_pTable->getConnection()->getURL() +
375 0 : OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER) +
376 0 : m_Name + ".ndx";
377 0 : return sDir;
378 : }
379 :
380 0 : void ODbaseIndex::createINFEntry()
381 : {
382 : // synchronize inf-file
383 0 : const OUString sEntry(m_Name + ".ndx");
384 :
385 0 : OUString sCfgFile(m_pTable->getConnection()->getURL() +
386 0 : OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER) +
387 0 : m_pTable->getName() +
388 0 : ".inf");
389 :
390 0 : OUString sPhysicalPath;
391 0 : LocalFileHelper::ConvertURLToPhysicalName(sCfgFile, sPhysicalPath);
392 :
393 0 : Config aInfFile(sPhysicalPath);
394 0 : aInfFile.SetGroup(dBASE_III_GROUP);
395 :
396 0 : sal_uInt16 nSuffix = aInfFile.GetKeyCount();
397 0 : OString aNewEntry,aKeyName;
398 0 : bool bCase = isCaseSensitive();
399 0 : while (aNewEntry.isEmpty())
400 : {
401 0 : aNewEntry = OString("NDX");
402 0 : aNewEntry += OString::number(++nSuffix);
403 0 : for (sal_uInt16 i = 0; i < aInfFile.GetKeyCount(); i++)
404 : {
405 0 : aKeyName = aInfFile.GetKeyName(i);
406 0 : if (bCase ? aKeyName.equals(aNewEntry) : aKeyName.equalsIgnoreAsciiCase(aNewEntry))
407 : {
408 0 : aNewEntry.clear();
409 0 : break;
410 : }
411 : }
412 : }
413 0 : aInfFile.WriteKey(aNewEntry, OUStringToOString(sEntry, m_pTable->getConnection()->getTextEncoding()));
414 0 : }
415 :
416 0 : bool ODbaseIndex::DropImpl()
417 : {
418 0 : closeImpl();
419 :
420 0 : OUString sPath = getCompletePath();
421 0 : if(UCBContentHelper::Exists(sPath))
422 : {
423 0 : if(!UCBContentHelper::Kill(sPath))
424 0 : m_pTable->getConnection()->throwGenericSQLException(STR_COULD_NOT_DELETE_INDEX,*m_pTable);
425 : }
426 :
427 : // synchronize inf-file
428 0 : OUString sCfgFile = m_pTable->getConnection()->getURL() +
429 0 : OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DELIMITER) +
430 0 : m_pTable->getName() + ".inf";
431 :
432 0 : OUString sPhysicalPath;
433 : OSL_VERIFY_RES( LocalFileHelper::ConvertURLToPhysicalName(sCfgFile, sPhysicalPath),
434 0 : "Can not convert Config Filename into Physical Name!");
435 :
436 0 : Config aInfFile(sPhysicalPath);
437 0 : aInfFile.SetGroup(dBASE_III_GROUP);
438 0 : sal_uInt16 nKeyCnt = aInfFile.GetKeyCount();
439 0 : OString aKeyName;
440 0 : OUString sEntry = m_Name + ".ndx";
441 :
442 : // delete entries from the inf file
443 0 : for (sal_uInt16 nKey = 0; nKey < nKeyCnt; nKey++)
444 : {
445 : // References the Key to an Index-file?
446 0 : aKeyName = aInfFile.GetKeyName( nKey );
447 0 : if (aKeyName.copy(0,3) == "NDX")
448 : {
449 0 : if(sEntry == OStringToOUString(aInfFile.ReadKey(aKeyName),m_pTable->getConnection()->getTextEncoding()))
450 : {
451 0 : aInfFile.DeleteKey(aKeyName);
452 0 : break;
453 : }
454 : }
455 : }
456 0 : return true;
457 : }
458 :
459 0 : void ODbaseIndex::impl_killFileAndthrowError_throw(sal_uInt16 _nErrorId,const OUString& _sFile)
460 : {
461 0 : closeImpl();
462 0 : if(UCBContentHelper::Exists(_sFile))
463 0 : UCBContentHelper::Kill(_sFile);
464 0 : m_pTable->getConnection()->throwGenericSQLException(_nErrorId,*this);
465 0 : }
466 :
467 0 : bool ODbaseIndex::CreateImpl()
468 : {
469 : // Create the Index
470 0 : const OUString sFile = getCompletePath();
471 0 : if(UCBContentHelper::Exists(sFile))
472 : {
473 0 : const OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
474 : STR_COULD_NOT_CREATE_INDEX_NAME,
475 : "$filename$", sFile
476 0 : ) );
477 0 : ::dbtools::throwGenericSQLException( sError, *this );
478 : }
479 : // Index comprises only one column
480 0 : if (m_pColumns->getCount() > 1)
481 0 : m_pTable->getConnection()->throwGenericSQLException(STR_ONL_ONE_COLUMN_PER_INDEX,*this);
482 :
483 0 : Reference<XFastPropertySet> xCol(m_pColumns->getByIndex(0),UNO_QUERY);
484 :
485 : // Is the column already indexed?
486 0 : if ( !xCol.is() )
487 0 : ::dbtools::throwFunctionSequenceException(*this);
488 :
489 : // create the index file
490 0 : m_pFileStream = OFileTable::createStream_simpleError(sFile,STREAM_READWRITE | StreamMode::SHARE_DENYWRITE | StreamMode::TRUNC);
491 0 : if (!m_pFileStream)
492 : {
493 0 : const OUString sError( m_pTable->getConnection()->getResources().getResourceStringWithSubstitution(
494 : STR_COULD_NOT_LOAD_FILE,
495 : "$filename$", sFile
496 0 : ) );
497 0 : ::dbtools::throwGenericSQLException( sError, *this );
498 : }
499 :
500 0 : m_pFileStream->SetEndian(SvStreamEndian::LITTLE);
501 0 : m_pFileStream->SetBufferSize(DINDEX_PAGE_SIZE);
502 :
503 : // firstly the result must be sorted
504 0 : utl::SharedUNOComponent<XStatement> xStmt;
505 0 : utl::SharedUNOComponent<XResultSet> xSet;
506 0 : OUString aName;
507 : try
508 : {
509 0 : xStmt.set( m_pTable->getConnection()->createStatement(), UNO_SET_THROW);
510 :
511 0 : aName = getString(xCol->getFastPropertyValue(PROPERTY_ID_NAME));
512 :
513 0 : const OUString aQuote(m_pTable->getConnection()->getMetaData()->getIdentifierQuoteString());
514 0 : OUString aStatement( "SELECT " + aQuote + aName + aQuote +" FROM " + aQuote + m_pTable->getName() + aQuote + " ORDER BY " + aQuote + aName + aQuote);
515 :
516 0 : xSet.set( xStmt->executeQuery(aStatement),UNO_SET_THROW );
517 : }
518 0 : catch(const Exception& )
519 : {
520 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
521 : }
522 0 : if (!xSet.is())
523 : {
524 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
525 : }
526 :
527 : // Set the header info
528 0 : memset(&m_aHeader,0,sizeof(m_aHeader));
529 0 : sal_Int32 nType = 0;
530 0 : ::rtl::Reference<OSQLColumns> aCols = m_pTable->getTableColumns();
531 0 : const Reference< XPropertySet > xTableCol(*find(aCols->get().begin(),aCols->get().end(),aName,::comphelper::UStringMixEqual(isCaseSensitive())));
532 :
533 0 : xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE)) >>= nType;
534 :
535 0 : m_aHeader.db_keytype = (nType == DataType::VARCHAR || nType == DataType::CHAR) ? 0 : 1;
536 0 : m_aHeader.db_keylen = (m_aHeader.db_keytype) ? 8 : (sal_uInt16)getINT32(xTableCol->getPropertyValue(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_PRECISION)));
537 0 : m_aHeader.db_keylen = (( m_aHeader.db_keylen - 1) / 4 + 1) * 4;
538 0 : m_aHeader.db_maxkeys = (DINDEX_PAGE_SIZE - 4) / (8 + m_aHeader.db_keylen);
539 0 : if ( m_aHeader.db_maxkeys < 3 )
540 : {
541 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_KEYSIZE,sFile);
542 : }
543 :
544 0 : m_pFileStream->SetStreamSize(DINDEX_PAGE_SIZE);
545 :
546 0 : OString aCol(OUStringToOString(aName, m_pTable->getConnection()->getTextEncoding()));
547 0 : strncpy(m_aHeader.db_name, aCol.getStr(), std::min<size_t>(sizeof(m_aHeader.db_name), aCol.getLength()));
548 0 : m_aHeader.db_unique = m_IsUnique ? 1: 0;
549 0 : m_aHeader.db_keyrec = m_aHeader.db_keylen + 8;
550 :
551 : // modifications of the header are detected by differences between
552 : // the HeaderInfo and nRootPage or nPageCount respectively
553 0 : m_nRootPage = 1;
554 0 : m_nPageCount = 2;
555 :
556 0 : m_aCurLeaf = m_aRoot = CreatePage(m_nRootPage);
557 0 : m_aRoot->SetModified(true);
558 :
559 0 : m_bUseCollector = true;
560 :
561 0 : sal_Int32 nRowsLeft = 0;
562 0 : Reference<XRow> xRow(xSet,UNO_QUERY);
563 :
564 0 : if(xSet->last())
565 : {
566 0 : Reference< XUnoTunnel> xTunnel(xSet, UNO_QUERY_THROW);
567 0 : ODbaseResultSet* pDbaseRes = reinterpret_cast< ODbaseResultSet* >( xTunnel->getSomething(ODbaseResultSet::getUnoTunnelImplementationId()) );
568 : assert(pDbaseRes); //"No dbase resultset found? What's going on here!
569 0 : Reference<XRowLocate> xRowLocate(xSet,UNO_QUERY);
570 0 : nRowsLeft = xSet->getRow();
571 :
572 0 : xSet->beforeFirst();
573 0 : ORowSetValue atmpValue=ORowSetValue();
574 0 : ONDXKey aKey(atmpValue, nType, 0);
575 0 : ONDXKey aInsertKey(atmpValue, nType, 0);
576 : // Create the index structure
577 0 : while (xSet->next())
578 : {
579 0 : ORowSetValue aValue(m_aHeader.db_keytype ? ORowSetValue(xRow->getDouble(1)) : ORowSetValue(xRow->getString(1)));
580 : // checking for duplicate entries
581 0 : if (m_IsUnique && m_nCurNode != NODE_NOTFOUND)
582 : {
583 0 : aKey.setValue(aValue);
584 0 : if (aKey == (*m_aCurLeaf)[m_nCurNode].GetKey())
585 : {
586 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX_NOT_UNIQUE,sFile);
587 : }
588 : }
589 0 : aInsertKey.setValue(aValue);
590 0 : aInsertKey.setRecord(pDbaseRes->getCurrentFilePos());
591 :
592 0 : ONDXNode aNewNode(aInsertKey);
593 0 : if (!m_aCurLeaf->Insert(aNewNode, --nRowsLeft))
594 0 : break;
595 0 : }
596 : }
597 :
598 0 : if(nRowsLeft)
599 : {
600 0 : impl_killFileAndthrowError_throw(STR_COULD_NOT_CREATE_INDEX,sFile);
601 : }
602 0 : Release();
603 0 : createINFEntry();
604 0 : return true;
605 : }
606 :
607 :
608 0 : void SAL_CALL ODbaseIndex::acquire() throw()
609 : {
610 0 : ODbaseIndex_BASE::acquire();
611 0 : }
612 :
613 0 : void SAL_CALL ODbaseIndex::release() throw()
614 : {
615 0 : ODbaseIndex_BASE::release();
616 0 : }
617 :
618 :
619 :
620 :
621 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|