bump product version to 7.2.5.1
[LibreOffice.git] / connectivity / source / drivers / dbase / DIndexIter.cxx
blob37e28a073f4c5165dfc4a8941a682cbfa06641f6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
28 // OIndexIterator
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;
40 if (bFirst)
42 m_aRoot = m_xIndex->getRoot();
43 m_aCurLeaf.Clear();
46 if (!m_pOperator)
48 // Preparation, position on the smallest element
49 if (bFirst)
51 ONDXPage* pPage = m_aRoot;
52 while (pPage && !pPage->IsLeaf())
53 pPage = pPage->GetChild(m_xIndex.get());
55 m_aCurLeaf = pPage;
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);
70 return nRes;
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);
81 sal_uInt16 i = 0;
83 if (pPage->IsLeaf())
85 // in the leaf the actual operation is run, otherwise temp. (>)
86 while (i < pPage->Count() && !m_pOperator->operate(&((*pPage)[i]).GetKey(), &rKey))
87 i++;
89 else
90 while (i < pPage->Count() && !aTempOp.operate(&((*pPage)[i]).GetKey(), &rKey))
91 i++;
93 ONDXKey* pFoundKey = nullptr;
94 if (!pPage->IsLeaf())
96 // descend further
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())
103 pFoundKey = nullptr;
105 else
107 pFoundKey = &(*pPage)[i].GetKey();
108 if (!m_pOperator->operate(pFoundKey, &rKey))
109 pFoundKey = nullptr;
111 m_aCurLeaf = pPage;
112 m_nCurNode = pFoundKey ? i : i - 1;
114 return pFoundKey;
117 sal_uInt32 OIndexIterator::GetCompare(bool bFirst)
119 ONDXKey* pKey = nullptr;
120 sal_Int32 ePredicateType = dynamic_cast<file::OOp_COMPARE&>(*m_pOperator).getPredicateType();
122 if (bFirst)
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());
134 m_aCurLeaf = pPage;
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))
143 break;
144 break;
145 case SQLFilterOperator::LESS:
146 while ((pKey = GetNextKey()) != nullptr)
147 if (!pKey->getValue().isNull())
148 break;
149 break;
150 case SQLFilterOperator::LESS_EQUAL:
151 while ((pKey = GetNextKey()) != nullptr)
153 break;
154 case SQLFilterOperator::GREATER_EQUAL:
155 case SQLFilterOperator::EQUAL:
156 pKey = GetFirstKey(m_aRoot, *m_pOperand);
157 break;
158 case SQLFilterOperator::GREATER:
159 pKey = GetFirstKey(m_aRoot, *m_pOperand);
160 if (!pKey)
161 while ((pKey = GetNextKey()) != nullptr)
162 if (m_pOperator->operate(pKey, m_pOperand))
163 break;
166 else
168 switch (ePredicateType)
170 case SQLFilterOperator::NOT_EQUAL:
171 while ((pKey = GetNextKey()) != nullptr)
172 if (m_pOperator->operate(pKey, m_pOperand))
173 break;
174 break;
175 case SQLFilterOperator::LESS:
176 case SQLFilterOperator::LESS_EQUAL:
177 case SQLFilterOperator::EQUAL:
178 pKey = GetNextKey();
179 if (pKey == nullptr || !m_pOperator->operate(pKey, m_pOperand))
181 pKey = nullptr;
182 m_aCurLeaf.Clear();
184 break;
185 case SQLFilterOperator::GREATER_EQUAL:
186 case SQLFilterOperator::GREATER:
187 pKey = GetNextKey();
191 return pKey ? pKey->GetRecord() : NODE_NOTFOUND;
194 sal_uInt32 OIndexIterator::GetLike(bool bFirst)
196 if (bFirst)
198 ONDXPage* pPage = m_aRoot;
200 while (pPage && !pPage->IsLeaf())
201 pPage = pPage->GetChild(m_xIndex.get());
203 m_aCurLeaf = pPage;
204 m_nCurNode = NODE_NOTFOUND;
207 ONDXKey* pKey;
208 while ((pKey = GetNextKey()) != nullptr)
209 if (m_pOperator->operate(pKey, m_pOperand))
210 break;
211 return pKey ? pKey->GetRecord() : NODE_NOTFOUND;
214 sal_uInt32 OIndexIterator::GetNull(bool bFirst)
216 if (bFirst)
218 ONDXPage* pPage = m_aRoot;
219 while (pPage && !pPage->IsLeaf())
220 pPage = pPage->GetChild(m_xIndex.get());
222 m_aCurLeaf = pPage;
223 m_nCurNode = NODE_NOTFOUND;
226 ONDXKey* pKey = GetNextKey();
227 if (pKey == nullptr || !pKey->getValue().isNull())
229 pKey = nullptr;
230 m_aCurLeaf.Clear();
232 return pKey ? pKey->GetRecord() : NODE_NOTFOUND;
235 sal_uInt32 OIndexIterator::GetNotNull(bool bFirst)
237 ONDXKey* pKey;
238 if (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;
245 else
246 pKey = GetNextKey();
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;
256 // search next page
257 while (pPage)
259 ONDXPage* pParentPage = pPage->GetParent();
260 if (pParentPage)
262 sal_uInt16 nPos = pParentPage->Search(pPage);
263 if (nPos != pParentPage->Count() - 1)
264 { // page found
265 pPage = (*pParentPage)[nPos + 1].GetChild(m_xIndex.get(), pParentPage);
266 break;
269 pPage = pParentPage;
272 // now go on with leaf
273 while (pPage && !pPage->IsLeaf())
274 pPage = pPage->GetChild(m_xIndex.get());
276 m_aCurLeaf = pPage;
277 m_nCurNode = 0;
279 return m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : nullptr;
282 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */