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 //==================================================================
39 //==================================================================
40 //------------------------------------------------------------------
41 OIndexIterator::~OIndexIterator()
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
;
64 m_aRoot
= m_pIndex
->getRoot();
70 // Preparation, position on the smallest element
73 ONDXPage
* pPage
= m_aRoot
;
74 while (pPage
&& !pPage
->IsLeaf())
75 pPage
= pPage
->GetChild(m_pIndex
);
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
);
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
);
108 // in the leaf the actual operation is run, otherwise temp. (>)
109 while (i
< pPage
->Count() && !m_pOperator
->operate(&((*pPage
)[i
]).GetKey(),&rKey
))
113 while (i
< pPage
->Count() && !aTempOp
.operate(&((*pPage
)[i
]).GetKey(),&rKey
))
117 ONDXKey
* pFoundKey
= NULL
;
118 if (!pPage
->IsLeaf())
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())
131 pFoundKey
= &(*pPage
)[i
].GetKey();
132 if (!m_pOperator
->operate(pFoundKey
,&rKey
))
136 m_nCurNode
= pFoundKey
? i
: i
- 1;
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();
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
);
160 m_nCurNode
= NODE_NOTFOUND
;
164 switch (ePredicateType
)
166 case SQLFilterOperator::NOT_EQUAL
:
167 while ( ( ( pKey
= GetNextKey() ) != NULL
) && !m_pOperator
->operate(pKey
,m_pOperand
)) ;
169 case SQLFilterOperator::LESS
:
170 while ( ( ( pKey
= GetNextKey() ) != NULL
) && pKey
->getValue().isNull()) ;
172 case SQLFilterOperator::LESS_EQUAL
:
173 while ( ( pKey
= GetNextKey() ) != NULL
) ;
175 case SQLFilterOperator::GREATER_EQUAL
:
176 case SQLFilterOperator::EQUAL
:
177 pKey
= GetFirstKey(m_aRoot
,*m_pOperand
);
179 case SQLFilterOperator::GREATER
:
180 pKey
= GetFirstKey(m_aRoot
,*m_pOperand
);
182 while ( ( ( pKey
= GetNextKey() ) != NULL
) && !m_pOperator
->operate(pKey
,m_pOperand
)) ;
187 switch (ePredicateType
)
189 case SQLFilterOperator::NOT_EQUAL
:
190 while ( ( ( pKey
= GetNextKey() ) != NULL
) && !m_pOperator
->operate(pKey
,m_pOperand
))
193 case SQLFilterOperator::LESS
:
194 case SQLFilterOperator::LESS_EQUAL
:
195 case SQLFilterOperator::EQUAL
:
196 if ( ( ( pKey
= GetNextKey() ) == NULL
) || !m_pOperator
->operate(pKey
,m_pOperand
))
202 case SQLFilterOperator::GREATER_EQUAL
:
203 case SQLFilterOperator::GREATER
:
208 return pKey
? pKey
->GetRecord() : STRING_NOTFOUND
;
211 //------------------------------------------------------------------
212 sal_uIntPtr
OIndexIterator::GetLike(sal_Bool bFirst
)
216 ONDXPage
* pPage
= m_aRoot
;
218 while (pPage
&& !pPage
->IsLeaf())
219 pPage
= pPage
->GetChild(m_pIndex
);
222 m_nCurNode
= NODE_NOTFOUND
;
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
)
236 ONDXPage
* pPage
= m_aRoot
;
237 while (pPage
&& !pPage
->IsLeaf())
238 pPage
= pPage
->GetChild(m_pIndex
);
241 m_nCurNode
= NODE_NOTFOUND
;
245 if ( ( ( pKey
= GetNextKey() ) == NULL
) || !pKey
->getValue().isNull())
250 return pKey
? pKey
->GetRecord() : STRING_NOTFOUND
;
253 //------------------------------------------------------------------
254 sal_uIntPtr
OIndexIterator::GetNotNull(sal_Bool 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
;
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
;
281 ONDXPage
* pParentPage
= pPage
->GetParent();
284 sal_uInt16 nPos
= pParentPage
->Search(pPage
);
285 if (nPos
!= pParentPage
->Count() - 1)
287 pPage
= (*pParentPage
)[nPos
+1].GetChild(m_pIndex
,pParentPage
);
294 // now go on with leaf
295 while (pPage
&& !pPage
->IsLeaf())
296 pPage
= pPage
->GetChild(m_pIndex
);
301 return m_aCurLeaf
.Is() ? &(*m_aCurLeaf
)[m_nCurNode
].GetKey() : NULL
;
304 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */