All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.db4o.inside.ix.QxPath Maven / Gradle / Ivy

The newest version!
/* Copyright (C) 2004 - 2005  db4objects Inc.  http://www.db4o.com

This file is part of the db4o open source object database.

db4o is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation and as clarified by db4objects' GPL 
interpretation policy, available at
http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
Suite 350, San Mateo, CA 94403, USA.

db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */
package com.db4o.inside.ix;

import com.db4o.*;
import com.db4o.foundation.*;

/**
 * Query Index Path
 */
class QxPath extends TreeInt{
    
    private final QxProcessor _processor;
    
    private QCon _constraint;
    
    final QxPath _parent;
    
    private IxTraverser[] _indexTraversers;
    
    private NIxPaths[] _ixPaths;
    
    private Tree _nCandidates;
    
    private Tree _candidates;
    
    private final int _depth;
    
    
    QxPath(QxProcessor processor, QxPath parent, QCon constraint, int depth){
        super(0);
        _processor = processor;
        _parent = parent;
        _constraint = constraint;
        _depth = depth;
    }
    
    void buildPaths(){
        
        int id = _constraint.identityID();
        if(id > 0){
            processChildCandidates(new TreeInt(id));
            return;
        }

        boolean isLeaf = true;
        Iterator4 i = _constraint.iterateChildren();
        while(i.hasNext()){
            isLeaf = false;
            QCon childConstraint = (QCon)i.next();
            if(childConstraint.canLoadByIndex()){
                new QxPath(_processor, this, childConstraint, _depth + 1).buildPaths();
            }
        }
        if(! isLeaf){
            return;
        }
        if(! _constraint.canLoadByIndex()){
            return;
        }
        
        if(! _constraint.canBeIndexLeaf()){
            return;
        }
        
        _indexTraversers = new IxTraverser[]{new IxTraverser()};
        
        i_key = ((QConObject)_constraint).findBoundsQuery(_indexTraversers[0]);
        
        if(i_key < 0){
            return;
        }
            
        if(Debug.useNIxPaths){
            
            if(i_key > 0){
                
                _ixPaths = new NIxPaths[]{_indexTraversers[0].convert()};

                // FIXME: remove NIxPath redundancies
                // indexPaths.removeRedundancies();
                
                expectNixCount(_ixPaths[0], i_key);
            }
        }
        
        _processor.addPath(this);
    }
    
    private void expectNixCount(NIxPaths ixPaths, int count){
        if(Debug.ixTrees){
            int cnt = ixPaths.count();
            if(count != cnt){
                System.err.println("Different Index candidate count");
                System.err.println("" + count + ", " + cnt);
                // new RuntimeException().printStackTrace();
            }
        }
    }
    

    void load(){
        loadFromIndexTraversers();
        loadFromNixPaths();    
        if(_parent == null){
            return;
        }
        if(Debug.useNIxPaths){
            if(_processor.exceedsLimit(Tree.size(_nCandidates), _depth)){
                return;
            }
        }else{
            if(_processor.exceedsLimit(Tree.size(_candidates), _depth)){
                return;
            }
        }
        
        QxPath parentPath = new QxPath(_processor, _parent._parent , _parent._constraint, _depth - 1);
        if(Debug.useNIxPaths){
            parentPath.processChildCandidates(_nCandidates);
        }else{
            parentPath.processChildCandidates(_candidates);
        }
    }
    
    private void loadFromIndexTraversers(){
        if(_indexTraversers == null){
            return;
        }
        for (int i = 0; i < _indexTraversers.length; i++) {
            _indexTraversers[i].visitAll(new Visitor4() {
                public void visit(Object a_object) {
                    int id = ((Integer)a_object).intValue();
                    if(_candidates == null){
                        _candidates = new TreeInt(id);
                    }else{
                        _candidates = _candidates.add(new TreeInt(id));
                    }
                }
            });
        }
    }
    
    private void loadFromNixPaths(){
        if(! Debug.useNIxPaths){
            return;
        }
        if(_ixPaths == null){
            return;
        }
        for (int i = 0; i < _ixPaths.length; i++) {
            if(_ixPaths[i] != null){
                _ixPaths[i].traverse(new Visitor4() {
                    public void visit(Object a_object) {
                        int id = ((Integer)a_object).intValue();
                        if(_nCandidates == null){
                            _nCandidates = new TreeInt(id);
                        }else{
                            _nCandidates = _nCandidates.add(new TreeInt(id));
                        }
                    }
                });
            }
        }
        compareLoadedNixPaths();
    }
    
    private void compareLoadedNixPaths(){
        
        if(! Debug.ixTrees){
            return;
        }
        
        if(Tree.size(_candidates) != Tree.size(_nCandidates)){
            System.err.println("Different index tree size");
            System.err.println("" + Tree.size(_candidates) + ", " + Tree.size(_nCandidates));
            // new RuntimeException().printStackTrace();
            return;
        }
        
        Tree.traverse(_nCandidates, new Visitor4() {
            public void visit(Object a_object) {
                if(_candidates.find((Tree)a_object) == null){
                    System.err.println("Element not in old tree");
                    System.err.println(a_object);
                    // new RuntimeException().printStackTrace();                                
                }
            }
        });
    }
    
    void processChildCandidates(Tree candidates){
        
        if(candidates == null){
            _processor.addPath(this);
            return;
        }
        
        if(_parent == null){
            _candidates = candidates;
            _nCandidates = candidates;
            _processor.addPath(this);
            return;
        }
        
        _indexTraversers = new IxTraverser[candidates.size()];
        
        if(Debug.useNIxPaths){
            _ixPaths = new NIxPaths[candidates.size()];
        }
        
        
        final int[] ix = new int[]{0};
        final boolean[] err = new boolean[] {false};
        candidates.traverse(new Visitor4() {
            public void visit(Object a_object) {
                
                int idx = ix[0]++;
                
                _indexTraversers[idx] = new IxTraverser();
                int count = _indexTraversers[idx].findBoundsQuery(_constraint, new Integer(((TreeInt)a_object).i_key));
                if(count >= 0){
                    i_key += count;
                }else{
                    err[0] = true;
                }
                
                if(Debug.useNIxPaths){
                    
                    if(count > 0){
                        _ixPaths[idx] = _indexTraversers[idx].convert();
                        
                        expectNixCount(_ixPaths[idx], count);
                        
                    }
                    
                }
                
            }
        });
        if(err[0]){
            return;
        }
        _processor.addPath(this);
    }
    
    

    public boolean isTopLevelComplete() {
        
        if(_parent == null){
            
            //FIXME: and if all joins are evaluated
            
            return true;
            
        }
        return false;
    }
    
    boolean onSameFieldAs(QxPath other){
        return _constraint.onSameFieldAs(other._constraint);
    }
    
    Tree toQCandidates(QCandidates candidates){
        if(Debug.useNIxPaths){
            return TreeInt.toQCandidate((TreeInt)_nCandidates, candidates);
        }
        return TreeInt.toQCandidate((TreeInt)_candidates, candidates);
    }
    
    void mergeForSameField(QxPath other){
        if(other._ixPaths == null){
            return;
        }
        int oldCount = _ixPaths[0].count();
        for (int i = 0; i < other._ixPaths.length; i++) {
            if(other._ixPaths[i] != null){
                other._ixPaths[i]._paths.traverse(new Visitor4() {
                    public void visit(Object a_object) {
                        _ixPaths[0].add((NIxPath)a_object);
                    }
                });
            }
        }
        int newCount = _ixPaths[0].count();
        i_key += newCount - oldCount;
    }
    
    
    

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy