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