xref: /trunk/main/connectivity/source/drivers/dbase/dindexnode.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
1*9b5730f6SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9b5730f6SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9b5730f6SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9b5730f6SAndrew Rist  * distributed with this work for additional information
6*9b5730f6SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9b5730f6SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9b5730f6SAndrew Rist  * "License"); you may not use this file except in compliance
9*9b5730f6SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*9b5730f6SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*9b5730f6SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9b5730f6SAndrew Rist  * software distributed under the License is distributed on an
15*9b5730f6SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9b5730f6SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9b5730f6SAndrew Rist  * specific language governing permissions and limitations
18*9b5730f6SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*9b5730f6SAndrew Rist  *************************************************************/
21*9b5730f6SAndrew Rist 
22*9b5730f6SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_connectivity.hxx"
26cdf0e10cSrcweir #include "dbase/dindexnode.hxx"
27cdf0e10cSrcweir #include "connectivity/CommonTools.hxx"
28cdf0e10cSrcweir #include <osl/thread.h>
29cdf0e10cSrcweir #include "dbase/DIndex.hxx"
30cdf0e10cSrcweir #include <tools/debug.hxx>
31cdf0e10cSrcweir #include "diagnose_ex.h"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <algorithm>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir 
36cdf0e10cSrcweir using namespace connectivity;
37cdf0e10cSrcweir using namespace connectivity::dbase;
38cdf0e10cSrcweir using namespace connectivity::file;
39cdf0e10cSrcweir using namespace com::sun::star::sdbc;
40cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(sal_uInt32 nRec)41cdf0e10cSrcweir ONDXKey::ONDXKey(sal_uInt32 nRec)
42cdf0e10cSrcweir     :nRecord(nRec)
43cdf0e10cSrcweir {
44cdf0e10cSrcweir }
45cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(const ORowSetValue & rVal,sal_Int32 eType,sal_uInt32 nRec)46cdf0e10cSrcweir ONDXKey::ONDXKey(const ORowSetValue& rVal, sal_Int32 eType, sal_uInt32 nRec)
47cdf0e10cSrcweir     : ONDXKey_BASE(eType)
48cdf0e10cSrcweir     , nRecord(nRec)
49cdf0e10cSrcweir     , xValue(rVal)
50cdf0e10cSrcweir {
51cdf0e10cSrcweir }
52cdf0e10cSrcweir // -----------------------------------------------------------------------------
ONDXKey(const rtl::OUString & aStr,sal_uInt32 nRec)53cdf0e10cSrcweir ONDXKey::ONDXKey(const rtl::OUString& aStr, sal_uInt32 nRec)
54cdf0e10cSrcweir     : ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR)
55cdf0e10cSrcweir      ,nRecord(nRec)
56cdf0e10cSrcweir {
57cdf0e10cSrcweir     if (aStr.getLength())
58cdf0e10cSrcweir     {
59cdf0e10cSrcweir         xValue = aStr;
60cdf0e10cSrcweir         xValue.setBound(sal_True);
61cdf0e10cSrcweir     }
62cdf0e10cSrcweir }
63cdf0e10cSrcweir // -----------------------------------------------------------------------------
64cdf0e10cSrcweir 
ONDXKey(double aVal,sal_uInt32 nRec)65cdf0e10cSrcweir ONDXKey::ONDXKey(double aVal, sal_uInt32 nRec)
66cdf0e10cSrcweir     : ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE)
67cdf0e10cSrcweir      ,nRecord(nRec)
68cdf0e10cSrcweir      ,xValue(aVal)
69cdf0e10cSrcweir {
70cdf0e10cSrcweir }
71cdf0e10cSrcweir // -----------------------------------------------------------------------------
72cdf0e10cSrcweir 
73cdf0e10cSrcweir //==================================================================
74cdf0e10cSrcweir // Index Seite
75cdf0e10cSrcweir //==================================================================
ONDXPage(ODbaseIndex & rInd,sal_uInt32 nPos,ONDXPage * pParent)76cdf0e10cSrcweir ONDXPage::ONDXPage(ODbaseIndex& rInd, sal_uInt32 nPos, ONDXPage* pParent)
77cdf0e10cSrcweir            :nPagePos(nPos)
78cdf0e10cSrcweir            ,bModified(sal_False)
79cdf0e10cSrcweir            ,nCount(0)
80cdf0e10cSrcweir            ,aParent(pParent)
81cdf0e10cSrcweir            ,rIndex(rInd)
82cdf0e10cSrcweir            ,ppNodes(NULL)
83cdf0e10cSrcweir {
84cdf0e10cSrcweir     sal_uInt16 nT = rIndex.getHeader().db_maxkeys;
85cdf0e10cSrcweir     ppNodes = new ONDXNode[nT];
86cdf0e10cSrcweir }
87cdf0e10cSrcweir 
88cdf0e10cSrcweir //------------------------------------------------------------------
~ONDXPage()89cdf0e10cSrcweir ONDXPage::~ONDXPage()
90cdf0e10cSrcweir {
91cdf0e10cSrcweir     delete[] ppNodes;
92cdf0e10cSrcweir     //  delete aParent;
93cdf0e10cSrcweir     //  delete aChild;
94cdf0e10cSrcweir }
95cdf0e10cSrcweir //------------------------------------------------------------------
QueryDelete()96cdf0e10cSrcweir void ONDXPage::QueryDelete()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     // Ablegen im GarbageCollector
99cdf0e10cSrcweir     if (IsModified() && rIndex.m_pFileStream)
100cdf0e10cSrcweir         (*rIndex.m_pFileStream) << *this;
101cdf0e10cSrcweir 
102cdf0e10cSrcweir     bModified = sal_False;
103cdf0e10cSrcweir     if (rIndex.UseCollector())
104cdf0e10cSrcweir     {
105cdf0e10cSrcweir         if (aChild.Is())
106cdf0e10cSrcweir             aChild->Release(sal_False);
107cdf0e10cSrcweir 
108cdf0e10cSrcweir         for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
109cdf0e10cSrcweir         {
110cdf0e10cSrcweir             if (ppNodes[i].GetChild().Is())
111cdf0e10cSrcweir                 ppNodes[i].GetChild()->Release(sal_False);
112cdf0e10cSrcweir 
113cdf0e10cSrcweir             ppNodes[i] = ONDXNode();
114cdf0e10cSrcweir         }
115cdf0e10cSrcweir         RestoreNoDelete();
116cdf0e10cSrcweir 
117cdf0e10cSrcweir         nCount = 0;
118cdf0e10cSrcweir         aParent.Clear();
119cdf0e10cSrcweir         rIndex.Collect(this);
120cdf0e10cSrcweir     }
121cdf0e10cSrcweir     else
122cdf0e10cSrcweir         SvRefBase::QueryDelete();
123cdf0e10cSrcweir }
124cdf0e10cSrcweir //------------------------------------------------------------------
GetChild(ODbaseIndex * pIndex)125cdf0e10cSrcweir ONDXPagePtr& ONDXPage::GetChild(ODbaseIndex* pIndex)
126cdf0e10cSrcweir {
127cdf0e10cSrcweir     if (!aChild.Is() && pIndex)
128cdf0e10cSrcweir     {
129cdf0e10cSrcweir         aChild = rIndex.CreatePage(aChild.GetPagePos(),this,aChild.HasPage());
130cdf0e10cSrcweir     }
131cdf0e10cSrcweir     return aChild;
132cdf0e10cSrcweir }
133cdf0e10cSrcweir 
134cdf0e10cSrcweir //------------------------------------------------------------------
FindPos(const ONDXKey & rKey) const135cdf0e10cSrcweir sal_uInt16 ONDXPage::FindPos(const ONDXKey& rKey) const
136cdf0e10cSrcweir {
137cdf0e10cSrcweir     // sucht nach Platz fuer den vorgegeben key auf einer Seite
138cdf0e10cSrcweir     sal_uInt16 i = 0;
139cdf0e10cSrcweir     while (i < nCount && rKey > ((*this)[i]).GetKey())
140cdf0e10cSrcweir            i++;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     return i;
143cdf0e10cSrcweir }
144cdf0e10cSrcweir 
145cdf0e10cSrcweir //------------------------------------------------------------------
Find(const ONDXKey & rKey)146cdf0e10cSrcweir sal_Bool ONDXPage::Find(const ONDXKey& rKey)
147cdf0e10cSrcweir {
148cdf0e10cSrcweir     // sucht den vorgegeben key
149cdf0e10cSrcweir     // Besonderheit: gelangt der Algorithmus ans Ende
150cdf0e10cSrcweir     // wird immer die aktuelle Seite und die Knotenposition vermerkt
151cdf0e10cSrcweir     // auf die die Bedingung <= zutrifft
152cdf0e10cSrcweir     // dieses findet beim Insert besondere Beachtung
153cdf0e10cSrcweir     sal_uInt16 i = 0;
154cdf0e10cSrcweir     while (i < nCount && rKey > ((*this)[i]).GetKey())
155cdf0e10cSrcweir            i++;
156cdf0e10cSrcweir 
157cdf0e10cSrcweir     sal_Bool bResult = sal_False;
158cdf0e10cSrcweir 
159cdf0e10cSrcweir     if (!IsLeaf())
160cdf0e10cSrcweir     {
161cdf0e10cSrcweir         // weiter absteigen
162cdf0e10cSrcweir         ONDXPagePtr aPage = (i==0) ? GetChild(&rIndex) : ((*this)[i-1]).GetChild(&rIndex, this);
163cdf0e10cSrcweir         bResult = aPage.Is() && aPage->Find(rKey);
164cdf0e10cSrcweir     }
165cdf0e10cSrcweir     else if (i == nCount)
166cdf0e10cSrcweir     {
167cdf0e10cSrcweir         rIndex.m_aCurLeaf = this;
168cdf0e10cSrcweir         rIndex.m_nCurNode = i - 1;
169cdf0e10cSrcweir         bResult = sal_False;
170cdf0e10cSrcweir     }
171cdf0e10cSrcweir     else
172cdf0e10cSrcweir     {
173cdf0e10cSrcweir         bResult = rKey == ((*this)[i]).GetKey();
174cdf0e10cSrcweir         rIndex.m_aCurLeaf = this;
175cdf0e10cSrcweir         rIndex.m_nCurNode = bResult ? i : i - 1;
176cdf0e10cSrcweir     }
177cdf0e10cSrcweir     return bResult;
178cdf0e10cSrcweir }
179cdf0e10cSrcweir 
180cdf0e10cSrcweir //------------------------------------------------------------------
Insert(ONDXNode & rNode,sal_uInt32 nRowsLeft)181cdf0e10cSrcweir sal_Bool ONDXPage::Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft)
182cdf0e10cSrcweir {
183cdf0e10cSrcweir     // beim Erzeugen eines Index koennen auch mehrere Knoten eingefuegt werden
184cdf0e10cSrcweir     // diese sin dann aufsteigend sortiert
185cdf0e10cSrcweir     sal_Bool bAppend = nRowsLeft > 0;
186cdf0e10cSrcweir     if (IsFull())
187cdf0e10cSrcweir     {
188cdf0e10cSrcweir         sal_Bool bResult = sal_True;
189cdf0e10cSrcweir         ONDXNode aSplitNode;
190cdf0e10cSrcweir         if (bAppend)
191cdf0e10cSrcweir             aSplitNode = rNode;
192cdf0e10cSrcweir         else
193cdf0e10cSrcweir         {
194cdf0e10cSrcweir             // merken des letzten Knotens
195cdf0e10cSrcweir             aSplitNode = (*this)[nCount-1];
196cdf0e10cSrcweir             if(rNode.GetKey() <= aSplitNode.GetKey())
197cdf0e10cSrcweir             {
198cdf0e10cSrcweir 
199cdf0e10cSrcweir                 // und damit habe ich im folgenden praktisch eine Node weniger
200cdf0e10cSrcweir                 if (IsLeaf() && this == &rIndex.m_aCurLeaf)
201cdf0e10cSrcweir                 {
202cdf0e10cSrcweir                     // geht davon aus, dass der Knoten, auf dem die Bedingung (<=)
203cdf0e10cSrcweir                     // zutrifft, als m_nCurNode gesetzt ist
204cdf0e10cSrcweir                     --nCount;   // (sonst bekomme ich u.U. Assertions und GPFs - 60593)
205cdf0e10cSrcweir                     bResult = Insert(rIndex.m_nCurNode + 1, rNode);
206cdf0e10cSrcweir                 }
207cdf0e10cSrcweir                 else  // Position unbekannt
208cdf0e10cSrcweir                 {
209cdf0e10cSrcweir                     sal_uInt16 nPos = NODE_NOTFOUND;
210cdf0e10cSrcweir                     while (++nPos < nCount && rNode.GetKey() > ((*this)[nPos]).GetKey()) ;
211cdf0e10cSrcweir 
212cdf0e10cSrcweir                     --nCount;   // (sonst bekomme ich u.U. Assertions und GPFs - 60593)
213cdf0e10cSrcweir                     bResult = Insert(nPos, rNode);
214cdf0e10cSrcweir                 }
215cdf0e10cSrcweir 
216cdf0e10cSrcweir                 // konnte der neue Knoten eingefuegt werden
217cdf0e10cSrcweir                 if (!bResult)
218cdf0e10cSrcweir                 {
219cdf0e10cSrcweir                     nCount++;
220cdf0e10cSrcweir                     aSplitNode = rNode;
221cdf0e10cSrcweir                 }
222cdf0e10cSrcweir             }
223cdf0e10cSrcweir             else
224cdf0e10cSrcweir                 aSplitNode = rNode;
225cdf0e10cSrcweir         }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir         sal_uInt32 nNewPagePos = rIndex.GetPageCount();
228cdf0e10cSrcweir         sal_uInt32 nNewPageCount = nNewPagePos + 1;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         // Herausgeloesten Knoten beim Vater einfuegen
231cdf0e10cSrcweir         if (!HasParent())
232cdf0e10cSrcweir         {
233cdf0e10cSrcweir             // Kein Vater, dann neue Wurzel
234cdf0e10cSrcweir             ONDXPagePtr aNewRoot = rIndex.CreatePage(nNewPagePos + 1);
235cdf0e10cSrcweir             aNewRoot->SetChild(this);
236cdf0e10cSrcweir 
237cdf0e10cSrcweir             rIndex.m_aRoot = aNewRoot;
238cdf0e10cSrcweir             rIndex.SetRootPos(nNewPagePos + 1);
239cdf0e10cSrcweir             rIndex.SetPageCount(++nNewPageCount);
240cdf0e10cSrcweir         }
241cdf0e10cSrcweir 
242cdf0e10cSrcweir         // neues blatt erzeugen und Seite aufteilen
243cdf0e10cSrcweir         ONDXPagePtr aNewPage = rIndex.CreatePage(nNewPagePos,aParent);
244cdf0e10cSrcweir         rIndex.SetPageCount(nNewPageCount);
245cdf0e10cSrcweir 
246cdf0e10cSrcweir         // wieviele Knoten weren noch eingefuegt
247cdf0e10cSrcweir         // kommen noch ausreichend, dann koennen die Seiten bis zum Rand vollgestopft werden
248cdf0e10cSrcweir 
249cdf0e10cSrcweir         ONDXNode aInnerNode;
250cdf0e10cSrcweir         if (!IsLeaf() || nRowsLeft < (sal_uInt32)(rIndex.GetMaxNodes() / 2))
251cdf0e10cSrcweir             aInnerNode = Split(*aNewPage);
252cdf0e10cSrcweir         else
253cdf0e10cSrcweir         {
254cdf0e10cSrcweir             aInnerNode = (*this)[nCount - 1];
255cdf0e10cSrcweir             //aInnerNode = aSplitNode;
256cdf0e10cSrcweir 
257cdf0e10cSrcweir             // Knoten zeigt auf neue Seite
258cdf0e10cSrcweir             aInnerNode.SetChild(aNewPage);
259cdf0e10cSrcweir 
260cdf0e10cSrcweir             // innere Knoten haben keine Recordnummer
261cdf0e10cSrcweir             if (rIndex.isUnique())
262cdf0e10cSrcweir                 aInnerNode.GetKey().ResetRecord();
263cdf0e10cSrcweir 
264cdf0e10cSrcweir             // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
265cdf0e10cSrcweir             if (!IsLeaf())
266cdf0e10cSrcweir                 aNewPage->SetChild(aInnerNode.GetChild());
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir         aNewPage->Append(aSplitNode);
270cdf0e10cSrcweir         ONDXPagePtr aTempParent = aParent;
271cdf0e10cSrcweir         if (IsLeaf())
272cdf0e10cSrcweir         {
273cdf0e10cSrcweir             rIndex.m_aCurLeaf = aNewPage;
274cdf0e10cSrcweir             rIndex.m_nCurNode = rIndex.m_aCurLeaf->Count() - 1;
275cdf0e10cSrcweir 
276cdf0e10cSrcweir             // Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
277cdf0e10cSrcweir             // mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
278cdf0e10cSrcweir             ReleaseFull();
279cdf0e10cSrcweir         }
280cdf0e10cSrcweir 
281cdf0e10cSrcweir         // Einfuegen des herausgeloesten Knotens
282cdf0e10cSrcweir         return aTempParent->Insert(aInnerNode);
283cdf0e10cSrcweir     }
284cdf0e10cSrcweir     else // Seite einfach weiter auffuellen
285cdf0e10cSrcweir     {
286cdf0e10cSrcweir         if (bAppend)
287cdf0e10cSrcweir         {
288cdf0e10cSrcweir             if (IsLeaf())
289cdf0e10cSrcweir                 rIndex.m_nCurNode = nCount - 1;
290cdf0e10cSrcweir             return Append(rNode);
291cdf0e10cSrcweir         }
292cdf0e10cSrcweir         else
293cdf0e10cSrcweir         {
294cdf0e10cSrcweir             sal_uInt16 nNodePos = FindPos(rNode.GetKey());
295cdf0e10cSrcweir             if (IsLeaf())
296cdf0e10cSrcweir                 rIndex.m_nCurNode = nNodePos;
297cdf0e10cSrcweir 
298cdf0e10cSrcweir             return Insert(nNodePos, rNode);
299cdf0e10cSrcweir         }
300cdf0e10cSrcweir     }
301cdf0e10cSrcweir }
302cdf0e10cSrcweir 
303cdf0e10cSrcweir //------------------------------------------------------------------
Insert(sal_uInt16 nPos,ONDXNode & rNode)304cdf0e10cSrcweir sal_Bool ONDXPage::Insert(sal_uInt16 nPos, ONDXNode& rNode)
305cdf0e10cSrcweir {
306cdf0e10cSrcweir     sal_uInt16 nMaxCount = rIndex.getHeader().db_maxkeys;
307cdf0e10cSrcweir     if (nPos >= nMaxCount)
308cdf0e10cSrcweir         return sal_False;
309cdf0e10cSrcweir 
310cdf0e10cSrcweir     if (nCount)
311cdf0e10cSrcweir     {
312cdf0e10cSrcweir         ++nCount;
313cdf0e10cSrcweir         // nach rechts verschieben
314cdf0e10cSrcweir         for (sal_uInt16 i = std::min((sal_uInt16)(nMaxCount-1), (sal_uInt16)(nCount-1)); nPos < i; --i)
315cdf0e10cSrcweir             (*this)[i] = (*this)[i-1];
316cdf0e10cSrcweir     }
317cdf0e10cSrcweir     else
318cdf0e10cSrcweir         if (nCount < nMaxCount)
319cdf0e10cSrcweir             nCount++;
320cdf0e10cSrcweir 
321cdf0e10cSrcweir     // einfuegen an der Position
322cdf0e10cSrcweir     ONDXNode& rInsertNode = (*this)[nPos];
323cdf0e10cSrcweir     rInsertNode = rNode;
324cdf0e10cSrcweir     if (rInsertNode.GetChild().Is())
325cdf0e10cSrcweir     {
326cdf0e10cSrcweir         rInsertNode.GetChild()->SetParent(this);
327cdf0e10cSrcweir         rNode.GetChild()->SetParent(this);
328cdf0e10cSrcweir     }
329cdf0e10cSrcweir 
330cdf0e10cSrcweir     bModified = sal_True;
331cdf0e10cSrcweir 
332cdf0e10cSrcweir     return sal_True;
333cdf0e10cSrcweir }
334cdf0e10cSrcweir 
335cdf0e10cSrcweir //------------------------------------------------------------------
Append(ONDXNode & rNode)336cdf0e10cSrcweir sal_Bool ONDXPage::Append(ONDXNode& rNode)
337cdf0e10cSrcweir {
338cdf0e10cSrcweir     DBG_ASSERT(!IsFull(), "kein Append moeglich");
339cdf0e10cSrcweir     return Insert(nCount, rNode);
340cdf0e10cSrcweir }
341cdf0e10cSrcweir //------------------------------------------------------------------
Release(sal_Bool bSave)342cdf0e10cSrcweir void ONDXPage::Release(sal_Bool bSave)
343cdf0e10cSrcweir {
344cdf0e10cSrcweir     // freigeben der Pages
345cdf0e10cSrcweir     if (aChild.Is())
346cdf0e10cSrcweir         aChild->Release(bSave);
347cdf0e10cSrcweir 
348cdf0e10cSrcweir     // Pointer freigeben
349cdf0e10cSrcweir     aChild.Clear();
350cdf0e10cSrcweir 
351cdf0e10cSrcweir     for (sal_uInt16 i = 0; i < rIndex.getHeader().db_maxkeys;i++)
352cdf0e10cSrcweir     {
353cdf0e10cSrcweir         if (ppNodes[i].GetChild())
354cdf0e10cSrcweir             ppNodes[i].GetChild()->Release(bSave);
355cdf0e10cSrcweir 
356cdf0e10cSrcweir         ppNodes[i].GetChild().Clear();
357cdf0e10cSrcweir     }
358cdf0e10cSrcweir     aParent = NULL;
359cdf0e10cSrcweir }
360cdf0e10cSrcweir //------------------------------------------------------------------
ReleaseFull(sal_Bool bSave)361cdf0e10cSrcweir void ONDXPage::ReleaseFull(sal_Bool bSave)
362cdf0e10cSrcweir {
363cdf0e10cSrcweir     ONDXPagePtr aTempParent = aParent;
364cdf0e10cSrcweir     Release(bSave);
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     if (aTempParent.Is())
367cdf0e10cSrcweir     {
368cdf0e10cSrcweir         // Freigeben nicht benoetigter Seiten, danach besteht keine Referenz
369cdf0e10cSrcweir         // mehr auf die Seite, danach kann 'this' nicht mehr gueltig sein!!!
370cdf0e10cSrcweir         sal_uInt16 nParentPos = aTempParent->Search(this);
371cdf0e10cSrcweir         if (nParentPos != NODE_NOTFOUND)
372cdf0e10cSrcweir             (*aTempParent)[nParentPos].GetChild().Clear();
373cdf0e10cSrcweir         else
374cdf0e10cSrcweir             aTempParent->GetChild().Clear();
375cdf0e10cSrcweir     }
376cdf0e10cSrcweir }
377cdf0e10cSrcweir //------------------------------------------------------------------
Delete(sal_uInt16 nNodePos)378cdf0e10cSrcweir sal_Bool ONDXPage::Delete(sal_uInt16 nNodePos)
379cdf0e10cSrcweir {
380cdf0e10cSrcweir     if (IsLeaf())
381cdf0e10cSrcweir     {
382cdf0e10cSrcweir         // Letztes Element wird geloescht
383cdf0e10cSrcweir         if (nNodePos == (nCount - 1))
384cdf0e10cSrcweir         {
385cdf0e10cSrcweir             ONDXNode aNode = (*this)[nNodePos];
386cdf0e10cSrcweir 
387cdf0e10cSrcweir             // beim Parent muss nun der KeyValue ausgetauscht werden
388cdf0e10cSrcweir             if (HasParent())
389cdf0e10cSrcweir                 aParent->SearchAndReplace(aNode.GetKey(),
390cdf0e10cSrcweir                                           (*this)[nNodePos-1].GetKey());
391cdf0e10cSrcweir         }
392cdf0e10cSrcweir     }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir     // Loeschen des Knoten
395cdf0e10cSrcweir     Remove(nNodePos);
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     // Unterlauf
398cdf0e10cSrcweir     if (HasParent() && nCount < (rIndex.GetMaxNodes() / 2))
399cdf0e10cSrcweir     {
400cdf0e10cSrcweir         // Feststellen, welcher Knoten auf die Seite zeigt
401cdf0e10cSrcweir         sal_uInt16 nParentNodePos = aParent->Search(this);
402cdf0e10cSrcweir         // letzte Element auf Vaterseite
403cdf0e10cSrcweir         // -> zusammenlegen mit vorletzter Seite
404cdf0e10cSrcweir         if (nParentNodePos == (aParent->Count() - 1))
405cdf0e10cSrcweir         {
406cdf0e10cSrcweir             if (!nParentNodePos)
407cdf0e10cSrcweir             // zusammenlegen mit linken nachbarn
408cdf0e10cSrcweir                 Merge(nParentNodePos,aParent->GetChild(&rIndex));
409cdf0e10cSrcweir             else
410cdf0e10cSrcweir                 Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
411cdf0e10cSrcweir         }
412cdf0e10cSrcweir         // sonst Seite mit naechster Seite zusammenlegen
413cdf0e10cSrcweir         else
414cdf0e10cSrcweir         {
415cdf0e10cSrcweir             // zusammenlegen mit rechten nachbarn
416cdf0e10cSrcweir             Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
417cdf0e10cSrcweir             nParentNodePos++;
418cdf0e10cSrcweir         }
419cdf0e10cSrcweir         if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
420cdf0e10cSrcweir             aParent->Delete(nParentNodePos);
421cdf0e10cSrcweir /*
422cdf0e10cSrcweir         // letzte Element auf Vaterseite
423cdf0e10cSrcweir         // -> zusammenlegen mit vorletzter Seite
424cdf0e10cSrcweir         if (nParentNodePos == (aParent->Count() - 1))
425cdf0e10cSrcweir         {
426cdf0e10cSrcweir             if (!nParentNodePos)
427cdf0e10cSrcweir             // zusammenlegen mit linken nachbarn
428cdf0e10cSrcweir                 Merge(nParentNodePos,aParent->GetChild(&rIndex));
429cdf0e10cSrcweir             else
430cdf0e10cSrcweir                 Merge(nParentNodePos,(*aParent)[nParentNodePos-1].GetChild(&rIndex,aParent));
431cdf0e10cSrcweir         }
432cdf0e10cSrcweir         // sonst Seite mit naechster Seite zusammenlegen
433cdf0e10cSrcweir         else if(nParentNodePos != NODE_NOTFOUND)
434cdf0e10cSrcweir         {
435cdf0e10cSrcweir             // zusammenlegen mit rechten nachbarn
436cdf0e10cSrcweir             Merge(nParentNodePos + 1,((*aParent)[nParentNodePos + 1].GetChild(&rIndex,aParent)));
437cdf0e10cSrcweir             nParentNodePos++;
438cdf0e10cSrcweir         }
439cdf0e10cSrcweir         else // Sonderbehandlung
440cdf0e10cSrcweir         {
441cdf0e10cSrcweir             // Page ist aChild Page vom Parent => erste Page aus ppNodes an aChild anhaengen
442cdf0e10cSrcweir             Merge(0,(*aParent)[0].GetChild(&rIndex,aParent));
443cdf0e10cSrcweir             nParentNodePos = 0;
444cdf0e10cSrcweir         }
445cdf0e10cSrcweir 
446cdf0e10cSrcweir         if (HasParent() && !(*aParent)[nParentNodePos].HasChild())
447cdf0e10cSrcweir             aParent->Delete(nParentNodePos);
448cdf0e10cSrcweir */
449cdf0e10cSrcweir 
450cdf0e10cSrcweir     }
451cdf0e10cSrcweir     else if (IsRoot())
452cdf0e10cSrcweir         // Sicherstellen das die Position der Wurzel festgehalten wird
453cdf0e10cSrcweir         rIndex.SetRootPos(nPagePos);
454cdf0e10cSrcweir     return sal_True;
455cdf0e10cSrcweir }
456cdf0e10cSrcweir 
457cdf0e10cSrcweir 
458cdf0e10cSrcweir //------------------------------------------------------------------
Split(ONDXPage & rPage)459cdf0e10cSrcweir ONDXNode ONDXPage::Split(ONDXPage& rPage)
460cdf0e10cSrcweir {
461cdf0e10cSrcweir     DBG_ASSERT(IsFull(), "Falsches Splitting");
462cdf0e10cSrcweir     /*  Aufteilen einer Seite auf zwei
463cdf0e10cSrcweir         Blatt:
464cdf0e10cSrcweir             Seite 1 behaelt (n - (n/2))
465cdf0e10cSrcweir             Seite 2 erhaelt (n/2)
466cdf0e10cSrcweir             Knoten n/2 wird dupliziert
467cdf0e10cSrcweir         Innerer Knoten:
468cdf0e10cSrcweir             Seite 1 behaelt (n+1)/2
469cdf0e10cSrcweir             Seite 2 erhaelt (n/2-1)
470cdf0e10cSrcweir             Knoten ((n+1)/2 + 1) : wird herausgenommen
471cdf0e10cSrcweir     */
472cdf0e10cSrcweir     ONDXNode aResultNode;
473cdf0e10cSrcweir     if (IsLeaf())
474cdf0e10cSrcweir     {
475cdf0e10cSrcweir         for (sal_uInt16 i = (nCount - (nCount / 2)), j = 0 ; i < nCount; i++)
476cdf0e10cSrcweir             rPage.Insert(j++,(*this)[i]);
477cdf0e10cSrcweir 
478cdf0e10cSrcweir         // dieser Knoten enthaelt einen Schluessel der noch einmal im Tree vorkommt
479cdf0e10cSrcweir         // und ersetzt werden muss
480cdf0e10cSrcweir         ONDXNode aLastNode = (*this)[nCount - 1];
481cdf0e10cSrcweir         nCount = nCount - (nCount / 2);
482cdf0e10cSrcweir         aResultNode = (*this)[nCount - 1];
483cdf0e10cSrcweir 
484cdf0e10cSrcweir         if (HasParent())
485cdf0e10cSrcweir             aParent->SearchAndReplace(aLastNode.GetKey(),
486cdf0e10cSrcweir                                       aResultNode.GetKey());
487cdf0e10cSrcweir     }
488cdf0e10cSrcweir     else
489cdf0e10cSrcweir     {
490cdf0e10cSrcweir         for (sal_uInt16 i = (nCount + 1) / 2 + 1, j = 0 ; i < nCount; i++)
491cdf0e10cSrcweir             rPage.Insert(j++,(*this)[i]);
492cdf0e10cSrcweir 
493cdf0e10cSrcweir         aResultNode = (*this)[(nCount + 1) / 2];
494cdf0e10cSrcweir         nCount = (nCount + 1) / 2;
495cdf0e10cSrcweir 
496cdf0e10cSrcweir         // neue Seite zeigt nun auf Seite des herausgeloesten Knoten
497cdf0e10cSrcweir         rPage.SetChild(aResultNode.GetChild());
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir     // Knoten zeigt auf neue Seite
500cdf0e10cSrcweir     aResultNode.SetChild(&rPage);
501cdf0e10cSrcweir 
502cdf0e10cSrcweir     // innere Knoten haben keine Recordnummer
503cdf0e10cSrcweir     if (rIndex.isUnique())
504cdf0e10cSrcweir         aResultNode.GetKey().ResetRecord();
505cdf0e10cSrcweir     bModified = sal_True;
506cdf0e10cSrcweir     return aResultNode;
507cdf0e10cSrcweir }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir //------------------------------------------------------------------
Merge(sal_uInt16 nParentNodePos,ONDXPagePtr xPage)510cdf0e10cSrcweir void ONDXPage::Merge(sal_uInt16 nParentNodePos, ONDXPagePtr xPage)
511cdf0e10cSrcweir {
512cdf0e10cSrcweir     DBG_ASSERT(HasParent(), "kein Vater vorhanden");
513cdf0e10cSrcweir     DBG_ASSERT(nParentNodePos != NODE_NOTFOUND, "Falscher Indexaufbau");
514cdf0e10cSrcweir 
515cdf0e10cSrcweir     /*  Zusammenlegen zweier Seiten */
516cdf0e10cSrcweir     ONDXNode aResultNode;
517cdf0e10cSrcweir     sal_uInt16 nMaxNodes = rIndex.GetMaxNodes(),
518cdf0e10cSrcweir            nMaxNodes_2 = nMaxNodes / 2;
519cdf0e10cSrcweir 
520cdf0e10cSrcweir     // Feststellen ob Seite rechter oder linker Nachbar
521cdf0e10cSrcweir     sal_Bool    bRight    = ((*xPage)[0].GetKey() > (*this)[0].GetKey()); // sal_True, wenn xPage die rechte Seite ist
522cdf0e10cSrcweir     sal_uInt16  nNewCount = (*xPage).Count() + Count();
523cdf0e10cSrcweir 
524cdf0e10cSrcweir     if (IsLeaf())
525cdf0e10cSrcweir     {
526cdf0e10cSrcweir         // Bedingung fuers zusammenlegen
527cdf0e10cSrcweir         if (nNewCount < (nMaxNodes_2 * 2))
528cdf0e10cSrcweir         {
529cdf0e10cSrcweir             sal_uInt16 nLastNode = bRight ? Count() - 1 : xPage->Count() - 1;
530cdf0e10cSrcweir             if (bRight)
531cdf0e10cSrcweir             {
532cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
533cdf0e10cSrcweir                 // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
534cdf0e10cSrcweir                 while (xPage->Count())
535cdf0e10cSrcweir                 {
536cdf0e10cSrcweir                     Append((*xPage)[0]);
537cdf0e10cSrcweir                     xPage->Remove(0);
538cdf0e10cSrcweir                 }
539cdf0e10cSrcweir             }
540cdf0e10cSrcweir             else
541cdf0e10cSrcweir             {
542cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
543cdf0e10cSrcweir                 // xPage ist die linke Page und THIS die rechte
544cdf0e10cSrcweir                 while (xPage->Count())
545cdf0e10cSrcweir                 {
546cdf0e10cSrcweir                     Insert(0,(*xPage)[xPage->Count()-1]);
547cdf0e10cSrcweir                     xPage->Remove(xPage->Count()-1);
548cdf0e10cSrcweir                 }
549cdf0e10cSrcweir                 // alte Position von xPage beim Parent mit this ersetzen
550cdf0e10cSrcweir                 if (nParentNodePos)
551cdf0e10cSrcweir                     (*aParent)[nParentNodePos-1].SetChild(this,aParent);
552cdf0e10cSrcweir                 else // oder als rechten Knoten setzen
553cdf0e10cSrcweir                     aParent->SetChild(this);
554cdf0e10cSrcweir                 aParent->SetModified(sal_True);
555cdf0e10cSrcweir 
556cdf0e10cSrcweir             }
557cdf0e10cSrcweir 
558cdf0e10cSrcweir             // Child beziehung beim Vaterknoten aufheben
559cdf0e10cSrcweir             (*aParent)[nParentNodePos].SetChild();
560cdf0e10cSrcweir             // Austauschen des KnotenWertes, nur wenn geaenderte Page
561cdf0e10cSrcweir             // die linke ist, ansonsten werde
562cdf0e10cSrcweir 
563cdf0e10cSrcweir             if(aParent->IsRoot() && aParent->Count() == 1)
564cdf0e10cSrcweir             {
565cdf0e10cSrcweir                 (*aParent)[0].SetChild();
566cdf0e10cSrcweir                 aParent->ReleaseFull();
567cdf0e10cSrcweir                 aParent = NULL;
568cdf0e10cSrcweir                 rIndex.SetRootPos(nPagePos);
569cdf0e10cSrcweir                 rIndex.m_aRoot = this;
570cdf0e10cSrcweir                 SetModified(sal_True);
571cdf0e10cSrcweir             }
572cdf0e10cSrcweir             else
573cdf0e10cSrcweir                 aParent->SearchAndReplace((*this)[nLastNode].GetKey(),(*this)[nCount-1].GetKey());
574cdf0e10cSrcweir 
575cdf0e10cSrcweir             xPage->SetModified(sal_False);
576cdf0e10cSrcweir             xPage->ReleaseFull(); // wird nicht mehr benoetigt
577cdf0e10cSrcweir         }
578cdf0e10cSrcweir         // Ausgleichen der Elemente   nNewCount >= (nMaxNodes_2 * 2)
579cdf0e10cSrcweir         else
580cdf0e10cSrcweir         {
581cdf0e10cSrcweir             if (bRight)
582cdf0e10cSrcweir             {
583cdf0e10cSrcweir                 // alle Knoten aus xPage auf den linken Knoten verschieben (anhaengen)
584cdf0e10cSrcweir                 ONDXNode aReplaceNode = (*this)[nCount - 1];
585cdf0e10cSrcweir                 while (nCount < nMaxNodes_2)
586cdf0e10cSrcweir                 {
587cdf0e10cSrcweir                     Append((*xPage)[0]);
588cdf0e10cSrcweir                     xPage->Remove(0);
589cdf0e10cSrcweir                 }
590cdf0e10cSrcweir                 // Austauschen des KnotenWertes: Setzt alten letzten Wert durch den letzten von xPage
591cdf0e10cSrcweir                 aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[nCount-1].GetKey());
592cdf0e10cSrcweir             }
593cdf0e10cSrcweir             else
594cdf0e10cSrcweir             {
595cdf0e10cSrcweir                 // alle Knoten aus this vor die xPage Knoten einfuegen
596cdf0e10cSrcweir                 ONDXNode aReplaceNode = (*this)[nCount - 1];
597cdf0e10cSrcweir                 while (xPage->Count() < nMaxNodes_2)
598cdf0e10cSrcweir                 {
599cdf0e10cSrcweir                     xPage->Insert(0,(*this)[nCount-1]);
600cdf0e10cSrcweir                     Remove(nCount-1);
601cdf0e10cSrcweir                 }
602cdf0e10cSrcweir                 // Austauschen des KnotenWertes
603cdf0e10cSrcweir                 aParent->SearchAndReplace(aReplaceNode.GetKey(),(*this)[Count()-1].GetKey());
604cdf0e10cSrcweir             }
605cdf0e10cSrcweir         }
606cdf0e10cSrcweir     }
607cdf0e10cSrcweir     else // !IsLeaf()
608cdf0e10cSrcweir     {
609cdf0e10cSrcweir         // Bedingung fuers zusammenlegen
610cdf0e10cSrcweir         if (nNewCount < nMaxNodes_2 * 2)
611cdf0e10cSrcweir         {
612cdf0e10cSrcweir             if (bRight)
613cdf0e10cSrcweir             {
614cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
615cdf0e10cSrcweir                 // Vaterknoten wird mit integriert
616cdf0e10cSrcweir                 // erhaelt zunaechst Child von xPage
617cdf0e10cSrcweir                 (*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
618cdf0e10cSrcweir                 Append((*aParent)[nParentNodePos]);
619cdf0e10cSrcweir                 for (sal_uInt16 i = 0 ; i < xPage->Count(); i++)
620cdf0e10cSrcweir                     Append((*xPage)[i]);
621cdf0e10cSrcweir             }
622cdf0e10cSrcweir             else
623cdf0e10cSrcweir             {
624cdf0e10cSrcweir                 DBG_ASSERT(&xPage != this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
625cdf0e10cSrcweir                 // Vaterknoten wird mit integriert
626cdf0e10cSrcweir                 // erhaelt zunaechst Child
627cdf0e10cSrcweir                 (*aParent)[nParentNodePos].SetChild(GetChild(),aParent); // Parent merkt sich mein Child
628cdf0e10cSrcweir                 Insert(0,(*aParent)[nParentNodePos]); // Node vom Parent bei mir einfuegen
629cdf0e10cSrcweir                 while (xPage->Count())
630cdf0e10cSrcweir                 {
631cdf0e10cSrcweir                     Insert(0,(*xPage)[xPage->Count()-1]);
632cdf0e10cSrcweir                     xPage->Remove(xPage->Count()-1);
633cdf0e10cSrcweir                 }
634cdf0e10cSrcweir                 SetChild(xPage->GetChild());
635cdf0e10cSrcweir 
636cdf0e10cSrcweir                 if (nParentNodePos)
637cdf0e10cSrcweir                     (*aParent)[nParentNodePos-1].SetChild(this,aParent);
638cdf0e10cSrcweir                 else
639cdf0e10cSrcweir                     aParent->SetChild(this);
640cdf0e10cSrcweir             }
641cdf0e10cSrcweir 
642cdf0e10cSrcweir             // danach wird der Vaterknoten zurueckgesetzt
643cdf0e10cSrcweir             (*aParent)[nParentNodePos].SetChild();
644cdf0e10cSrcweir             aParent->SetModified(sal_True);
645cdf0e10cSrcweir 
646cdf0e10cSrcweir             if(aParent->IsRoot() && aParent->Count() == 1)
647cdf0e10cSrcweir             {
648cdf0e10cSrcweir                 (*aParent).SetChild();
649cdf0e10cSrcweir                 aParent->ReleaseFull();
650cdf0e10cSrcweir                 aParent = NULL;
651cdf0e10cSrcweir                 rIndex.SetRootPos(nPagePos);
652cdf0e10cSrcweir                 rIndex.m_aRoot = this;
653cdf0e10cSrcweir                 SetModified(sal_True);
654cdf0e10cSrcweir             }
655cdf0e10cSrcweir             else if(nParentNodePos)
656cdf0e10cSrcweir                 // Austauschen des KnotenWertes
657cdf0e10cSrcweir                 // beim Append wird der Bereich erweitert, beim INsert verweist der alte Knoten von xPage auf this
658cdf0e10cSrcweir                 // deshalb muss der Knoten auch hier aktualisiert werden
659cdf0e10cSrcweir                 aParent->SearchAndReplace((*aParent)[nParentNodePos-1].GetKey(),(*aParent)[nParentNodePos].GetKey());
660cdf0e10cSrcweir 
661cdf0e10cSrcweir             xPage->SetModified(sal_False);
662cdf0e10cSrcweir             xPage->ReleaseFull();
663cdf0e10cSrcweir         }
664cdf0e10cSrcweir         // Ausgleichen der Elemente
665cdf0e10cSrcweir         else
666cdf0e10cSrcweir         {
667cdf0e10cSrcweir             if (bRight)
668cdf0e10cSrcweir             {
669cdf0e10cSrcweir                 while (nCount < nMaxNodes_2)
670cdf0e10cSrcweir                 {
671cdf0e10cSrcweir                     (*aParent)[nParentNodePos].SetChild(xPage->GetChild(),aParent);
672cdf0e10cSrcweir                     Append((*aParent)[nParentNodePos]);
673cdf0e10cSrcweir                     (*aParent)[nParentNodePos] = (*xPage)[0];
674cdf0e10cSrcweir                     xPage->Remove(0);
675cdf0e10cSrcweir                 }
676cdf0e10cSrcweir                 xPage->SetChild((*aParent)[nParentNodePos].GetChild());
677cdf0e10cSrcweir                 (*aParent)[nParentNodePos].SetChild(xPage,aParent);
678cdf0e10cSrcweir             }
679cdf0e10cSrcweir             else
680cdf0e10cSrcweir             {
681cdf0e10cSrcweir                 while (nCount < nMaxNodes_2)
682cdf0e10cSrcweir                 {
683cdf0e10cSrcweir                     (*aParent)[nParentNodePos].SetChild(GetChild(),aParent);
684cdf0e10cSrcweir                     Insert(0,(*aParent)[nParentNodePos]);
685cdf0e10cSrcweir                     (*aParent)[nParentNodePos] = (*xPage)[xPage->Count()-1];
686cdf0e10cSrcweir                     xPage->Remove(xPage->Count()-1);
687cdf0e10cSrcweir                 }
688cdf0e10cSrcweir                 SetChild((*aParent)[nParentNodePos].GetChild());
689cdf0e10cSrcweir                 (*aParent)[nParentNodePos].SetChild(this,aParent);
690cdf0e10cSrcweir 
691cdf0e10cSrcweir             }
692cdf0e10cSrcweir             aParent->SetModified(sal_True);
693cdf0e10cSrcweir         }
694cdf0e10cSrcweir     }
695cdf0e10cSrcweir }
696cdf0e10cSrcweir //==================================================================
697cdf0e10cSrcweir // ONDXNode
698cdf0e10cSrcweir //==================================================================
699cdf0e10cSrcweir 
700cdf0e10cSrcweir //------------------------------------------------------------------
Read(SvStream & rStream,ODbaseIndex & rIndex)701cdf0e10cSrcweir void ONDXNode::Read(SvStream &rStream, ODbaseIndex& rIndex)
702cdf0e10cSrcweir {
703cdf0e10cSrcweir     rStream >> aKey.nRecord; // schluessel
704cdf0e10cSrcweir 
705cdf0e10cSrcweir     if (rIndex.getHeader().db_keytype)
706cdf0e10cSrcweir     {
707cdf0e10cSrcweir         double aDbl;
708cdf0e10cSrcweir         rStream >> aDbl;
709cdf0e10cSrcweir         aKey = ONDXKey(aDbl,aKey.nRecord);
710cdf0e10cSrcweir     }
711cdf0e10cSrcweir     else
712cdf0e10cSrcweir     {
713cdf0e10cSrcweir         ByteString aBuf;
714cdf0e10cSrcweir         sal_uInt16 nLen = rIndex.getHeader().db_keylen;
715cdf0e10cSrcweir         char* pStr = aBuf.AllocBuffer(nLen+1);
716cdf0e10cSrcweir 
717cdf0e10cSrcweir         rStream.Read(pStr,nLen);
718cdf0e10cSrcweir         pStr[nLen] = 0;
719cdf0e10cSrcweir         aBuf.ReleaseBufferAccess();
720cdf0e10cSrcweir         aBuf.EraseTrailingChars();
721cdf0e10cSrcweir 
722cdf0e10cSrcweir         //  aKey = ONDXKey((aBuf,rIndex.GetDBFConnection()->GetCharacterSet()) ,aKey.nRecord);
723cdf0e10cSrcweir         aKey = ONDXKey(::rtl::OUString(aBuf.GetBuffer(),aBuf.Len(),rIndex.m_pTable->getConnection()->getTextEncoding()) ,aKey.nRecord);
724cdf0e10cSrcweir     }
725cdf0e10cSrcweir     rStream >> aChild;
726cdf0e10cSrcweir }
727cdf0e10cSrcweir 
728cdf0e10cSrcweir union NodeData
729cdf0e10cSrcweir {
730cdf0e10cSrcweir     double aDbl;
731cdf0e10cSrcweir     char   aData[128];
732cdf0e10cSrcweir } aNodeData;
733cdf0e10cSrcweir //------------------------------------------------------------------
Write(SvStream & rStream,const ONDXPage & rPage) const734cdf0e10cSrcweir void ONDXNode::Write(SvStream &rStream, const ONDXPage& rPage) const
735cdf0e10cSrcweir {
736cdf0e10cSrcweir     const ODbaseIndex& rIndex = rPage.GetIndex();
737cdf0e10cSrcweir     if (!rIndex.isUnique() || rPage.IsLeaf())
738cdf0e10cSrcweir         rStream << (sal_uInt32)aKey.nRecord; // schluessel
739cdf0e10cSrcweir     else
740cdf0e10cSrcweir         rStream << (sal_uInt32)0;   // schluessel
741cdf0e10cSrcweir 
742cdf0e10cSrcweir     if (rIndex.getHeader().db_keytype) // double
743cdf0e10cSrcweir     {
744cdf0e10cSrcweir         if (aKey.getValue().isNull())
745cdf0e10cSrcweir         {
746cdf0e10cSrcweir             memset(aNodeData.aData,0,rIndex.getHeader().db_keylen);
747cdf0e10cSrcweir             rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
748cdf0e10cSrcweir         }
749cdf0e10cSrcweir         else
750cdf0e10cSrcweir             rStream << (double) aKey.getValue();
751cdf0e10cSrcweir     }
752cdf0e10cSrcweir     else
753cdf0e10cSrcweir     {
754cdf0e10cSrcweir         memset(aNodeData.aData,0x20,rIndex.getHeader().db_keylen);
755cdf0e10cSrcweir         if (!aKey.getValue().isNull())
756cdf0e10cSrcweir         {
757cdf0e10cSrcweir             ::rtl::OUString sValue = aKey.getValue();
758cdf0e10cSrcweir             ByteString aText(sValue.getStr(), rIndex.m_pTable->getConnection()->getTextEncoding());
759cdf0e10cSrcweir             strncpy(aNodeData.aData,aText.GetBuffer(),std::min(rIndex.getHeader().db_keylen, aText.Len()));
760cdf0e10cSrcweir         }
761cdf0e10cSrcweir         rStream.Write((sal_uInt8*)aNodeData.aData,rIndex.getHeader().db_keylen);
762cdf0e10cSrcweir     }
763cdf0e10cSrcweir     rStream << aChild;
764cdf0e10cSrcweir }
765cdf0e10cSrcweir 
766cdf0e10cSrcweir 
767cdf0e10cSrcweir //------------------------------------------------------------------
GetChild(ODbaseIndex * pIndex,ONDXPage * pParent)768cdf0e10cSrcweir ONDXPagePtr& ONDXNode::GetChild(ODbaseIndex* pIndex, ONDXPage* pParent)
769cdf0e10cSrcweir {
770cdf0e10cSrcweir     if (!aChild.Is() && pIndex)
771cdf0e10cSrcweir     {
772cdf0e10cSrcweir         aChild = pIndex->CreatePage(aChild.GetPagePos(),pParent,aChild.HasPage());
773cdf0e10cSrcweir     }
774cdf0e10cSrcweir     return aChild;
775cdf0e10cSrcweir }
776cdf0e10cSrcweir 
777cdf0e10cSrcweir //==================================================================
778cdf0e10cSrcweir // ONDXKey
779cdf0e10cSrcweir //==================================================================
780cdf0e10cSrcweir //------------------------------------------------------------------
IsText(sal_Int32 eType)781cdf0e10cSrcweir sal_Bool ONDXKey::IsText(sal_Int32 eType)
782cdf0e10cSrcweir {
783cdf0e10cSrcweir     return eType == DataType::VARCHAR || eType == DataType::CHAR;
784cdf0e10cSrcweir }
785cdf0e10cSrcweir 
786cdf0e10cSrcweir //------------------------------------------------------------------
Compare(const ONDXKey & rKey) const787cdf0e10cSrcweir StringCompare ONDXKey::Compare(const ONDXKey& rKey) const
788cdf0e10cSrcweir {
789cdf0e10cSrcweir     //  DBG_ASSERT(is(), "Falscher Indexzugriff");
790cdf0e10cSrcweir     StringCompare eResult;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir     if (getValue().isNull())
793cdf0e10cSrcweir     {
794cdf0e10cSrcweir         if (rKey.getValue().isNull() || (rKey.IsText(getDBType()) && !rKey.getValue().getString().getLength()))
795cdf0e10cSrcweir             eResult = COMPARE_EQUAL;
796cdf0e10cSrcweir         else
797cdf0e10cSrcweir             eResult = COMPARE_LESS;
798cdf0e10cSrcweir     }
799cdf0e10cSrcweir     else if (rKey.getValue().isNull())
800cdf0e10cSrcweir     {
801cdf0e10cSrcweir         if (getValue().isNull() || (IsText(getDBType()) && !getValue().getString().getLength()))
802cdf0e10cSrcweir             eResult = COMPARE_EQUAL;
803cdf0e10cSrcweir         else
804cdf0e10cSrcweir             eResult = COMPARE_GREATER;
805cdf0e10cSrcweir     }
806cdf0e10cSrcweir     else if (IsText(getDBType()))
807cdf0e10cSrcweir     {
808cdf0e10cSrcweir         sal_Int32 nRes = getValue().getString().compareTo(rKey.getValue());
809cdf0e10cSrcweir         eResult = (nRes > 0) ? COMPARE_GREATER : (nRes == 0) ? COMPARE_EQUAL : COMPARE_LESS;
810cdf0e10cSrcweir     }
811cdf0e10cSrcweir     else
812cdf0e10cSrcweir     {
813cdf0e10cSrcweir         double m = getValue(),n = rKey.getValue();
814cdf0e10cSrcweir         eResult = (m > n) ? COMPARE_GREATER : (n == m) ? COMPARE_EQUAL : COMPARE_LESS;
815cdf0e10cSrcweir     }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir     // Record vergleich, wenn Index !Unique
818cdf0e10cSrcweir     if (eResult == COMPARE_EQUAL && nRecord && rKey.nRecord)
819cdf0e10cSrcweir         eResult = (nRecord > rKey.nRecord) ? COMPARE_GREATER :
820cdf0e10cSrcweir                   (nRecord == rKey.nRecord) ? COMPARE_EQUAL : COMPARE_LESS;
821cdf0e10cSrcweir 
822cdf0e10cSrcweir     return eResult;
823cdf0e10cSrcweir }
824cdf0e10cSrcweir // -----------------------------------------------------------------------------
setValue(const ORowSetValue & _rVal)825cdf0e10cSrcweir void ONDXKey::setValue(const ORowSetValue& _rVal)
826cdf0e10cSrcweir {
827cdf0e10cSrcweir     xValue = _rVal;
828cdf0e10cSrcweir }
829cdf0e10cSrcweir // -----------------------------------------------------------------------------
getValue() const830cdf0e10cSrcweir const ORowSetValue& ONDXKey::getValue() const
831cdf0e10cSrcweir {
832cdf0e10cSrcweir     return xValue;
833cdf0e10cSrcweir }
834cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator >>(SvStream & rStream,ONDXPagePtr & rPage)835cdf0e10cSrcweir SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPagePtr& rPage)
836cdf0e10cSrcweir {
837cdf0e10cSrcweir     rStream >> rPage.nPagePos;
838cdf0e10cSrcweir     return rStream;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator <<(SvStream & rStream,const ONDXPagePtr & rPage)841cdf0e10cSrcweir SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPagePtr& rPage)
842cdf0e10cSrcweir {
843cdf0e10cSrcweir     rStream << rPage.nPagePos;
844cdf0e10cSrcweir     return rStream;
845cdf0e10cSrcweir }
846cdf0e10cSrcweir // -----------------------------------------------------------------------------
847cdf0e10cSrcweir //==================================================================
848cdf0e10cSrcweir // ONDXPagePtr
849cdf0e10cSrcweir //==================================================================
850cdf0e10cSrcweir //------------------------------------------------------------------
ONDXPagePtr(const ONDXPagePtr & rRef)851cdf0e10cSrcweir ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr& rRef)
852cdf0e10cSrcweir               :ONDXPageRef(rRef)
853cdf0e10cSrcweir               ,nPagePos(rRef.nPagePos)
854cdf0e10cSrcweir {
855cdf0e10cSrcweir }
856cdf0e10cSrcweir 
857cdf0e10cSrcweir //------------------------------------------------------------------
ONDXPagePtr(ONDXPage * pRefPage)858cdf0e10cSrcweir ONDXPagePtr::ONDXPagePtr(ONDXPage* pRefPage)
859cdf0e10cSrcweir               :ONDXPageRef(pRefPage)
860cdf0e10cSrcweir               ,nPagePos(0)
861cdf0e10cSrcweir {
862cdf0e10cSrcweir     if (pRefPage)
863cdf0e10cSrcweir         nPagePos = pRefPage->GetPagePos();
864cdf0e10cSrcweir }
865cdf0e10cSrcweir //------------------------------------------------------------------
operator =(const ONDXPagePtr & rRef)866cdf0e10cSrcweir ONDXPagePtr& ONDXPagePtr::operator=(const ONDXPagePtr& rRef)
867cdf0e10cSrcweir {
868cdf0e10cSrcweir     ONDXPageRef::operator=(rRef);
869cdf0e10cSrcweir     nPagePos = rRef.nPagePos;
870cdf0e10cSrcweir     return *this;
871cdf0e10cSrcweir }
872cdf0e10cSrcweir 
873cdf0e10cSrcweir //------------------------------------------------------------------
operator =(ONDXPage * pRef)874cdf0e10cSrcweir ONDXPagePtr& ONDXPagePtr::operator= (ONDXPage* pRef)
875cdf0e10cSrcweir {
876cdf0e10cSrcweir     ONDXPageRef::operator=(pRef);
877cdf0e10cSrcweir     nPagePos = (pRef) ? pRef->GetPagePos() : 0;
878cdf0e10cSrcweir     return *this;
879cdf0e10cSrcweir }
880cdf0e10cSrcweir // -----------------------------------------------------------------------------
881cdf0e10cSrcweir static sal_uInt32 nValue;
882cdf0e10cSrcweir //------------------------------------------------------------------
operator >>(SvStream & rStream,ONDXPage & rPage)883cdf0e10cSrcweir SvStream& connectivity::dbase::operator >> (SvStream &rStream, ONDXPage& rPage)
884cdf0e10cSrcweir {
885cdf0e10cSrcweir     rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
886cdf0e10cSrcweir     rStream >> nValue >> rPage.aChild;
887cdf0e10cSrcweir     rPage.nCount = sal_uInt16(nValue);
888cdf0e10cSrcweir 
889cdf0e10cSrcweir //  DBG_ASSERT(rPage.nCount && rPage.nCount < rPage.GetIndex().GetMaxNodes(), "Falscher Count");
890cdf0e10cSrcweir     for (sal_uInt16 i = 0; i < rPage.nCount; i++)
891cdf0e10cSrcweir         rPage[i].Read(rStream, rPage.GetIndex());
892cdf0e10cSrcweir     return rStream;
893cdf0e10cSrcweir }
894cdf0e10cSrcweir 
895cdf0e10cSrcweir //------------------------------------------------------------------
operator <<(SvStream & rStream,const ONDXPage & rPage)896cdf0e10cSrcweir SvStream& connectivity::dbase::operator << (SvStream &rStream, const ONDXPage& rPage)
897cdf0e10cSrcweir {
898cdf0e10cSrcweir     // Seite existiert noch nicht
899cdf0e10cSrcweir     sal_uIntPtr nSize = (rPage.GetPagePos() + 1) * PAGE_SIZE;
900cdf0e10cSrcweir     if (nSize > rStream.Seek(STREAM_SEEK_TO_END))
901cdf0e10cSrcweir     {
902cdf0e10cSrcweir         rStream.SetStreamSize(nSize);
903cdf0e10cSrcweir         rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
904cdf0e10cSrcweir 
905cdf0e10cSrcweir         char aEmptyData[PAGE_SIZE];
906cdf0e10cSrcweir         memset(aEmptyData,0x00,PAGE_SIZE);
907cdf0e10cSrcweir         rStream.Write((sal_uInt8*)aEmptyData,PAGE_SIZE);
908cdf0e10cSrcweir     }
909cdf0e10cSrcweir     sal_uIntPtr nCurrentPos = rStream.Seek(rPage.GetPagePos() * PAGE_SIZE);
910cdf0e10cSrcweir     OSL_UNUSED( nCurrentPos );
911cdf0e10cSrcweir 
912cdf0e10cSrcweir     nValue = rPage.nCount;
913cdf0e10cSrcweir     rStream << nValue << rPage.aChild;
914cdf0e10cSrcweir 
915cdf0e10cSrcweir     sal_uInt16 i = 0;
916cdf0e10cSrcweir     for (; i < rPage.nCount; i++)
917cdf0e10cSrcweir         rPage[i].Write(rStream, rPage);
918cdf0e10cSrcweir 
919cdf0e10cSrcweir     // check if we have to fill the stream with '\0'
920cdf0e10cSrcweir     if(i < rPage.rIndex.getHeader().db_maxkeys)
921cdf0e10cSrcweir     {
922cdf0e10cSrcweir         sal_uIntPtr nTell = rStream.Tell() % PAGE_SIZE;
923cdf0e10cSrcweir         sal_uInt16 nBufferSize = rStream.GetBufferSize();
924cdf0e10cSrcweir         sal_uIntPtr nRemainSize = nBufferSize - nTell;
925cdf0e10cSrcweir         if ( nRemainSize <= nBufferSize )
926cdf0e10cSrcweir         {
927cdf0e10cSrcweir             char* pEmptyData = new char[nRemainSize];
928cdf0e10cSrcweir             memset(pEmptyData,0x00,nRemainSize);
929cdf0e10cSrcweir             rStream.Write((sal_uInt8*)pEmptyData,nRemainSize);
930cdf0e10cSrcweir             rStream.Seek(nTell);
931cdf0e10cSrcweir             delete [] pEmptyData;
932cdf0e10cSrcweir         }
933cdf0e10cSrcweir     }
934cdf0e10cSrcweir     return rStream;
935cdf0e10cSrcweir }
936cdf0e10cSrcweir // -----------------------------------------------------------------------------
937cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
938cdf0e10cSrcweir //------------------------------------------------------------------
PrintPage()939cdf0e10cSrcweir void ONDXPage::PrintPage()
940cdf0e10cSrcweir {
941cdf0e10cSrcweir     DBG_TRACE4("\nSDB: -----------Page: %d  Parent: %d  Count: %d  Child: %d-----",
942cdf0e10cSrcweir         nPagePos, HasParent() ? aParent->GetPagePos() : 0 ,nCount, aChild.GetPagePos());
943cdf0e10cSrcweir 
944cdf0e10cSrcweir     for (sal_uInt16 i = 0; i < nCount; i++)
945cdf0e10cSrcweir     {
946cdf0e10cSrcweir         ONDXNode rNode = (*this)[i];
947cdf0e10cSrcweir         ONDXKey&  rKey = rNode.GetKey();
948cdf0e10cSrcweir         if (!IsLeaf())
949cdf0e10cSrcweir             rNode.GetChild(&rIndex, this);
950cdf0e10cSrcweir 
951cdf0e10cSrcweir         if (rKey.getValue().isNull())
952cdf0e10cSrcweir         {
953cdf0e10cSrcweir             DBG_TRACE2("SDB: [%d,NULL,%d]",rKey.GetRecord(), rNode.GetChild().GetPagePos());
954cdf0e10cSrcweir         }
955cdf0e10cSrcweir         else if (rIndex.getHeader().db_keytype)
956cdf0e10cSrcweir         {
957cdf0e10cSrcweir             DBG_TRACE3("SDB: [%d,%f,%d]",rKey.GetRecord(), rKey.getValue().getDouble(),rNode.GetChild().GetPagePos());
958cdf0e10cSrcweir         }
959cdf0e10cSrcweir         else
960cdf0e10cSrcweir         {
961cdf0e10cSrcweir             DBG_TRACE3("SDB: [%d,%s,%d]",rKey.GetRecord(), (const char* )ByteString(rKey.getValue().getString().getStr(), rIndex.m_pTable->getConnection()->getTextEncoding()).GetBuffer(),rNode.GetChild().GetPagePos());
962cdf0e10cSrcweir         }
963cdf0e10cSrcweir     }
964cdf0e10cSrcweir     DBG_TRACE("SDB: -----------------------------------------------\n");
965cdf0e10cSrcweir     if (!IsLeaf())
966cdf0e10cSrcweir     {
967cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
968cdf0e10cSrcweir         GetChild(&rIndex)->PrintPage();
969cdf0e10cSrcweir         for (sal_uInt16 i = 0; i < nCount; i++)
970cdf0e10cSrcweir         {
971cdf0e10cSrcweir             ONDXNode rNode = (*this)[i];
972cdf0e10cSrcweir             rNode.GetChild(&rIndex,this)->PrintPage();
973cdf0e10cSrcweir         }
974cdf0e10cSrcweir #endif
975cdf0e10cSrcweir     }
976cdf0e10cSrcweir     DBG_TRACE("SDB: ===============================================\n");
977cdf0e10cSrcweir }
978cdf0e10cSrcweir #endif
979cdf0e10cSrcweir // -----------------------------------------------------------------------------
IsFull() const980cdf0e10cSrcweir sal_Bool ONDXPage::IsFull() const
981cdf0e10cSrcweir {
982cdf0e10cSrcweir     return Count() == rIndex.getHeader().db_maxkeys;
983cdf0e10cSrcweir }
984cdf0e10cSrcweir // -----------------------------------------------------------------------------
985cdf0e10cSrcweir //------------------------------------------------------------------
Search(const ONDXKey & rSearch)986cdf0e10cSrcweir sal_uInt16 ONDXPage::Search(const ONDXKey& rSearch)
987cdf0e10cSrcweir {
988cdf0e10cSrcweir     // binare Suche spaeter
989cdf0e10cSrcweir     sal_uInt16 i = NODE_NOTFOUND;
990cdf0e10cSrcweir     while (++i < Count())
991cdf0e10cSrcweir         if ((*this)[i].GetKey() == rSearch)
992cdf0e10cSrcweir             break;
993cdf0e10cSrcweir 
994cdf0e10cSrcweir     return (i < Count()) ? i : NODE_NOTFOUND;
995cdf0e10cSrcweir }
996cdf0e10cSrcweir 
997cdf0e10cSrcweir //------------------------------------------------------------------
Search(const ONDXPage * pPage)998cdf0e10cSrcweir sal_uInt16 ONDXPage::Search(const ONDXPage* pPage)
999cdf0e10cSrcweir {
1000cdf0e10cSrcweir     sal_uInt16 i = NODE_NOTFOUND;
1001cdf0e10cSrcweir     while (++i < Count())
1002cdf0e10cSrcweir         if (((*this)[i]).GetChild() == pPage)
1003cdf0e10cSrcweir             break;
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir     // wenn nicht gefunden, dann wird davon ausgegangen, dass die Seite selbst
1006cdf0e10cSrcweir     // auf die Page zeigt
1007cdf0e10cSrcweir     return (i < Count()) ? i : NODE_NOTFOUND;
1008cdf0e10cSrcweir }
1009cdf0e10cSrcweir // -----------------------------------------------------------------------------
1010cdf0e10cSrcweir // laeuft rekursiv
SearchAndReplace(const ONDXKey & rSearch,ONDXKey & rReplace)1011cdf0e10cSrcweir void ONDXPage::SearchAndReplace(const ONDXKey& rSearch,
1012cdf0e10cSrcweir                                   ONDXKey& rReplace)
1013cdf0e10cSrcweir {
1014cdf0e10cSrcweir     OSL_ENSURE(rSearch != rReplace,"Invalid here:rSearch == rReplace");
1015cdf0e10cSrcweir     if (rSearch != rReplace)
1016cdf0e10cSrcweir     {
1017cdf0e10cSrcweir         sal_uInt16 nPos = NODE_NOTFOUND;
1018cdf0e10cSrcweir         ONDXPage* pPage = this;
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir         while (pPage && (nPos = pPage->Search(rSearch)) == NODE_NOTFOUND)
1021cdf0e10cSrcweir             pPage = pPage->aParent;
1022cdf0e10cSrcweir 
1023cdf0e10cSrcweir         if (pPage)
1024cdf0e10cSrcweir         {
1025cdf0e10cSrcweir             (*pPage)[nPos].GetKey() = rReplace;
1026cdf0e10cSrcweir             pPage->SetModified(sal_True);
1027cdf0e10cSrcweir         }
1028cdf0e10cSrcweir     }
1029cdf0e10cSrcweir }
1030cdf0e10cSrcweir // -----------------------------------------------------------------------------
operator [](sal_uInt16 nPos)1031cdf0e10cSrcweir ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos)
1032cdf0e10cSrcweir {
1033cdf0e10cSrcweir     DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1034cdf0e10cSrcweir     return ppNodes[nPos];
1035cdf0e10cSrcweir }
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir //------------------------------------------------------------------
operator [](sal_uInt16 nPos) const1038cdf0e10cSrcweir const ONDXNode& ONDXPage::operator[] (sal_uInt16 nPos) const
1039cdf0e10cSrcweir {
1040cdf0e10cSrcweir     DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1041cdf0e10cSrcweir     return ppNodes[nPos];
1042cdf0e10cSrcweir }
1043cdf0e10cSrcweir // -----------------------------------------------------------------------------
Remove(sal_uInt16 nPos)1044cdf0e10cSrcweir void ONDXPage::Remove(sal_uInt16 nPos)
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir     DBG_ASSERT(nCount > nPos, "falscher Indexzugriff");
1047cdf0e10cSrcweir 
1048cdf0e10cSrcweir     for (sal_uInt16 i = nPos; i < (nCount-1); i++)
1049cdf0e10cSrcweir         (*this)[i] = (*this)[i+1];
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir     nCount--;
1052cdf0e10cSrcweir     bModified = sal_True;
1053cdf0e10cSrcweir }
1054cdf0e10cSrcweir // -----------------------------------------------------------------------------
1055