Package com.hp.hpl.jena.sparql.algebra.optimize

Source Code of com.hp.hpl.jena.sparql.algebra.optimize.Optimize$RewriterFactory

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.hp.hpl.jena.sparql.algebra.optimize;

import org.slf4j.Logger ;
import org.slf4j.LoggerFactory ;

import com.hp.hpl.jena.query.ARQ ;
import com.hp.hpl.jena.sparql.ARQConstants ;
import com.hp.hpl.jena.sparql.algebra.Op ;
import com.hp.hpl.jena.sparql.algebra.OpWalker ;
import com.hp.hpl.jena.sparql.algebra.Transform ;
import com.hp.hpl.jena.sparql.algebra.TransformCopy;
import com.hp.hpl.jena.sparql.algebra.Transformer ;
import com.hp.hpl.jena.sparql.algebra.op.OpLabel ;
import com.hp.hpl.jena.sparql.engine.ExecutionContext ;
import com.hp.hpl.jena.sparql.util.Context ;
import com.hp.hpl.jena.sparql.util.Symbol ;


public class Optimize implements Rewrite
{
    static private Logger log = LoggerFactory.getLogger(Optimize.class) ;

    // A small (one slot) registry to allow plugging in an alternative optimizer
    public interface RewriterFactory { Rewrite create(Context context) ; }
   
    // ----   
    public static RewriterFactory noOptimizationFactory = new RewriterFactory()
    {
        @Override
        public Rewrite create(Context context)
        {
            return new Rewrite() {

                @Override
                public Op rewrite(Op op)
                {
                    return op ;
                }} ;
        }} ;
       
    public static RewriterFactory stdOptimizationFactory = new RewriterFactory()
    {
        @Override
        public Rewrite create(Context context)
        {
            return new Optimize(context) ;
        }
    } ;
   
    // Set this to a different factory implementation to have a different general optimizer. 
    private static RewriterFactory factory = stdOptimizationFactory ;
   
    // ----       
       
    public static Op optimize(Op op, ExecutionContext execCxt)
    {
        return optimize(op, execCxt.getContext()) ;
    }

    // The execution-independent optimizations
    public static Op optimize(Op op, Context context)
    {
        Rewrite opt = decideOptimizer(context) ;
        return opt.rewrite(op) ;
    }

    /** Set the global optimizer factory to one that does nothing */
    public static void noOptimizer()
    {
        setFactory(noOptimizationFactory) ;
    }

    static private Rewrite decideOptimizer(Context context)
    {
        RewriterFactory f = (RewriterFactory)context.get(ARQConstants.sysOptimizerFactory) ;
        if ( f == null )
            f = factory ;
        if ( f == null )
            f = stdOptimizationFactory ;    // Only if default 'factory' gets lost.
        return f.create(context) ;
    }

   
    /** Globably set the factory for making optimizers */
    public static void setFactory(RewriterFactory aFactory)
    { factory = aFactory ; }

    /** Get the global factory for making optimizers */
    public static RewriterFactory getFactory()
    { return factory ; }
   
    // ---- The object proper for the standard optimizations
   
    private final Context context ;
    private Optimize(ExecutionContext execCxt)
    {
        this(execCxt.getContext()) ;
    }
   
    private Optimize(Context context)
    {
        this.context = context ;
    }

    /** Alternative name for compatibility only */
    public static final Symbol filterPlacementOldName = ARQConstants.allocSymbol("filterPlacement") ;
   
