1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <dbase/DIndexIter.hxx>
21 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
23 using namespace ::com::sun::star::sdb
;
24 using namespace connectivity
;
25 using namespace connectivity::dbase
;
26 using namespace connectivity::file
;
30 OIndexIterator::~OIndexIterator() {}
32 sal_uInt32
OIndexIterator::First() { return Find(true); }
34 sal_uInt32
OIndexIterator::Next() { return Find(false); }
36 sal_uInt32
OIndexIterator::Find(bool bFirst
)
38 sal_uInt32 nRes
= NODE_NOTFOUND
;
42 m_aRoot
= m_xIndex
->getRoot();
48 // Preparation, position on the smallest element
51 ONDXPage
* pPage
= m_aRoot
;
52 while (pPage
&& !pPage
->IsLeaf())
53 pPage
= pPage
->GetChild(m_xIndex
.get());
56 m_nCurNode
= NODE_NOTFOUND
;
58 ONDXKey
* pKey
= GetNextKey();
59 nRes
= pKey
? pKey
->GetRecord() : NODE_NOTFOUND
;
61 else if (dynamic_cast<const OOp_ISNOTNULL
*>(m_pOperator
) != nullptr)
62 nRes
= GetNotNull(bFirst
);
63 else if (dynamic_cast<const OOp_ISNULL
*>(m_pOperator
) != nullptr)
64 nRes
= GetNull(bFirst
);
65 else if (dynamic_cast<const OOp_LIKE
*>(m_pOperator
) != nullptr)
66 nRes
= GetLike(bFirst
);
67 else if (dynamic_cast<const OOp_COMPARE
*>(m_pOperator
) != nullptr)
68 nRes
= GetCompare(bFirst
);
73 ONDXKey
* OIndexIterator::GetFirstKey(ONDXPage
* pPage
, const OOperand
& rKey
)
75 // searches a given key
76 // Speciality: At the end of the algorithm
77 // the actual page and the position of the node which fulfil the
78 // '<='-condition are saved. this is considered for inserts.
79 // ONDXIndex* m_pIndex = GetNDXIndex();
80 OOp_COMPARE
aTempOp(SQLFilterOperator::GREATER
);
85 // in the leaf the actual operation is run, otherwise temp. (>)
86 while (i
< pPage
->Count() && !m_pOperator
->operate(&((*pPage
)[i
]).GetKey(), &rKey
))
90 while (i
< pPage
->Count() && !aTempOp
.operate(&((*pPage
)[i
]).GetKey(), &rKey
))
93 ONDXKey
* pFoundKey
= nullptr;
97 ONDXPagePtr aPage
= (i
== 0) ? pPage
->GetChild(m_xIndex
.get())
98 : ((*pPage
)[i
- 1]).GetChild(m_xIndex
.get(), pPage
);
99 pFoundKey
= aPage
.Is() ? GetFirstKey(aPage
, rKey
) : nullptr;
101 else if (i
== pPage
->Count())
107 pFoundKey
= &(*pPage
)[i
].GetKey();
108 if (!m_pOperator
->operate(pFoundKey
, &rKey
))
112 m_nCurNode
= pFoundKey
? i
: i
- 1;
117 sal_uInt32
OIndexIterator::GetCompare(bool bFirst
)
119 ONDXKey
* pKey
= nullptr;
120 sal_Int32 ePredicateType
= dynamic_cast<file::OOp_COMPARE
&>(*m_pOperator
).getPredicateType();
124 // Preparation, position on the smallest element
125 ONDXPage
* pPage
= m_aRoot
;
126 switch (ePredicateType
)
128 case SQLFilterOperator::NOT_EQUAL
:
129 case SQLFilterOperator::LESS
:
130 case SQLFilterOperator::LESS_EQUAL
:
131 while (pPage
&& !pPage
->IsLeaf())
132 pPage
= pPage
->GetChild(m_xIndex
.get());
135 m_nCurNode
= NODE_NOTFOUND
;
138 switch (ePredicateType
)
140 case SQLFilterOperator::NOT_EQUAL
:
141 while ((pKey
= GetNextKey()) != nullptr)
142 if (m_pOperator
->operate(pKey
, m_pOperand
))
145 case SQLFilterOperator::LESS
:
146 while ((pKey
= GetNextKey()) != nullptr)
147 if (!pKey
->getValue().isNull())
150 case SQLFilterOperator::LESS_EQUAL
:
151 while ((pKey
= GetNextKey()) != nullptr)
154 case SQLFilterOperator::GREATER_EQUAL
:
155 case SQLFilterOperator::EQUAL
:
156 pKey
= GetFirstKey(m_aRoot
, *m_pOperand
);
158 case SQLFilterOperator::GREATER
:
159 pKey
= GetFirstKey(m_aRoot
, *m_pOperand
);
161 while ((pKey
= GetNextKey()) != nullptr)
162 if (m_pOperator
->operate(pKey
, m_pOperand
))
168 switch (ePredicateType
)
170 case SQLFilterOperator::NOT_EQUAL
:
171 while ((pKey
= GetNextKey()) != nullptr)
172 if (m_pOperator
->operate(pKey
, m_pOperand
))
175 case SQLFilterOperator::LESS
:
176 case SQLFilterOperator::LESS_EQUAL
:
177 case SQLFilterOperator::EQUAL
:
179 if (pKey
== nullptr || !m_pOperator
->operate(pKey
, m_pOperand
))
185 case SQLFilterOperator::GREATER_EQUAL
:
186 case SQLFilterOperator::GREATER
:
191 return pKey
? pKey
->GetRecord() : NODE_NOTFOUND
;
194 sal_uInt32
OIndexIterator::GetLike(bool bFirst
)
198 ONDXPage
* pPage
= m_aRoot
;
200 while (pPage
&& !pPage
->IsLeaf())
201 pPage
= pPage
->GetChild(m_xIndex
.get());
204 m_nCurNode
= NODE_NOTFOUND
;
208 while ((pKey
= GetNextKey()) != nullptr)
209 if (m_pOperator
->operate(pKey
, m_pOperand
))
211 return pKey
? pKey
->GetRecord() : NODE_NOTFOUND
;
214 sal_uInt32
OIndexIterator::GetNull(bool bFirst
)
218 ONDXPage
* pPage
= m_aRoot
;
219 while (pPage
&& !pPage
->IsLeaf())
220 pPage
= pPage
->GetChild(m_xIndex
.get());
223 m_nCurNode
= NODE_NOTFOUND
;
226 ONDXKey
* pKey
= GetNextKey();
227 if (pKey
== nullptr || !pKey
->getValue().isNull())
232 return pKey
? pKey
->GetRecord() : NODE_NOTFOUND
;
235 sal_uInt32
OIndexIterator::GetNotNull(bool bFirst
)
240 // go through all NULL values first
241 for (sal_uInt32 nRec
= GetNull(bFirst
); nRec
!= NODE_NOTFOUND
; nRec
= GetNull(false))
243 pKey
= m_aCurLeaf
.Is() ? &(*m_aCurLeaf
)[m_nCurNode
].GetKey() : nullptr;
248 return pKey
? pKey
->GetRecord() : NODE_NOTFOUND
;
251 ONDXKey
* OIndexIterator::GetNextKey()
253 if (m_aCurLeaf
.Is() && ((++m_nCurNode
) >= m_aCurLeaf
->Count()))
255 ONDXPage
* pPage
= m_aCurLeaf
;
259 ONDXPage
* pParentPage
= pPage
->GetParent();
262 sal_uInt16 nPos
= pParentPage
->Search(pPage
);
263 if (nPos
!= pParentPage
->Count() - 1)
265 pPage
= (*pParentPage
)[nPos
+ 1].GetChild(m_xIndex
.get(), pParentPage
);
272 // now go on with leaf
273 while (pPage
&& !pPage
->IsLeaf())
274 pPage
= pPage
->GetChild(m_xIndex
.get());
279 return m_aCurLeaf
.Is() ? &(*m_aCurLeaf
)[m_nCurNode
].GetKey() : nullptr;
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */