1 21 package com.db4o; 22 23 import com.db4o.foundation.*; 24 import com.db4o.inside.classindex.*; 25 import com.db4o.inside.diagnostic.DiagnosticProcessor; 26 import com.db4o.inside.fieldindex.*; 27 import com.db4o.inside.marshall.*; 28 29 36 public final class QCandidates implements Visitor4 { 37 38 public final Transaction i_trans; 40 41 public Tree i_root; 43 44 private List4 i_constraints; 46 47 YapClass i_yapClass; 49 50 private QField i_field; 52 53 QCon i_currentConstraint; 55 56 Tree i_ordered; 58 59 private int i_orderID; 61 62 private IDGenerator _idGenerator; 63 64 QCandidates(Transaction a_trans, YapClass a_yapClass, QField a_field) { 65 i_trans = a_trans; 66 i_yapClass = a_yapClass; 67 i_field = a_field; 68 69 if (a_field == null 70 || a_field.i_yapField == null 71 || !(a_field.i_yapField.getHandler() instanceof YapClass) 72 ) { 73 return; 74 } 75 76 YapClass yc = (YapClass) a_field.i_yapField.getHandler(); 77 if (i_yapClass == null) { 78 i_yapClass = yc; 79 } else { 80 yc = i_yapClass.getHigherOrCommonHierarchy(yc); 81 if (yc != null) { 82 i_yapClass = yc; 83 } 84 } 85 } 86 87 public QCandidate addByIdentity(QCandidate candidate) { 88 i_root = Tree.add(i_root, candidate); 89 if(candidate._size == 0){ 90 91 94 98 return candidate.getRoot(); 99 100 } 101 return candidate; 102 } 103 104 void addConstraint(QCon a_constraint) { 105 i_constraints = new List4(i_constraints, a_constraint); 106 } 107 108 void addOrder(QOrder a_order) { 109 i_ordered = Tree.add(i_ordered, a_order); 110 } 111 112 void applyOrdering(Tree a_ordered, int a_orderID) { 113 if (a_ordered == null || i_root == null) { 114 return; 115 } 116 if (a_orderID > 0) { 117 a_orderID = -a_orderID; 118 } 119 final boolean major = (a_orderID - i_orderID) < 0; 120 if (major) { 121 i_orderID = a_orderID; 122 } 123 124 final int[] placement = { 0 }; 125 i_root.traverse(new Visitor4() { 128 public void visit(Object a_object) { 129 ((QCandidate) a_object).hintOrder(0, major); 130 ((QCandidate) a_object).hintOrder(placement[0]++, !major); 131 } 132 }); 133 134 placement[0] = 1; 136 a_ordered.traverse(new Visitor4() { 137 public void visit(Object a_object) { 138 QOrder qo = (QOrder) a_object; 139 QCandidate candidate = qo._candidate.getRoot(); 140 candidate.hintOrder(placement[0]++, major); 141 } 142 }); 143 144 final Collection4 col = new Collection4(); 147 i_root.traverse(new Visitor4() { 148 public void visit(Object a_object) { 149 QCandidate candidate = (QCandidate) a_object; 150 col.add(candidate); 151 } 152 }); 153 154 Tree newTree = null; 156 Iterator4 i = col.iterator(); 157 while(i.moveNext()){ 158 QCandidate candidate = (QCandidate) i.current(); 159 candidate._preceding = null; 160 candidate._subsequent = null; 161 candidate._size = 1; 162 newTree = Tree.add(newTree, candidate); 163 } 164 165 i_root = newTree; 166 } 167 168 void collect(final QCandidates a_candidates) { 169 Iterator4 i = iterateConstraints(); 170 while(i.moveNext()){ 171 QCon qCon = (QCon)i.current(); 172 setCurrentConstraint(qCon); 173 qCon.collect(a_candidates); 174 } 175 setCurrentConstraint(null); 176 } 177 178 void execute() { 179 if(DTrace.enabled){ 180 DTrace.QUERY_PROCESS.log(); 181 } 182 final FieldIndexProcessorResult result = processFieldIndexes(); 183 if(result.foundIndex()){ 184 i_root = result.toQCandidate(this); 185 }else{ 186 loadFromClassIndex(); 187 } 188 evaluate(); 189 } 190 191 public Iterator4 executeSnapshot(Collection4 executionPath){ 192 IntIterator4 indexIterator = new IntIterator4Adaptor(iterateIndex(processFieldIndexes())); 193 Tree idRoot = TreeInt.addAll(null, indexIterator); 194 Iterator4 snapshotIterator = new TreeKeyIterator(idRoot); 195 Iterator4 singleObjectQueryIterator = singleObjectSodaProcessor(snapshotIterator); 196 return mapIdsToExecutionPath(singleObjectQueryIterator, executionPath); 197 } 198 199 private Iterator4 singleObjectSodaProcessor(Iterator4 indexIterator){ 200 return new MappingIterator(indexIterator) { 201 protected Object map(Object current) { 202 int id = ((Integer )current).intValue(); 203 QCandidate candidate = new QCandidate(QCandidates.this, null, id, true); 204 i_root = candidate; 205 evaluate(); 206 if(! candidate.include()){ 207 return MappingIterator.SKIP; 208 } 209 return current; 210 } 211 }; 212 } 213 214 public Iterator4 executeLazy(Collection4 executionPath){ 215 Iterator4 indexIterator = iterateIndex(processFieldIndexes()); 216 Iterator4 singleObjectQueryIterator = singleObjectSodaProcessor(indexIterator); 217 return mapIdsToExecutionPath(singleObjectQueryIterator, executionPath); 218 } 219 220 private Iterator4 iterateIndex (FieldIndexProcessorResult result ){ 221 if(result.noMatch()){ 222 return Iterator4Impl.EMPTY; 223 } 224 if(result.foundIndex()){ 225 return result.iterateIDs(); 226 } 227 if(i_yapClass.isPrimitive()){ 228 return Iterator4Impl.EMPTY; 229 } 230 return BTreeClassIndexStrategy.iterate(i_yapClass, i_trans); 231 } 232 233 private Iterator4 mapIdsToExecutionPath(Iterator4 singleObjectQueryIterator, Collection4 executionPath) { 234 235 if(executionPath == null){ 236 return singleObjectQueryIterator; 237 } 238 239 Iterator4 res = singleObjectQueryIterator; 240 241 Iterator4 executionPathIterator = executionPath.iterator(); 242 while(executionPathIterator.moveNext()){ 243 244 final String fieldName = (String ) executionPathIterator.current(); 245 246 Iterator4 mapIdToFieldIdsIterator = new MappingIterator(res){ 247 248 protected Object map(Object current) { 249 int id = ((Integer )current).intValue(); 250 YapWriter reader = stream().readWriterByID(i_trans, id); 251 if (reader == null) { 252 return MappingIterator.SKIP; 253 } 254 255 ObjectHeader oh = new ObjectHeader(stream(), reader); 256 257 Tree idTree = oh.yapClass().collectFieldIDs( 258 oh._marshallerFamily, 259 oh._headerAttributes, 260 null, 261 reader, 262 fieldName); 263 264 return new TreeKeyIterator(idTree); 265 } 266 267 }; 268 269 res = new CompositeIterator4(mapIdToFieldIdsIterator); 270 271 } 272 return res; 273 } 274 275 public YapStream stream() { 276 return i_trans.stream(); 277 } 278 279 public int classIndexEntryCount() { 280 return i_yapClass.indexEntryCount(i_trans); 281 } 282 283 private FieldIndexProcessorResult processFieldIndexes() { 284 if(i_constraints == null){ 285 return FieldIndexProcessorResult.NO_INDEX_FOUND; 286 } 287 return new FieldIndexProcessor(this).run(); 288 } 289 290 void evaluate() { 291 292 if (i_constraints == null) { 293 return; 294 } 295 296 Iterator4 i = iterateConstraints(); 297 while(i.moveNext()){ 298 QCon qCon = (QCon)i.current(); 299 qCon.setCandidates(this); 300 qCon.evaluateSelf(); 301 } 302 303 i = iterateConstraints(); 304 while(i.moveNext()){ 305 ((QCon)i.current()).evaluateSimpleChildren(); 306 } 307 308 i = iterateConstraints(); 309 while(i.moveNext()){ 310 ((QCon)i.current()).evaluateEvaluations(); 311 } 312 313 i = iterateConstraints(); 314 while(i.moveNext()){ 315 ((QCon)i.current()).evaluateCreateChildrenCandidates(); 316 } 317 318 i = iterateConstraints(); 319 while(i.moveNext()){ 320 ((QCon)i.current()).evaluateCollectChildren(); 321 } 322 323 i = iterateConstraints(); 324 while(i.moveNext()){ 325 ((QCon)i.current()).evaluateChildren(); 326 } 327 } 328 329 boolean isEmpty() { 330 final boolean[] ret = new boolean[] { true }; 331 traverse(new Visitor4() { 332 public void visit(Object obj) { 333 if (((QCandidate) obj)._include) { 334 ret[0] = false; 335 } 336 } 337 }); 338 return ret[0]; 339 } 340 341 boolean filter(Visitor4 a_host) { 342 if (i_root != null) { 343 i_root.traverse(a_host); 344 i_root = i_root.filter(new Predicate4() { 345 public boolean match(Object a_candidate) { 346 return ((QCandidate) a_candidate)._include; 347 } 348 }); 349 } 350 351 return i_root != null; 352 } 353 354 int generateCandidateId(){ 355 if(_idGenerator == null){ 356 _idGenerator = new IDGenerator(); 357 } 358 return - _idGenerator.next(); 359 } 360 361 public Iterator4 iterateConstraints(){ 362 if(i_constraints == null){ 363 return Iterator4Impl.EMPTY; 364 } 365 return new Iterator4Impl(i_constraints); 366 } 367 368 final static class TreeIntBuilder { 369 public TreeInt tree; 370 371 public void add(TreeInt node) { 372 tree = (TreeInt)Tree.add(tree, node); 373 } 374 } 375 376 void loadFromClassIndex() { 377 if (!isEmpty()) { 378 return; 379 } 380 381 final TreeIntBuilder result = new TreeIntBuilder(); 382 final ClassIndexStrategy index = i_yapClass.index(); 383 index.traverseAll(i_trans, new Visitor4() { 384 public void visit(Object obj) { 385 result.add(new QCandidate(QCandidates.this, null, ((Integer )obj).intValue(), true)); 386 } 387 }); 388 389 i_root = result.tree; 390 391 DiagnosticProcessor dp = i_trans.stream().i_handlers._diagnosticProcessor; 392 if (dp.enabled()){ 393 dp.loadedFromClassIndex(i_yapClass); 394 } 395 396 } 397 398 void setCurrentConstraint(QCon a_constraint) { 399 i_currentConstraint = a_constraint; 400 } 401 402 void traverse(Visitor4 a_visitor) { 403 if(i_root != null){ 404 i_root.traverse(a_visitor); 405 } 406 } 407 408 boolean tryAddConstraint(QCon a_constraint) { 409 410 if (i_field != null) { 411 QField qf = a_constraint.getField(); 412 if (qf != null) { 413 if (i_field.i_name != qf.i_name) { 414 return false; 415 } 416 } 417 } 418 419 if (i_yapClass == null || a_constraint.isNullConstraint()) { 420 addConstraint(a_constraint); 421 return true; 422 } 423 YapClass yc = a_constraint.getYapClass(); 424 if (yc != null) { 425 yc = i_yapClass.getHigherOrCommonHierarchy(yc); 426 if (yc != null) { 427 i_yapClass = yc; 428 addConstraint(a_constraint); 429 return true; 430 } 431 } 432 return false; 433 } 434 435 public void visit(Object a_tree) { 436 final QCandidate parent = (QCandidate) a_tree; 437 if (parent.createChild(this)) { 438 return; 439 } 440 441 Iterator4 i = iterateConstraints(); 445 while(i.moveNext()){ 446 ((QCon)i.current()).visitOnNull(parent.getRoot()); 447 } 448 449 } 450 } 451 | Popular Tags |