xref: /trunk/main/connectivity/source/drivers/dbase/DIndex.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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