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 //------------------------------------------------------------------ 38 OIndexIterator::~OIndexIterator() 39 { 40 // m_pIndex->UnLock(); 41 m_pIndex->release(); 42 } 43 44 //------------------------------------------------------------------ 45 sal_uIntPtr OIndexIterator::First() 46 { 47 return Find(sal_True); 48 } 49 50 //------------------------------------------------------------------ 51 sal_uIntPtr OIndexIterator::Next() 52 { 53 return Find(sal_False); 54 } 55 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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 //------------------------------------------------------------------ 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