Bump for 3.6-28
[LibreOffice.git] / connectivity / source / drivers / dbase / DIndexIter.cxx
blob546daecd82993949a4b7d4aedc365adb75ab6e53
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/DIndexIter.hxx"
30 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
32 using namespace ::com::sun::star::sdb;
33 using namespace connectivity;
34 using namespace connectivity::dbase;
35 using namespace connectivity::file;
36 using namespace ::com::sun::star::sdb;
37 //==================================================================
38 // OIndexIterator
39 //==================================================================
40 //------------------------------------------------------------------
41 OIndexIterator::~OIndexIterator()
43 m_pIndex->release();
46 //------------------------------------------------------------------
47 sal_uIntPtr OIndexIterator::First()
49 return Find(sal_True);
52 //------------------------------------------------------------------
53 sal_uIntPtr OIndexIterator::Next()
55 return Find(sal_False);
57 //------------------------------------------------------------------
58 sal_uIntPtr OIndexIterator::Find(sal_Bool bFirst)
60 sal_uIntPtr nRes = STRING_NOTFOUND;
62 if (bFirst)
64 m_aRoot = m_pIndex->getRoot();
65 m_aCurLeaf = NULL;
68 if (!m_pOperator)
70 // Preparation, position on the smallest element
71 if (bFirst)
73 ONDXPage* pPage = m_aRoot;
74 while (pPage && !pPage->IsLeaf())
75 pPage = pPage->GetChild(m_pIndex);
77 m_aCurLeaf = pPage;
78 m_nCurNode = NODE_NOTFOUND;
80 ONDXKey* pKey = GetNextKey();
81 nRes = pKey ? pKey->GetRecord() : STRING_NOTFOUND;
83 else if (m_pOperator->IsA(TYPE(OOp_ISNOTNULL)))
84 nRes = GetNotNull(bFirst);
85 else if (m_pOperator->IsA(TYPE(OOp_ISNULL)))
86 nRes = GetNull(bFirst);
87 else if (m_pOperator->IsA(TYPE(OOp_LIKE)))
88 nRes = GetLike(bFirst);
89 else if (m_pOperator->IsA(TYPE(OOp_COMPARE)))
90 nRes = GetCompare(bFirst);
92 return nRes;
95 //------------------------------------------------------------------
96 ONDXKey* OIndexIterator::GetFirstKey(ONDXPage* pPage, const OOperand& rKey)
98 // searches a given key
99 // Speciality: At the end of the algorithm
100 // the actual page and the position of the node which fulfil the
101 // '<='-condition are saved. this is considered for inserts.
102 // ONDXIndex* m_pIndex = GetNDXIndex();
103 OOp_COMPARE aTempOp(SQLFilterOperator::GREATER);
104 sal_uInt16 i = 0;
106 if (pPage->IsLeaf())
108 // in the leaf the actual operation is run, otherwise temp. (>)
109 while (i < pPage->Count() && !m_pOperator->operate(&((*pPage)[i]).GetKey(),&rKey))
110 i++;
112 else
113 while (i < pPage->Count() && !aTempOp.operate(&((*pPage)[i]).GetKey(),&rKey))
114 i++;
117 ONDXKey* pFoundKey = NULL;
118 if (!pPage->IsLeaf())
120 // descend further
121 ONDXPagePtr aPage = (i==0) ? pPage->GetChild(m_pIndex)
122 : ((*pPage)[i-1]).GetChild(m_pIndex, pPage);
123 pFoundKey = aPage.Is() ? GetFirstKey(aPage, rKey) : NULL;
125 else if (i == pPage->Count())
127 pFoundKey = NULL;
129 else
131 pFoundKey = &(*pPage)[i].GetKey();
132 if (!m_pOperator->operate(pFoundKey,&rKey))
133 pFoundKey = NULL;
135 m_aCurLeaf = pPage;
136 m_nCurNode = pFoundKey ? i : i - 1;
138 return pFoundKey;
141 //------------------------------------------------------------------
142 sal_uIntPtr OIndexIterator::GetCompare(sal_Bool bFirst)
144 ONDXKey* pKey = NULL;
145 sal_Int32 ePredicateType = PTR_CAST(file::OOp_COMPARE,m_pOperator)->getPredicateType();
147 if (bFirst)
149 // Preparation, position on the smallest element
150 ONDXPage* pPage = m_aRoot;
151 switch (ePredicateType)
153 case SQLFilterOperator::NOT_EQUAL:
154 case SQLFilterOperator::LESS:
155 case SQLFilterOperator::LESS_EQUAL:
156 while (pPage && !pPage->IsLeaf())
157 pPage = pPage->GetChild(m_pIndex);
159 m_aCurLeaf = pPage;
160 m_nCurNode = NODE_NOTFOUND;
164 switch (ePredicateType)
166 case SQLFilterOperator::NOT_EQUAL:
167 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ;
168 break;
169 case SQLFilterOperator::LESS:
170 while ( ( ( pKey = GetNextKey() ) != NULL ) && pKey->getValue().isNull()) ;
171 break;
172 case SQLFilterOperator::LESS_EQUAL:
173 while ( ( pKey = GetNextKey() ) != NULL ) ;
174 break;
175 case SQLFilterOperator::GREATER_EQUAL:
176 case SQLFilterOperator::EQUAL:
177 pKey = GetFirstKey(m_aRoot,*m_pOperand);
178 break;
179 case SQLFilterOperator::GREATER:
180 pKey = GetFirstKey(m_aRoot,*m_pOperand);
181 if ( !pKey )
182 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ;
185 else
187 switch (ePredicateType)
189 case SQLFilterOperator::NOT_EQUAL:
190 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand))
192 break;
193 case SQLFilterOperator::LESS:
194 case SQLFilterOperator::LESS_EQUAL:
195 case SQLFilterOperator::EQUAL:
196 if ( ( ( pKey = GetNextKey() ) == NULL ) || !m_pOperator->operate(pKey,m_pOperand))
198 pKey = NULL;
199 m_aCurLeaf = NULL;
201 break;
202 case SQLFilterOperator::GREATER_EQUAL:
203 case SQLFilterOperator::GREATER:
204 pKey = GetNextKey();
208 return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
211 //------------------------------------------------------------------
212 sal_uIntPtr OIndexIterator::GetLike(sal_Bool bFirst)
214 if (bFirst)
216 ONDXPage* pPage = m_aRoot;
218 while (pPage && !pPage->IsLeaf())
219 pPage = pPage->GetChild(m_pIndex);
221 m_aCurLeaf = pPage;
222 m_nCurNode = NODE_NOTFOUND;
225 ONDXKey* pKey;
226 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand))
228 return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
231 //------------------------------------------------------------------
232 sal_uIntPtr OIndexIterator::GetNull(sal_Bool bFirst)
234 if (bFirst)
236 ONDXPage* pPage = m_aRoot;
237 while (pPage && !pPage->IsLeaf())
238 pPage = pPage->GetChild(m_pIndex);
240 m_aCurLeaf = pPage;
241 m_nCurNode = NODE_NOTFOUND;
244 ONDXKey* pKey;
245 if ( ( ( pKey = GetNextKey() ) == NULL ) || !pKey->getValue().isNull())
247 pKey = NULL;
248 m_aCurLeaf = NULL;
250 return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
253 //------------------------------------------------------------------
254 sal_uIntPtr OIndexIterator::GetNotNull(sal_Bool bFirst)
256 ONDXKey* pKey;
257 if (bFirst)
259 // go through all NULL values first
260 for (sal_uIntPtr nRec = GetNull(bFirst);
261 nRec != STRING_NOTFOUND;
262 nRec = GetNull(sal_False))
264 pKey = m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL;
266 else
267 pKey = GetNextKey();
269 return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
272 //------------------------------------------------------------------
273 ONDXKey* OIndexIterator::GetNextKey()
275 if (m_aCurLeaf.Is() && ((++m_nCurNode) >= m_aCurLeaf->Count()))
277 ONDXPage* pPage = m_aCurLeaf;
278 // search next page
279 while (pPage)
281 ONDXPage* pParentPage = pPage->GetParent();
282 if (pParentPage)
284 sal_uInt16 nPos = pParentPage->Search(pPage);
285 if (nPos != pParentPage->Count() - 1)
286 { // page found
287 pPage = (*pParentPage)[nPos+1].GetChild(m_pIndex,pParentPage);
288 break;
291 pPage = pParentPage;
294 // now go on with leaf
295 while (pPage && !pPage->IsLeaf())
296 pPage = pPage->GetChild(m_pIndex);
298 m_aCurLeaf = pPage;
299 m_nCurNode = 0;
301 return m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL;
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */