xref: /trunk/main/connectivity/source/drivers/dbase/DIndexIter.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_connectivity.hxx"
30 #include "dbase/DIndexIter.hxx"
31 #include <com/sun/star/sdb/SQLFilterOperator.hpp>
32 
33 using namespace ::com::sun::star::sdb;
34 using namespace connectivity;
35 using namespace connectivity::dbase;
36 using namespace connectivity::file;
37 using namespace ::com::sun::star::sdb;
38 //==================================================================
39 // OIndexIterator
40 //==================================================================
41 //------------------------------------------------------------------
42 OIndexIterator::~OIndexIterator()
43 {
44     //  m_pIndex->UnLock();
45     m_pIndex->release();
46 }
47 
48 //------------------------------------------------------------------
49 sal_uIntPtr OIndexIterator::First()
50 {
51     return Find(sal_True);
52 }
53 
54 //------------------------------------------------------------------
55 sal_uIntPtr OIndexIterator::Next()
56 {
57     return Find(sal_False);
58 }
59 //------------------------------------------------------------------
60 sal_uIntPtr OIndexIterator::Find(sal_Bool bFirst)
61 {
62     //  ONDXIndex* m_pIndex = GetNDXIndex();
63 
64     sal_uIntPtr nRes = STRING_NOTFOUND;
65 //  if (!m_pIndex->IsOpen())
66 //      return nRes;
67 
68     if (bFirst)
69     {
70         m_aRoot = m_pIndex->getRoot();
71         m_aCurLeaf = NULL;
72     }
73 
74     if (!m_pOperator)
75     {
76         // Vorbereitung , auf kleinstes Element positionieren
77         if (bFirst)
78         {
79             ONDXPage* pPage = m_aRoot;
80             while (pPage && !pPage->IsLeaf())
81                 pPage = pPage->GetChild(m_pIndex);
82 
83             m_aCurLeaf = pPage;
84             m_nCurNode = NODE_NOTFOUND;
85         }
86         ONDXKey* pKey = GetNextKey();
87         nRes = pKey ? pKey->GetRecord() : STRING_NOTFOUND;
88     }
89     else if (m_pOperator->IsA(TYPE(OOp_ISNOTNULL)))
90         nRes = GetNotNull(bFirst);
91     else if (m_pOperator->IsA(TYPE(OOp_ISNULL)))
92         nRes = GetNull(bFirst);
93     else if (m_pOperator->IsA(TYPE(OOp_LIKE)))
94         nRes = GetLike(bFirst);
95     else if (m_pOperator->IsA(TYPE(OOp_COMPARE)))
96         nRes = GetCompare(bFirst);
97 
98     return nRes;
99 }
100 
101 //------------------------------------------------------------------
102 ONDXKey* OIndexIterator::GetFirstKey(ONDXPage* pPage, const OOperand& rKey)
103 {
104     // sucht den vorgegeben key
105     // Besonderheit: gelangt der Algorithmus ans Ende
106     // wird immer die aktuelle Seite und die Knotenposition vermerkt
107     // auf die die Bedingung <= zutrifft
108     // dieses findet beim Insert besondere Beachtung
109     //  ONDXIndex* m_pIndex = GetNDXIndex();
110     OOp_COMPARE aTempOp(SQLFilterOperator::GREATER);
111     sal_uInt16 i = 0;
112 
113     if (pPage->IsLeaf())
114     {
115         // im blatt wird die eigentliche Operation ausgefuehrt, sonst die temp. (>)
116         while (i < pPage->Count() && !m_pOperator->operate(&((*pPage)[i]).GetKey(),&rKey))
117                i++;
118     }
119     else
120         while (i < pPage->Count() && !aTempOp.operate(&((*pPage)[i]).GetKey(),&rKey))
121                i++;
122 
123 
124     ONDXKey* pFoundKey = NULL;
125     if (!pPage->IsLeaf())
126     {
127         // weiter absteigen
128         ONDXPagePtr aPage = (i==0) ? pPage->GetChild(m_pIndex)
129                                      : ((*pPage)[i-1]).GetChild(m_pIndex, pPage);
130         pFoundKey = aPage.Is() ? GetFirstKey(aPage, rKey) : NULL;
131     }
132     else if (i == pPage->Count())
133     {
134         pFoundKey = NULL;
135     }
136     else
137     {
138         pFoundKey = &(*pPage)[i].GetKey();
139         if (!m_pOperator->operate(pFoundKey,&rKey))
140             pFoundKey = NULL;
141 
142         m_aCurLeaf = pPage;
143         m_nCurNode = pFoundKey ? i : i - 1;
144     }
145     return pFoundKey;
146 }
147 
148 //------------------------------------------------------------------
149 sal_uIntPtr OIndexIterator::GetCompare(sal_Bool bFirst)
150 {
151     ONDXKey* pKey = NULL;
152     //  ONDXIndex* m_pIndex = GetNDXIndex();
153     sal_Int32 ePredicateType = PTR_CAST(file::OOp_COMPARE,m_pOperator)->getPredicateType();
154 
155     if (bFirst)
156     {
157         // Vorbereitung , auf kleinstes Element positionieren
158         ONDXPage* pPage = m_aRoot;
159         switch (ePredicateType)
160         {
161             case SQLFilterOperator::NOT_EQUAL:
162             case SQLFilterOperator::LESS:
163             case SQLFilterOperator::LESS_EQUAL:
164                 while (pPage && !pPage->IsLeaf())
165                     pPage = pPage->GetChild(m_pIndex);
166 
167                 m_aCurLeaf = pPage;
168                 m_nCurNode = NODE_NOTFOUND;
169         }
170 
171 
172         switch (ePredicateType)
173         {
174             case SQLFilterOperator::NOT_EQUAL:
175                 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ;
176                 break;
177             case SQLFilterOperator::LESS:
178                 while ( ( ( pKey = GetNextKey() ) != NULL ) && pKey->getValue().isNull()) ;
179                 break;
180             case SQLFilterOperator::LESS_EQUAL:
181                 while ( ( pKey = GetNextKey() ) != NULL ) ;
182                 break;
183             case SQLFilterOperator::GREATER_EQUAL:
184             case SQLFilterOperator::EQUAL:
185                 pKey = GetFirstKey(m_aRoot,*m_pOperand);
186                 break;
187             case SQLFilterOperator::GREATER:
188                 pKey = GetFirstKey(m_aRoot,*m_pOperand);
189                 if ( !pKey )
190                     while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand)) ;
191         }
192     }
193     else
194     {
195         switch (ePredicateType)
196         {
197             case SQLFilterOperator::NOT_EQUAL:
198                 while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand))
199                     ;
200                 break;
201             case SQLFilterOperator::LESS:
202             case SQLFilterOperator::LESS_EQUAL:
203             case SQLFilterOperator::EQUAL:
204                 if ( ( ( pKey = GetNextKey() ) == NULL )  || !m_pOperator->operate(pKey,m_pOperand))
205                 {
206                     pKey = NULL;
207                     m_aCurLeaf = NULL;
208                 }
209                 break;
210             case SQLFilterOperator::GREATER_EQUAL:
211             case SQLFilterOperator::GREATER:
212                 pKey = GetNextKey();
213         }
214     }
215 
216     return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
217 }
218 
219 //------------------------------------------------------------------
220 sal_uIntPtr OIndexIterator::GetLike(sal_Bool bFirst)
221 {
222     //  ONDXIndex* m_pIndex = GetNDXIndex();
223     if (bFirst)
224     {
225         ONDXPage* pPage = m_aRoot;
226 
227         while (pPage && !pPage->IsLeaf())
228             pPage = pPage->GetChild(m_pIndex);
229 
230         m_aCurLeaf = pPage;
231         m_nCurNode = NODE_NOTFOUND;
232     }
233 
234     ONDXKey* pKey;
235     while ( ( ( pKey = GetNextKey() ) != NULL ) && !m_pOperator->operate(pKey,m_pOperand))
236         ;
237     return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
238 }
239 
240 //------------------------------------------------------------------
241 sal_uIntPtr OIndexIterator::GetNull(sal_Bool bFirst)
242 {
243     //  ONDXIndex* m_pIndex = GetNDXIndex();
244     if (bFirst)
245     {
246         ONDXPage* pPage = m_aRoot;
247         while (pPage && !pPage->IsLeaf())
248             pPage = pPage->GetChild(m_pIndex);
249 
250         m_aCurLeaf = pPage;
251         m_nCurNode = NODE_NOTFOUND;
252     }
253 
254     ONDXKey* pKey;
255     if ( ( ( pKey = GetNextKey() ) == NULL ) || !pKey->getValue().isNull())
256     {
257         pKey = NULL;
258         m_aCurLeaf = NULL;
259     }
260     return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
261 }
262 
263 //------------------------------------------------------------------
264 sal_uIntPtr OIndexIterator::GetNotNull(sal_Bool bFirst)
265 {
266     ONDXKey* pKey;
267     //  ONDXIndex* m_pIndex = GetNDXIndex();
268     if (bFirst)
269     {
270         // erst alle NULL werte abklappern
271         for (sal_uIntPtr nRec = GetNull(bFirst);
272              nRec != STRING_NOTFOUND;
273              nRec = GetNull(sal_False))
274                  ;
275         pKey = m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL;
276     }
277     else
278         pKey = GetNextKey();
279 
280     return pKey ? pKey->GetRecord() : STRING_NOTFOUND;
281 }
282 
283 //------------------------------------------------------------------
284 ONDXKey* OIndexIterator::GetNextKey()
285 {
286     //  ONDXIndex* m_pIndex = GetNDXIndex();
287     if (m_aCurLeaf.Is() && ((++m_nCurNode) >= m_aCurLeaf->Count()))
288     {
289         ONDXPage* pPage = m_aCurLeaf;
290         // naechste Seite suchen
291         while (pPage)
292         {
293             ONDXPage* pParentPage = pPage->GetParent();
294             if (pParentPage)
295             {
296                 sal_uInt16 nPos = pParentPage->Search(pPage);
297                 if (nPos != pParentPage->Count() - 1)
298                 {   // Seite gefunden
299                     pPage = (*pParentPage)[nPos+1].GetChild(m_pIndex,pParentPage);
300                     break;
301                 }
302             }
303             pPage = pParentPage;
304         }
305 
306         // jetzt wieder zum Blatt
307         while (pPage && !pPage->IsLeaf())
308             pPage = pPage->GetChild(m_pIndex);
309 
310         m_aCurLeaf = pPage;
311         m_nCurNode = 0;
312     }
313     return m_aCurLeaf.Is() ? &(*m_aCurLeaf)[m_nCurNode].GetKey() : NULL;
314 }
315 
316