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