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
10*9b5730f6SAndrew Rist *
11*9b5730f6SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*9b5730f6SAndrew Rist *
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.
19*9b5730f6SAndrew Rist *
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 // -----------------------------------------------------------------------------
1055cdf0e10cSrcweir
1056