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