    @Override
    public Op rewrite(Op op)
    {
        // Record optimizer
        if ( context.get(ARQConstants.sysOptimizer) == null )
            context.set(ARQConstants.sysOptimizer, this) ;
       
        // Old name, new name fixup.
        if ( context.isDefined(filterPlacementOldName) )
        {
            if ( context.isUndef(ARQ.optFilterPlacement) )
                context.set(ARQ.optFilterPlacement, context.get(filterPlacementOldName)) ;
        }
       
        if ( false )
        {
            // Removal of "group of one" join (AKA SPARQL "simplification")
            // is done during algebra generation in AlgebraGenerator
            op = apply("Simplify", new TransformSimplify(), op) ;
            op = apply("Delabel", new TransformRemoveLabels(), op) ;
        }

        // ** TransformScopeRename::
        // This is a requirement for the linearization execution that the default
        // ARQ query engine uses where possible. 
        // This transformation must be done (e.g. by QueryEngineBase) if no other optimization is done.
        op = TransformScopeRename.transform(op) ;
       
        // Prepare expressions.
        OpWalker.walk(op, new OpVisitorExprPrepare(context)) ;
       
        // Convert paths to triple patterns if possible.
        if ( context.isTrueOrUndef(ARQ.optPathFlatten) )
            op = apply("Path flattening", new TransformPathFlattern(), op) ;

        // Expression constant folding
        if ( context.isTrueOrUndef(ARQ.optExprConstantFolding) )
            op = Transformer.transform(new TransformCopy(), new ExprTransformConstantFold(), op);
       
        // Need to allow subsystems to play with this list.
       
        if ( context.isTrueOrUndef(ARQ.propertyFunctions) )
            op = apply("Property Functions", new TransformPropertyFunction(context), op) ;

        if ( context.isTrueOrUndef(ARQ.optFilterConjunction) )
            op = apply("filter conjunctions to ExprLists", new TransformFilterConjunction(), op) ;

        if ( context.isTrueOrUndef(ARQ.optFilterExpandOneOf) )
            op = apply("Break up IN and NOT IN", new TransformExpandOneOf(), op) ;

        // Apply some general purpose filter transformations
               
        if ( context.isTrueOrUndef(ARQ.optFilterImplicitJoin) )
            op = apply("Filter Implicit Join", new TransformFilterImplicitJoin(), op);
       
        if ( context.isTrueOrUndef(ARQ.optImplicitLeftJoin) )
            op = apply("Implicit Left Join", new TransformImplicitLeftJoin(), op);
               
        if ( context.isTrueOrUndef(ARQ.optFilterDisjunction) )
            op = apply("Filter Disjunction", new TransformFilterDisjunction(), op) ;
       
        // Some ORDER BY-LIMIT N queries can be done more efficiently by only recording
        // the top N items, so a full sort is not needed.
        if ( context.isTrueOrUndef(ARQ.optTopNSorting) )
            op = apply("TopN Sorting", new TransformTopN(), op) ;
       
        // ORDER BY+DISTINCT optimizations
        // We apply the one that changes evaluation order first since when it does apply it will give much
        // better performance than just transforming DISTINCT to REDUCED
       
        if ( context.isTrueOrUndef(ARQ.optOrderByDistinctApplication) )
            op = apply("Apply DISTINCT prior to ORDER BY where possible", new TransformOrderByDistinctApplication(), op);

        // Transform some DISTINCT to REDUCED, slightly more liberal transform that ORDER BY+DISTINCT application
        // Reduces memory consumption.
        if ( context.isTrueOrUndef(ARQ.optDistinctToReduced) )
            op = apply("Distinct replaced with reduced", new TransformDistinctToReduced(), op) ;
       
        // Find joins/leftJoin that can be done by index joins (generally preferred as fixed memory overhead).
        if ( context.isTrueOrUndef(ARQ.optIndexJoinStrategy) )
            op = apply("Index Join strategy", new TransformJoinStrategy(), op) ;
       
        // Place filters close to where their dependency variables are defined.
        // This prunes the output of that step as early as possible.
        // If done before TransformJoinStrategy, you can get two applications
        // of a filter in a (sequence) from each half of a (join).  This is harmless,
        // because filters are generally cheap, but it looks a bit bad.
        if ( context.isTrueOrUndef(ARQ.optFilterPlacement) ) {
            if ( context.isTrue(ARQ.optFilterPlacementConservative))
                op = apply("Filter Placement (conservative)", new TransformFilterPlacementConservative(), op) ;
            else {
                // Whether to push into BGPs
                boolean b = context.isTrueOrUndef(ARQ.optFilterPlacementBGP) ;
                op = apply("Filter Placement", new TransformFilterPlacement(b), op) ;
            }
        }
       
        // Replace suitable FILTER(?x = TERM) with (assign) and write the TERm for ?x in the pattern.   
        // Apply (possible a second time) after FILTER placement as it can create new possibilities.
        // See JENA-616.
        if ( context.isTrueOrUndef(ARQ.optFilterEquality) )
            op = apply("Filter Equality", new TransformFilterEquality(), op) ;
               
        // Replace suitable FILTER(?x != TERM) with (minus (original) (table)) where the table contains
        // the candidate rows to be eliminated
        // Off by default due to minimal performance difference
        if ( context.isTrue(ARQ.optFilterInequality) )
            op = apply("Filter Inequality", new TransformFilterInequality(), op);
       
        // Promote table empty as late as possible since this will only be produced by other
        // optimizations and never directly from algebra generation
        if ( context.isTrueOrUndef(ARQ.optPromoteTableEmpty) )
            op = apply("Table Empty Promotion", new TransformPromoteTableEmpty(), op) ;

        // Merge adjacent BGPs
        if ( context.isTrueOrUndef(ARQ.optMergeBGPs) )
            op = apply("Merge BGPs", new TransformMergeBGPs(), op) ;
       
        // Mark
        if ( false )
            op = OpLabel.create("Transformed", op) ;
        return op ;
    }
   
    public static Op apply(Transform transform, Op op)
    {
        Op op2 = Transformer.transformSkipService(transform, op) ;
        if ( op2 != op )
            return op2 ;
        return op ;
    }
   
    public static Op apply(String label, Transform transform, Op op)
    {
        // Use this to apply inside NOT EXISTS and EXISTS
        // Transform transform2 = new TransformApplyInsideExprFunctionOp(transform) ;
        // Remember there is an outer substitue to the NOT EXISTS operation.

        //Transform transform2 = new TransformApplyInsideExprFunctionOp(transform) ;
       
        Op op2 = Transformer.transformSkipService(transform, op) ;
       
        final boolean debug = false ;
       
        if ( debug )
        {
            if ( label != null && log.isInfoEnabled() )
                    log.info("Transform: "+label) ;
            if ( op == op2 )
            {
                if ( log.isInfoEnabled() )
                    log.info("No change (==)") ;
                return op2 ;
            }

            if ( op.equals(op2) )
            {
                if ( log.isInfoEnabled() )
                    log.info("No change (equals)") ;
                return op2 ;
            }
            if ( log.isInfoEnabled() )
            {
                log.info("\n"+op.toString()) ;
                log.info("\n"+op2.toString()) ;
            }
        }
        if ( op2 != op )
            return op2 ;
        return op ;
    }
}
TOP

Related Classes of com.hp.hpl.jena.sparql.algebra.optimize.Optimize$RewriterFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.