1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include "dbase/dindexnode.hxx"
30 #include "connectivity/CommonTools.hxx"
31 #include <osl/thread.h>
32 #include "dbase/DIndex.hxx"
33 #include <tools/debug.hxx>
34 #include "diagnose_ex.h"
37 #include <boost/scoped_array.hpp>
40 using namespace connectivity
;
41 using namespace connectivity::dbase
;
42 using namespace connectivity::file
;
43 using namespace com::sun::star::sdbc
;
44 // -----------------------------------------------------------------------------
45 ONDXKey::ONDXKey(sal_uInt32 nRec
)
49 // -----------------------------------------------------------------------------
50 ONDXKey::ONDXKey(const ORowSetValue
& rVal
, sal_Int32 eType
, sal_uInt32 nRec
)
56 // -----------------------------------------------------------------------------
57 ONDXKey::ONDXKey(const rtl::OUString
& aStr
, sal_uInt32 nRec
)
58 : ONDXKey_BASE(::com::sun::star::sdbc::DataType::VARCHAR
)
64 xValue
.setBound(sal_True
);
67 // -----------------------------------------------------------------------------
69 ONDXKey::ONDXKey(double aVal
, sal_uInt32 nRec
)
70 : ONDXKey_BASE(::com::sun::star::sdbc::DataType::DOUBLE
)
75 // -----------------------------------------------------------------------------
77 //==================================================================
79 //==================================================================
80 ONDXPage::ONDXPage(ODbaseIndex
& rInd
, sal_uInt32 nPos
, ONDXPage
* pParent
)
88 sal_uInt16 nT
= rIndex
.getHeader().db_maxkeys
;
89 ppNodes
= new ONDXNode
[nT
];
92 //------------------------------------------------------------------
97 //------------------------------------------------------------------
98 void ONDXPage::QueryDelete()
100 // Store in GarbageCollector
101 if (IsModified() && rIndex
.m_pFileStream
)
102 (*rIndex
.m_pFileStream
) << *this;
104 bModified
= sal_False
;
105 if (rIndex
.UseCollector())
108 aChild
->Release(sal_False
);
110 for (sal_uInt16 i
= 0; i
< rIndex
.getHeader().db_maxkeys
;i
++)
112 if (ppNodes
[i
].GetChild().Is())
113 ppNodes
[i
].GetChild()->Release(sal_False
);
115 ppNodes
[i
] = ONDXNode();
121 rIndex
.Collect(this);
124 SvRefBase::QueryDelete();
126 //------------------------------------------------------------------
127 ONDXPagePtr
& ONDXPage::GetChild(ODbaseIndex
* pIndex
)
129 if (!aChild
.Is() && pIndex
)
131 aChild
= rIndex
.CreatePage(aChild
.GetPagePos(),this,aChild
.HasPage());
136 //------------------------------------------------------------------
137 sal_uInt16
ONDXPage::FindPos(const ONDXKey
& rKey
) const
139 // searches the position for the given key in a page
141 while (i
< nCount
&& rKey
> ((*this)[i
]).GetKey())
147 //------------------------------------------------------------------
148 sal_Bool
ONDXPage::Find(const ONDXKey
& rKey
)
150 // searches the given key
151 // Speciality: At the end of the method
152 // the actual page and the position of the node, fulfilling the '<=' condition, are saved
153 // This is considered at insert.
155 while (i
< nCount
&& rKey
> ((*this)[i
]).GetKey())
158 sal_Bool bResult
= sal_False
;
163 ONDXPagePtr aPage
= (i
==0) ? GetChild(&rIndex
) : ((*this)[i
-1]).GetChild(&rIndex
, this);
164 bResult
= aPage
.Is() && aPage
->Find(rKey
);
166 else if (i
== nCount
)
168 rIndex
.m_aCurLeaf
= this;
169 rIndex
.m_nCurNode
= i
- 1;
174 bResult
= rKey
== ((*this)[i
]).GetKey();
175 rIndex
.m_aCurLeaf
= this;
176 rIndex
.m_nCurNode
= bResult
? i
: i
- 1;
181 //------------------------------------------------------------------
182 sal_Bool
ONDXPage::Insert(ONDXNode
& rNode
, sal_uInt32 nRowsLeft
)
184 // When creating an index there can be multiple nodes added,
185 // these are sorted ascending
186 sal_Bool bAppend
= nRowsLeft
> 0;
189 sal_Bool bResult
= sal_True
;
195 // Save the last node
196 aSplitNode
= (*this)[nCount
-1];
197 if(rNode
.GetKey() <= aSplitNode
.GetKey())
200 // this practically reduces the number of nodes by 1
201 if (IsLeaf() && this == &rIndex
.m_aCurLeaf
)
203 // assumes, that the node, for which the condition (<=) holds, is stored in m_nCurNode
204 --nCount
; // (otherwise we might get Assertions and GPFs - 60593)
205 bResult
= Insert(rIndex
.m_nCurNode
+ 1, rNode
);
207 else // position unknown
209 sal_uInt16 nPos
= NODE_NOTFOUND
;
210 while (++nPos
< nCount
&& rNode
.GetKey() > ((*this)[nPos
]).GetKey()) ;
212 --nCount
; // (otherwise we might get Assertions and GPFs - 60593)
213 bResult
= Insert(nPos
, rNode
);
216 // can the new node be inserted
227 sal_uInt32 nNewPagePos
= rIndex
.GetPageCount();
228 sal_uInt32 nNewPageCount
= nNewPagePos
+ 1;
230 // insert extracted node into parent node
233 // No parent, then new root
234 ONDXPagePtr aNewRoot
= rIndex
.CreatePage(nNewPagePos
+ 1);
235 aNewRoot
->SetChild(this);
237 rIndex
.m_aRoot
= aNewRoot
;
238 rIndex
.SetRootPos(nNewPagePos
+ 1);
239 rIndex
.SetPageCount(++nNewPageCount
);
242 // create new leaf and divide page
243 ONDXPagePtr aNewPage
= rIndex
.CreatePage(nNewPagePos
,aParent
);
244 rIndex
.SetPageCount(nNewPageCount
);
246 // How many nodes are being inserted?
247 // Enough, then we can fill the page to the brim
249 if (!IsLeaf() || nRowsLeft
< (sal_uInt32
)(rIndex
.GetMaxNodes() / 2))
250 aInnerNode
= Split(*aNewPage
);
253 aInnerNode
= (*this)[nCount
- 1];
255 // Node points to the new page
256 aInnerNode
.SetChild(aNewPage
);
258 // Inner nodes have no record number
259 if (rIndex
.isUnique())
260 aInnerNode
.GetKey().ResetRecord();
262 // new page points to the page of the extracted node
264 aNewPage
->SetChild(aInnerNode
.GetChild());
267 aNewPage
->Append(aSplitNode
);
268 ONDXPagePtr aTempParent
= aParent
;
271 rIndex
.m_aCurLeaf
= aNewPage
;
272 rIndex
.m_nCurNode
= rIndex
.m_aCurLeaf
->Count() - 1;
274 // free not needed pages, there are no references to those on the page
275 // afterwards 'this' can't be valid anymore!!!
279 // Insert extracted node
280 return aTempParent
->Insert(aInnerNode
);
282 else // Fill the page up
287 rIndex
.m_nCurNode
= nCount
- 1;
288 return Append(rNode
);
292 sal_uInt16 nNodePos
= FindPos(rNode
.GetKey());
294 rIndex
.m_nCurNode
= nNodePos
;
296 return Insert(nNodePos
, rNode
);
301 //------------------------------------------------------------------
302 sal_Bool
ONDXPage::Insert(sal_uInt16 nPos
, ONDXNode
& rNode
)
304 sal_uInt16 nMaxCount
= rIndex
.getHeader().db_maxkeys
;
305 if (nPos
>= nMaxCount
)
312 for (sal_uInt16 i
= std::min((sal_uInt16
)(nMaxCount
-1), (sal_uInt16
)(nCount
-1)); nPos
< i
; --i
)
313 (*this)[i
] = (*this)[i
-1];
316 if (nCount
< nMaxCount
)
319 // insert at the position
320 ONDXNode
& rInsertNode
= (*this)[nPos
];
322 if (rInsertNode
.GetChild().Is())
324 rInsertNode
.GetChild()->SetParent(this);
325 rNode
.GetChild()->SetParent(this);
328 bModified
= sal_True
;
333 //------------------------------------------------------------------
334 sal_Bool
ONDXPage::Append(ONDXNode
& rNode
)
336 DBG_ASSERT(!IsFull(), "kein Append moeglich");
337 return Insert(nCount
, rNode
);
339 //------------------------------------------------------------------
340 void ONDXPage::Release(sal_Bool bSave
)
344 aChild
->Release(bSave
);
349 for (sal_uInt16 i
= 0; i
< rIndex
.getHeader().db_maxkeys
;i
++)
351 if (ppNodes
[i
].GetChild())
352 ppNodes
[i
].GetChild()->Release(bSave
);
354 ppNodes
[i
].GetChild().Clear();
358 //------------------------------------------------------------------
359 void ONDXPage::ReleaseFull(sal_Bool bSave
)
361 ONDXPagePtr aTempParent
= aParent
;
364 if (aTempParent
.Is())
366 // Free pages not needed, there will be no reference anymore to the pages
367 // afterwards 'this' can't be valid anymore!!!
368 sal_uInt16 nParentPos
= aTempParent
->Search(this);
369 if (nParentPos
!= NODE_NOTFOUND
)
370 (*aTempParent
)[nParentPos
].GetChild().Clear();
372 aTempParent
->GetChild().Clear();
375 //------------------------------------------------------------------
376 sal_Bool
ONDXPage::Delete(sal_uInt16 nNodePos
)
380 // The last element will not be deleted
381 if (nNodePos
== (nCount
- 1))
383 ONDXNode aNode
= (*this)[nNodePos
];
385 // parent's KeyValue has to be replaced
387 aParent
->SearchAndReplace(aNode
.GetKey(),
388 (*this)[nNodePos
-1].GetKey());
396 if (HasParent() && nCount
< (rIndex
.GetMaxNodes() / 2))
398 // determine, which node points to the page
399 sal_uInt16 nParentNodePos
= aParent
->Search(this);
400 // last element on parent-page -> merge with secondlast page
401 if (nParentNodePos
== (aParent
->Count() - 1))
404 // merge with left neighbour
405 Merge(nParentNodePos
,aParent
->GetChild(&rIndex
));
407 Merge(nParentNodePos
,(*aParent
)[nParentNodePos
-1].GetChild(&rIndex
,aParent
));
409 // otherwise merge page with next page
412 // merge with right neighbour
413 Merge(nParentNodePos
+ 1,((*aParent
)[nParentNodePos
+ 1].GetChild(&rIndex
,aParent
)));
416 if (HasParent() && !(*aParent
)[nParentNodePos
].HasChild())
417 aParent
->Delete(nParentNodePos
);
420 // make sure that the position of the root is kept
421 rIndex
.SetRootPos(nPagePos
);
426 //------------------------------------------------------------------
427 ONDXNode
ONDXPage::Split(ONDXPage
& rPage
)
429 DBG_ASSERT(IsFull(), "Falsches Splitting");
430 /* devide one page into two
432 Page 1 is (n - (n/2))
434 Node n/2 will be duplicated
438 Node ((n+1)/2 + 1) : will be taken out
440 ONDXNode aResultNode
;
443 for (sal_uInt16 i
= (nCount
- (nCount
/ 2)), j
= 0 ; i
< nCount
; i
++)
444 rPage
.Insert(j
++,(*this)[i
]);
446 // this node contains a key that already exists in the tree and must be replaced
447 ONDXNode aLastNode
= (*this)[nCount
- 1];
448 nCount
= nCount
- (nCount
/ 2);
449 aResultNode
= (*this)[nCount
- 1];
452 aParent
->SearchAndReplace(aLastNode
.GetKey(),
453 aResultNode
.GetKey());
457 for (sal_uInt16 i
= (nCount
+ 1) / 2 + 1, j
= 0 ; i
< nCount
; i
++)
458 rPage
.Insert(j
++,(*this)[i
]);
460 aResultNode
= (*this)[(nCount
+ 1) / 2];
461 nCount
= (nCount
+ 1) / 2;
463 // new page points to page with extraced node
464 rPage
.SetChild(aResultNode
.GetChild());
466 // node points to new page
467 aResultNode
.SetChild(&rPage
);
469 // inner nodes have no record number
470 if (rIndex
.isUnique())
471 aResultNode
.GetKey().ResetRecord();
472 bModified
= sal_True
;
476 //------------------------------------------------------------------
477 void ONDXPage::Merge(sal_uInt16 nParentNodePos
, ONDXPagePtr xPage
)
479 DBG_ASSERT(HasParent(), "kein Vater vorhanden");
480 DBG_ASSERT(nParentNodePos
!= NODE_NOTFOUND
, "Falscher Indexaufbau");
483 ONDXNode aResultNode
;
484 sal_uInt16 nMaxNodes
= rIndex
.GetMaxNodes(),
485 nMaxNodes_2
= nMaxNodes
/ 2;
487 // Determine if page is right or left neighbour
488 sal_Bool bRight
= ((*xPage
)[0].GetKey() > (*this)[0].GetKey()); // sal_True, whenn xPage the right side is
489 sal_uInt16 nNewCount
= (*xPage
).Count() + Count();
493 // Condition for merge
494 if (nNewCount
< (nMaxNodes_2
* 2))
496 sal_uInt16 nLastNode
= bRight
? Count() - 1 : xPage
->Count() - 1;
499 DBG_ASSERT(&xPage
!= this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
500 // shift all nodes from xPage to the left node (append)
501 while (xPage
->Count())
509 DBG_ASSERT(&xPage
!= this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
510 // xPage is the left page and THIS the right one
511 while (xPage
->Count())
513 Insert(0,(*xPage
)[xPage
->Count()-1]);
514 xPage
->Remove(xPage
->Count()-1);
516 // replace old position of xPage in parent with this
518 (*aParent
)[nParentNodePos
-1].SetChild(this,aParent
);
519 else // or set as right node
520 aParent
->SetChild(this);
521 aParent
->SetModified(sal_True
);
525 // cancel Child-relationship at parent node
526 (*aParent
)[nParentNodePos
].SetChild();
527 // replace the Node-value, only if changed page is the left one, otherwise become
528 if(aParent
->IsRoot() && aParent
->Count() == 1)
530 (*aParent
)[0].SetChild();
531 aParent
->ReleaseFull();
533 rIndex
.SetRootPos(nPagePos
);
534 rIndex
.m_aRoot
= this;
535 SetModified(sal_True
);
538 aParent
->SearchAndReplace((*this)[nLastNode
].GetKey(),(*this)[nCount
-1].GetKey());
540 xPage
->SetModified(sal_False
);
541 xPage
->ReleaseFull(); // is not needed anymore
543 // balance the elements nNewCount >= (nMaxNodes_2 * 2)
548 // shift all nodes from xPage to the left node (append)
549 ONDXNode aReplaceNode
= (*this)[nCount
- 1];
550 while (nCount
< nMaxNodes_2
)
555 // Replace the node values: replace old last value by the last of xPage
556 aParent
->SearchAndReplace(aReplaceNode
.GetKey(),(*this)[nCount
-1].GetKey());
560 // insert all nodes from this in front of the xPage nodes
561 ONDXNode aReplaceNode
= (*this)[nCount
- 1];
562 while (xPage
->Count() < nMaxNodes_2
)
564 xPage
->Insert(0,(*this)[nCount
-1]);
567 // Replace the node value
568 aParent
->SearchAndReplace(aReplaceNode
.GetKey(),(*this)[Count()-1].GetKey());
574 // Condition for merge
575 if (nNewCount
< nMaxNodes_2
* 2)
579 DBG_ASSERT(&xPage
!= this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
580 // Parent node will be integrated; is initialized with Child from xPage
581 (*aParent
)[nParentNodePos
].SetChild(xPage
->GetChild(),aParent
);
582 Append((*aParent
)[nParentNodePos
]);
583 for (sal_uInt16 i
= 0 ; i
< xPage
->Count(); i
++)
588 DBG_ASSERT(&xPage
!= this,"xPage und THIS duerfen nicht gleich sein: Endlosschleife");
589 // Parent-node will be integrated; is initialized with child
590 (*aParent
)[nParentNodePos
].SetChild(GetChild(),aParent
); // Parent memorizes my child
591 Insert(0,(*aParent
)[nParentNodePos
]); // insert parent node into myself
592 while (xPage
->Count())
594 Insert(0,(*xPage
)[xPage
->Count()-1]);
595 xPage
->Remove(xPage
->Count()-1);
597 SetChild(xPage
->GetChild());
600 (*aParent
)[nParentNodePos
-1].SetChild(this,aParent
);
602 aParent
->SetChild(this);
605 // afterwards parent node will be reset
606 (*aParent
)[nParentNodePos
].SetChild();
607 aParent
->SetModified(sal_True
);
609 if(aParent
->IsRoot() && aParent
->Count() == 1)
611 (*aParent
).SetChild();
612 aParent
->ReleaseFull();
614 rIndex
.SetRootPos(nPagePos
);
615 rIndex
.m_aRoot
= this;
616 SetModified(sal_True
);
618 else if(nParentNodePos
)
619 // replace the node value
620 // for Append the range will be enlarged, for Insert the old node from xPage will reference to this
621 // thats why the node must be updated here
622 aParent
->SearchAndReplace((*aParent
)[nParentNodePos
-1].GetKey(),(*aParent
)[nParentNodePos
].GetKey());
624 xPage
->SetModified(sal_False
);
625 xPage
->ReleaseFull();
627 // balance the elements
632 while (nCount
< nMaxNodes_2
)
634 (*aParent
)[nParentNodePos
].SetChild(xPage
->GetChild(),aParent
);
635 Append((*aParent
)[nParentNodePos
]);
636 (*aParent
)[nParentNodePos
] = (*xPage
)[0];
639 xPage
->SetChild((*aParent
)[nParentNodePos
].GetChild());
640 (*aParent
)[nParentNodePos
].SetChild(xPage
,aParent
);
644 while (nCount
< nMaxNodes_2
)
646 (*aParent
)[nParentNodePos
].SetChild(GetChild(),aParent
);
647 Insert(0,(*aParent
)[nParentNodePos
]);
648 (*aParent
)[nParentNodePos
] = (*xPage
)[xPage
->Count()-1];
649 xPage
->Remove(xPage
->Count()-1);
651 SetChild((*aParent
)[nParentNodePos
].GetChild());
652 (*aParent
)[nParentNodePos
].SetChild(this,aParent
);
655 aParent
->SetModified(sal_True
);
659 //==================================================================
661 //==================================================================
663 //------------------------------------------------------------------
664 void ONDXNode::Read(SvStream
&rStream
, ODbaseIndex
& rIndex
)
666 rStream
>> aKey
.nRecord
; // key
668 if (rIndex
.getHeader().db_keytype
)
672 aKey
= ONDXKey(aDbl
,aKey
.nRecord
);
676 sal_uInt16 nLen
= rIndex
.getHeader().db_keylen
;
677 rtl::OString aBuf
= read_uInt8s_ToOString(rStream
, nLen
);
678 //get length minus trailing whitespace
679 sal_Int32 nContentLen
= aBuf
.getLength();
680 while (nContentLen
&& aBuf
[nContentLen
-1] == ' ')
682 aKey
= ONDXKey(::rtl::OUString(aBuf
.getStr(), nContentLen
, rIndex
.m_pTable
->getConnection()->getTextEncoding()) ,aKey
.nRecord
);
687 //------------------------------------------------------------------
688 void ONDXNode::Write(SvStream
&rStream
, const ONDXPage
& rPage
) const
690 const ODbaseIndex
& rIndex
= rPage
.GetIndex();
691 if (!rIndex
.isUnique() || rPage
.IsLeaf())
692 rStream
<< (sal_uInt32
)aKey
.nRecord
; // key
694 rStream
<< (sal_uInt32
)0; // key
696 if (rIndex
.getHeader().db_keytype
) // double
698 if (sizeof(double) != rIndex
.getHeader().db_keylen
)
700 OSL_TRACE("this key length cannot possibly be right?");
702 if (aKey
.getValue().isNull())
704 sal_uInt8 buf
[sizeof(double)];
705 memset(&buf
[0], 0, sizeof(double));
706 rStream
.Write(&buf
[0], sizeof(double));
709 rStream
<< (double) aKey
.getValue();
713 sal_uInt16
const nLen(rIndex
.getHeader().db_keylen
);
714 ::boost::scoped_array
<sal_uInt8
> pBuf(new sal_uInt8
[nLen
]);
715 memset(&pBuf
[0], 0x20, nLen
);
716 if (!aKey
.getValue().isNull())
718 ::rtl::OUString sValue
= aKey
.getValue();
719 rtl::OString
aText(rtl::OUStringToOString(sValue
, rIndex
.m_pTable
->getConnection()->getTextEncoding()));
720 strncpy(reinterpret_cast<char *>(&pBuf
[0]), aText
.getStr(),
721 std::min
<size_t>(nLen
, aText
.getLength()));
723 rStream
.Write(&pBuf
[0], nLen
);
729 //------------------------------------------------------------------
730 ONDXPagePtr
& ONDXNode::GetChild(ODbaseIndex
* pIndex
, ONDXPage
* pParent
)
732 if (!aChild
.Is() && pIndex
)
734 aChild
= pIndex
->CreatePage(aChild
.GetPagePos(),pParent
,aChild
.HasPage());
739 //==================================================================
741 //==================================================================
742 //------------------------------------------------------------------
743 sal_Bool
ONDXKey::IsText(sal_Int32 eType
)
745 return eType
== DataType::VARCHAR
|| eType
== DataType::CHAR
;
748 //------------------------------------------------------------------
749 StringCompare
ONDXKey::Compare(const ONDXKey
& rKey
) const
751 StringCompare eResult
;
753 if (getValue().isNull())
755 if (rKey
.getValue().isNull() || (rKey
.IsText(getDBType()) && rKey
.getValue().getString().isEmpty()))
756 eResult
= COMPARE_EQUAL
;
758 eResult
= COMPARE_LESS
;
760 else if (rKey
.getValue().isNull())
762 if (getValue().isNull() || (IsText(getDBType()) && getValue().getString().isEmpty()))
763 eResult
= COMPARE_EQUAL
;
765 eResult
= COMPARE_GREATER
;
767 else if (IsText(getDBType()))
769 sal_Int32 nRes
= getValue().getString().compareTo(rKey
.getValue());
770 eResult
= (nRes
> 0) ? COMPARE_GREATER
: (nRes
== 0) ? COMPARE_EQUAL
: COMPARE_LESS
;
774 double m
= getValue(),n
= rKey
.getValue();
775 eResult
= (m
> n
) ? COMPARE_GREATER
: (n
== m
) ? COMPARE_EQUAL
: COMPARE_LESS
;
778 // compare record, if index !Unique
779 if (eResult
== COMPARE_EQUAL
&& nRecord
&& rKey
.nRecord
)
780 eResult
= (nRecord
> rKey
.nRecord
) ? COMPARE_GREATER
:
781 (nRecord
== rKey
.nRecord
) ? COMPARE_EQUAL
: COMPARE_LESS
;
785 // -----------------------------------------------------------------------------
786 void ONDXKey::setValue(const ORowSetValue
& _rVal
)
790 // -----------------------------------------------------------------------------
791 const ORowSetValue
& ONDXKey::getValue() const
795 // -----------------------------------------------------------------------------
796 SvStream
& connectivity::dbase::operator >> (SvStream
&rStream
, ONDXPagePtr
& rPage
)
798 rStream
>> rPage
.nPagePos
;
801 // -----------------------------------------------------------------------------
802 SvStream
& connectivity::dbase::operator << (SvStream
&rStream
, const ONDXPagePtr
& rPage
)
804 rStream
<< rPage
.nPagePos
;
807 // -----------------------------------------------------------------------------
808 //==================================================================
810 //==================================================================
811 //------------------------------------------------------------------
812 ONDXPagePtr::ONDXPagePtr(const ONDXPagePtr
& rRef
)
814 ,nPagePos(rRef
.nPagePos
)
818 //------------------------------------------------------------------
819 ONDXPagePtr::ONDXPagePtr(ONDXPage
* pRefPage
)
820 :ONDXPageRef(pRefPage
)
824 nPagePos
= pRefPage
->GetPagePos();
826 //------------------------------------------------------------------
827 ONDXPagePtr
& ONDXPagePtr::operator=(const ONDXPagePtr
& rRef
)
829 ONDXPageRef::operator=(rRef
);
830 nPagePos
= rRef
.nPagePos
;
834 //------------------------------------------------------------------
835 ONDXPagePtr
& ONDXPagePtr::operator= (ONDXPage
* pRef
)
837 ONDXPageRef::operator=(pRef
);
838 nPagePos
= (pRef
) ? pRef
->GetPagePos() : 0;
841 // -----------------------------------------------------------------------------
842 static sal_uInt32 nValue
;
843 //------------------------------------------------------------------
844 SvStream
& connectivity::dbase::operator >> (SvStream
&rStream
, ONDXPage
& rPage
)
846 rStream
.Seek(rPage
.GetPagePos() * PAGE_SIZE
);
847 rStream
>> nValue
>> rPage
.aChild
;
848 rPage
.nCount
= sal_uInt16(nValue
);
850 for (sal_uInt16 i
= 0; i
< rPage
.nCount
; i
++)
851 rPage
[i
].Read(rStream
, rPage
.GetIndex());
855 //------------------------------------------------------------------
856 SvStream
& connectivity::dbase::operator << (SvStream
&rStream
, const ONDXPage
& rPage
)
858 // Page doesn't exist yet
859 sal_uIntPtr nSize
= (rPage
.GetPagePos() + 1) * PAGE_SIZE
;
860 if (nSize
> rStream
.Seek(STREAM_SEEK_TO_END
))
862 rStream
.SetStreamSize(nSize
);
863 rStream
.Seek(rPage
.GetPagePos() * PAGE_SIZE
);
865 char aEmptyData
[PAGE_SIZE
];
866 memset(aEmptyData
,0x00,PAGE_SIZE
);
867 rStream
.Write((sal_uInt8
*)aEmptyData
,PAGE_SIZE
);
869 sal_uIntPtr nCurrentPos
= rStream
.Seek(rPage
.GetPagePos() * PAGE_SIZE
);
870 OSL_UNUSED( nCurrentPos
);
872 nValue
= rPage
.nCount
;
873 rStream
<< nValue
<< rPage
.aChild
;
876 for (; i
< rPage
.nCount
; i
++)
877 rPage
[i
].Write(rStream
, rPage
);
879 // check if we have to fill the stream with '\0'
880 if(i
< rPage
.rIndex
.getHeader().db_maxkeys
)
882 sal_uIntPtr nTell
= rStream
.Tell() % PAGE_SIZE
;
883 sal_uInt16 nBufferSize
= rStream
.GetBufferSize();
884 sal_uIntPtr nRemainSize
= nBufferSize
- nTell
;
885 if ( nRemainSize
<= nBufferSize
)
887 char* pEmptyData
= new char[nRemainSize
];
888 memset(pEmptyData
,0x00,nRemainSize
);
889 rStream
.Write((sal_uInt8
*)pEmptyData
,nRemainSize
);
891 delete [] pEmptyData
;
896 // -----------------------------------------------------------------------------
897 #if OSL_DEBUG_LEVEL > 1
898 //------------------------------------------------------------------
899 void ONDXPage::PrintPage()
901 OSL_TRACE("\nSDB: -----------Page: %d Parent: %d Count: %d Child: %d-----",
902 nPagePos
, HasParent() ? aParent
->GetPagePos() : 0 ,nCount
, aChild
.GetPagePos());
904 for (sal_uInt16 i
= 0; i
< nCount
; i
++)
906 ONDXNode rNode
= (*this)[i
];
907 ONDXKey
& rKey
= rNode
.GetKey();
909 rNode
.GetChild(&rIndex
, this);
911 if (rKey
.getValue().isNull())
913 OSL_TRACE("SDB: [%d,NULL,%d]",rKey
.GetRecord(), rNode
.GetChild().GetPagePos());
915 else if (rIndex
.getHeader().db_keytype
)
917 OSL_TRACE("SDB: [%d,%f,%d]",rKey
.GetRecord(), rKey
.getValue().getDouble(),rNode
.GetChild().GetPagePos());
921 OSL_TRACE("SDB: [%d,%s,%d]",rKey
.GetRecord(), rtl::OUStringToOString(rKey
.getValue().getString(), rIndex
.m_pTable
->getConnection()->getTextEncoding()).getStr(),rNode
.GetChild().GetPagePos());
924 OSL_TRACE("SDB: -----------------------------------------------");
927 #if OSL_DEBUG_LEVEL > 1
928 GetChild(&rIndex
)->PrintPage();
929 for (sal_uInt16 i
= 0; i
< nCount
; i
++)
931 ONDXNode rNode
= (*this)[i
];
932 rNode
.GetChild(&rIndex
,this)->PrintPage();
936 OSL_TRACE("SDB: ===============================================");
939 // -----------------------------------------------------------------------------
940 sal_Bool
ONDXPage::IsFull() const
942 return Count() == rIndex
.getHeader().db_maxkeys
;
944 // -----------------------------------------------------------------------------
945 //------------------------------------------------------------------
946 sal_uInt16
ONDXPage::Search(const ONDXKey
& rSearch
)
948 // binary search later
949 sal_uInt16 i
= NODE_NOTFOUND
;
950 while (++i
< Count())
951 if ((*this)[i
].GetKey() == rSearch
)
954 return (i
< Count()) ? i
: NODE_NOTFOUND
;
957 //------------------------------------------------------------------
958 sal_uInt16
ONDXPage::Search(const ONDXPage
* pPage
)
960 sal_uInt16 i
= NODE_NOTFOUND
;
961 while (++i
< Count())
962 if (((*this)[i
]).GetChild() == pPage
)
965 // if not found, then we assume, that the page itself points to the page
966 return (i
< Count()) ? i
: NODE_NOTFOUND
;
968 // -----------------------------------------------------------------------------
970 void ONDXPage::SearchAndReplace(const ONDXKey
& rSearch
,
973 OSL_ENSURE(rSearch
!= rReplace
,"Invalid here:rSearch == rReplace");
974 if (rSearch
!= rReplace
)
976 sal_uInt16 nPos
= NODE_NOTFOUND
;
977 ONDXPage
* pPage
= this;
979 while (pPage
&& (nPos
= pPage
->Search(rSearch
)) == NODE_NOTFOUND
)
980 pPage
= pPage
->aParent
;
984 (*pPage
)[nPos
].GetKey() = rReplace
;
985 pPage
->SetModified(sal_True
);
989 // -----------------------------------------------------------------------------
990 ONDXNode
& ONDXPage::operator[] (sal_uInt16 nPos
)
992 DBG_ASSERT(nCount
> nPos
, "falscher Indexzugriff");
993 return ppNodes
[nPos
];
996 //------------------------------------------------------------------
997 const ONDXNode
& ONDXPage::operator[] (sal_uInt16 nPos
) const
999 DBG_ASSERT(nCount
> nPos
, "falscher Indexzugriff");
1000 return ppNodes
[nPos
];
1002 // -----------------------------------------------------------------------------
1003 void ONDXPage::Remove(sal_uInt16 nPos
)
1005 DBG_ASSERT(nCount
> nPos
, "falscher Indexzugriff");
1007 for (sal_uInt16 i
= nPos
; i
< (nCount
-1); i
++)
1008 (*this)[i
] = (*this)[i
+1];
1011 bModified
= sal_True
;
1013 // -----------------------------------------------------------------------------
1015 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */