You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2015/07/07 11:24:24 UTC

[19/26] jena git commit: Merge branch 'master' into eliminate-assignments-jena3

http://git-wip-us.apache.org/repos/asf/jena/blob/9d684173/jena-arq/src/main/java/org/apache/jena/query/ARQ.java
----------------------------------------------------------------------
diff --cc jena-arq/src/main/java/org/apache/jena/query/ARQ.java
index 0000000,420e3b9..5ba3074
mode 000000,100644..100644
--- a/jena-arq/src/main/java/org/apache/jena/query/ARQ.java
+++ b/jena-arq/src/main/java/org/apache/jena/query/ARQ.java
@@@ -1,0 -1,582 +1,594 @@@
+ /*
+  * 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 org.apache.jena.query;
+ 
+ import org.apache.jena.riot.RIOT ;
+ import org.apache.jena.sparql.ARQConstants ;
+ import org.apache.jena.sparql.SystemARQ ;
+ import org.apache.jena.sparql.algebra.optimize.TransformOrderByDistinctApplication ;
+ import org.apache.jena.sparql.engine.http.Service ;
+ import org.apache.jena.sparql.engine.main.StageBuilder ;
+ import org.apache.jena.sparql.lib.Metadata ;
+ import org.apache.jena.sparql.mgt.ARQMgt ;
+ import org.apache.jena.sparql.mgt.Explain ;
+ import org.apache.jena.sparql.mgt.SystemInfo ;
+ import org.apache.jena.sparql.mgt.Explain.InfoLevel ;
+ import org.apache.jena.sparql.util.Context ;
+ import org.apache.jena.sparql.util.MappingRegistry ;
+ import org.apache.jena.sparql.util.Symbol ;
+ import org.slf4j.Logger ;
+ import org.slf4j.LoggerFactory ;
+ 
+ /** ARQ - miscellaneous settings */
+ 
+ public class ARQ
+ {
+     /** Name of the execution logger */
+     public static final String logExecName = "com.hp.hpl.jena.arq.exec" ;
+     
+     /** Name of the information logger */
+     public static final String logInfoName = "com.hp.hpl.jena.arq.info" ;
+     
+     /** Name of the logger for remote HTTP requests */
+     public static final String logHttpRequestName = "com.hp.hpl.jena.arq.service" ;
+     
+     private static final Logger logExec = LoggerFactory.getLogger(logExecName) ;
+     private static final Logger logInfo = LoggerFactory.getLogger(logInfoName) ;
+     private static final Logger logHttpRequest = LoggerFactory.getLogger(logHttpRequestName) ;
+ 
+     /** The execution logger */
+     public static Logger getExecLogger() { return logExec ; }
+     
+     /** The information logger */
+     public static Logger getInfoLogger() { return logInfo ; }
+     
+     /** The HTTP Request logger */
+     public static Logger getHttpRequestLogger() { return logHttpRequest ; }
+ 
+     /** Symbol to enable logging of execution.  
+      * Must also set log4j, or other logging system,
+      * for logger "com.hp.hpl.jena.sparql.exec"
+      * e.g. log4j.properties -- log4j.logger.com.hp.hpl.jena.sparql.exec=INFO
+      * See the <a href="http://jena.apache.org/documentation/query/logging.html">ARQ Logging Documentation</a>.
+      */
+     public static final Symbol symLogExec           = ARQConstants.allocSymbol("logExec") ;
+     
+     /** Get the currently global execution logging setting */  
+     public static Explain.InfoLevel getExecutionLogging() { return (Explain.InfoLevel)ARQ.getContext().get(ARQ.symLogExec) ; }
+     
+     /** Set execution logging - logging is to logger "com.hp.hpl.jena.arq.exec" at level INFO.
+      *  An appropriate logging configuration is also required.
+      */
+     public static void setExecutionLogging(Explain.InfoLevel infoLevel)
+     {
+         if ( InfoLevel.NONE.equals(infoLevel) )
+         {
+             ARQ.getContext().unset(ARQ.symLogExec) ;
+             return ;
+         }
+         
+         ARQ.getContext().set(ARQ.symLogExec, infoLevel) ;
+ //        if ( ! getExecLogger().isInfoEnabled() )
+ //            getExecLogger().warn("Attempt to enable execution logging but the logger '"+logExecName+"' is not logging at level INFO") ;
+     }
+ 
+     /** IRI for ARQ */  
+     public static final String arqIRI = "http://jena.hpl.hp.com/#arq" ;
+ 
+     /** Root of ARQ-defined parameter names */  
+     public static final String arqParamNS = "http://jena.apache.org/ARQ#" ;
+     
+     /** Prefix for ARQ-defined parameter names */  
+     public static final String arqSymbolPrefix = "arq" ;
+     
+     /** Stick exactly to the spec.
+      */
+     public static final Symbol strictSPARQL =
+         ARQConstants.allocSymbol("strictSPARQL") ;
+     
+     /** Controls bNode labels as &lt;_:...&gt; or not -
+      * that is a pseudo URIs.
+      * This does not affect [] or _:a bNodes as variables in queries. 
+      */
+ 
+     public static final Symbol constantBNodeLabels =
+         ARQConstants.allocSymbol("constantBNodeLabels") ;
+     
+     /** Enable built-in property functions - also called "magic properties".
+      * These are properties in triple patterns that need
+      * calculation, not matching.  See ARQ documentation for more details.
+      * rdfs:member and http://jena.apache.org/ARQ/list#member are provided.
+      */
+ 
+     public static final Symbol enablePropertyFunctions =
+         ARQConstants.allocSymbol("enablePropertyFunctions") ;
+ 
+     /** Enable logging of execution timing. 
+      */
+ 
+     public static final Symbol enableExecutionTimeLogging =
+         ARQConstants.allocSymbol("enableExecutionTimeLogging") ;
+ 
+     /** If true, XML result sets written will contain the graph bNode label
+      *  See also inputGraphBNodeLabels
+      */
+     
+     public static final Symbol outputGraphBNodeLabels =  
+         ARQConstants.allocSymbol("outputGraphBNodeLabels") ;
+ 
+     /** If true, XML result sets will use the bNode label in the result set itself.
+      *  See also outputGraphBNodeLabels
+      */
+     
+     public static final Symbol inputGraphBNodeLabels =  
+         ARQConstants.allocSymbol("inputGraphBNodeLabels") ;
+ 
+     /** Turn on processing of blank node labels in queries */  
+     public static void enableBlankNodeResultLabels() { enableBlankNodeResultLabels(true) ; }
+     
+     /** Turn on/off processing of blank node labels in queries */  
+     public static void enableBlankNodeResultLabels(boolean val)
+     { 
+         Boolean b = val;
+         globalContext.set(inputGraphBNodeLabels, b) ;
+         globalContext.set(outputGraphBNodeLabels, b) ;
+     }
+ 
+ 
+     /**
+      * Set timeout.  The value of this symbol gives thevalue of the timeout in milliseconds
+      * <ul>
+      * <li>A Number; the long value is used</li>
+      * <li>A string, e.g. "1000", parsed as a number</li>
+      * <li>A string, as two numbers separated by a comma, e.g. "500,10000" parsed as two numbers</li>
+      * </ul>
+      * @see QueryExecution#setTimeout(long)
+      * @see QueryExecution#setTimeout(long,long)
+      */
+     public static final Symbol queryTimeout = ARQConstants.allocSymbol("queryTimeout") ;
+     
+     // This can't be a context constant because NodeValues don't look in the context.
+ //    /**
+ //     * Context symbol controlling Roman Numerals in Filters.
+ //     */
+ //    public static final Symbol enableRomanNumerals = ARQConstants.allocSymbol("romanNumerals") ;
+ 
+     /**
+      * Context key for StageBuilder used in BGP compilation 
+      */
+     public static final Symbol stageGenerator = ARQConstants.allocSymbol("stageGenerator") ;
+ 
+     /**
+      * Context key to control hiding non-distinuished variables 
+      */
+     public static final Symbol hideNonDistiguishedVariables = ARQConstants.allocSymbol("hideNonDistiguishedVariables") ;
+ 
+     /**
+      * Use the SAX parser for XML result sets.  The default is to use StAX for
+      * full streaming of XML results.  The SAX parser takes a copy of the result set
+      * before giving the ResultSet to the calling application.
+      */
+     public static final Symbol useSAX = ARQConstants.allocSymbol("useSAX") ;
+     
+     /** 
+      * Indicate whether duplicate select and groupby variables are allowed. 
+      * If false, duplicates are silently supressed; it's not an error.  
+      */
+     public static final boolean allowDuplicateSelectColumns = false ;
+ 
+     /**
+      * Determine which regular expression system to use.
+      * The value of this context entry should be a string or symbol
+      * of one of the following:
+      *   javaRegex :   use java.util.regex (support features outside the strict SPARQL regex language)
+      *   xercesRegex : use the internal XPath regex engine (more compliant)  
+      */
+     
+     public static final Symbol regexImpl =  ARQConstants.allocSymbol("regexImpl") ;
+     
+         
+     /** Symbol to name java.util.regex regular expression engine */ 
+     public static final Symbol javaRegex =  ARQConstants.allocSymbol("javaRegex") ;
+     /** Symbol to name the Xerces-J regular expression engine */ 
+     public static final Symbol xercesRegex =  ARQConstants.allocSymbol("xercesRegex") ;
+ 
+     /** 
+      * Use this Symbol to allow passing additional query parameters to a 
+      * SERVICE <IRI> call.
+      * Parameters need to be grouped by SERVICE <IRI>,  
+      * a Map<String, Map<String,List<String>>> is assumed.
+      * The key of the first map is the SERVICE IRI, the value is a Map 
+      * which maps the name of a query string parameters to its values.
+      * 
+      * @see org.apache.jena.sparql.engine.http.Service
+      */
+     public static final Symbol serviceParams = ARQConstants.allocSymbol("serviceParams") ;
+     
+     /**
+      * Control whether SERVICE processing is allowed.
+      * If the context of the query exexcution contains this, 
+      * and it's set to "false", then SERVICE is not allowed.
+      */
+     
+     public static final Symbol serviceAllowed = Service.serviceAllowed ;
+     
+     /**
+      * A Long value that specifies the number of bindings (or triples for CONSTRUCT queries) to be stored in memory by sort
+      * operations or hash tables before switching to temporary disk files.  The value defaults to -1, which will always
+      * keep the bindings in memory and never write to temporary files.  The amount of memory used will vary based on
+      * the size of the bindings.  If you are retrieving large literal strings, then you may need to lower the value. 
+      * <p/>
+      * Note that for a complex query, several sort or hash operations might be running in parallel; each one will be
+      * allowed to retain as many bindings in memory as this value specifies before it starts putting data in temporary
+      * files.  Also, several running sessions could be doing such operations concurrently.  Therefore, the total number
+      * of bindings held in memory could be many times this value; it is necessary to keep this fact in mind when
+      * choosing the value.
+      * <p/>
+      * Operations currently affected by this symbol: <br>
+      * ORDER BY, SPARQL Update, CONSTRUCT (optionally)
+      * <p/>
+      * TODO: Give a reasonable suggested value here.  10,000?
+      * <p/>
+      * @see <a href="https://issues.apache.org/jira/browse/JENA-119">JENA-119</a>
+      */
+     // Some possible additions to the list:
+     // Sort: DISTINCT, merge joins<br>
+     // Hash table: GROUP BY, MINUS, SERVICE, VALUES, and hash joins <br>
+     public static final Symbol spillToDiskThreshold = ARQConstants.allocSymbol("spillToDiskThreshold") ;
+     
+     // Optimizer controls.
+     
+     /** 
+      *  Globally switch the default optimizer on and off : 
+      *  Note that storage subsystems may also be applying 
+      *  separately controlled optimizations.
+      */
+     
+     public static void enableOptimizer(boolean state) 
+     {
+         enableOptimizer(ARQ.getContext(), state) ;
+     }
+     
+     /** 
+      *  Switch the default optimizer on and off for a specific Context. 
+      *  Note that storage subsystems may also be applying 
+      *  separately controlled optimizations.
+      */
+     public static void enableOptimizer(Context context, boolean state) 
+     {
+         context.set(ARQ.optimization, state) ;
+     }
+     
+     /** 
+      *  Context key controlling whether the main query engine applies the
+      *  default optimization transformations.
+      */  
+     public static final Symbol optimization = ARQConstants.allocSymbol("optimization") ;
+     
+     /** 
+      *  Context key controlling whether the main query engine flattens simple paths
+      *  (e.g. <tt>?x :p/:q ?z => ?x :p ?.0 . ?.0 ?q ?z</tt>)   
+      *  <p>Default is "true"
+      */  
+     public static final Symbol optPathFlatten = ARQConstants.allocSymbol("optPathFlatten") ;
+     
+     /** 
+      *  Context key controlling whether the main query engine moves filters to the "best" place.
+      *  Default is "true" - filter placement is done.
+      */  
+     public static final Symbol optFilterPlacement = ARQConstants.allocSymbol("optFilterPlacement") ;
+ 
+     /** 
+      *  Context key controlling whether to do filter placement within BGP and quad blocks.
+      *  Modies the effect of optFilterPlacement. 
+      *  Default is "true" - filter placement is pushed into BGPs.
+      */  
+     public static final Symbol optFilterPlacementBGP = ARQConstants.allocSymbol("optFilterPlacementBGP") ;
+     
+     /** 
+      *  Context key controlling whether the main query engine moves filters to the "best" place using 
+      *  the more limited and conservative strategy which does not place as many filters
+      *  Must be explicitly set "true" to operate.
+      *  Filter placement, via {@link #optFilterPlacement} must also be active (which it is by default).
+      * @see #optFilterPlacement
+      */ 
+     public static final Symbol optFilterPlacementConservative = ARQConstants.allocSymbol("optFilterPlacementConservative") ;
+ 
+     /** 
+      *  Context key controlling whether an ORDER BY-LIMIT query is done avoiding total sort using an heap.
+      *  Default is "true" - total sort if avoided by default when ORDER BY is used with LIMIT.
+      */  
+     public static final Symbol optTopNSorting = ARQConstants.allocSymbol("optTopNSorting") ;
+     
+     /** 
+      *  Context key controlling whether a DISTINCT-ORDER BY query is done by replacing the distinct with a reduced.
+      *  Default is "true" - the reduced operator does not need to keep a data structure with all previously seen bindings.
+      */  
+     public static final Symbol optDistinctToReduced = ARQConstants.allocSymbol("optDistinctToReduced") ;
+     
+     /**
+      * Context key controlling whether a DISTINCT-ORDER BY query is done by applying the ORDER BY after the DISTINCT
+      * when default SPARQL semantics usually mean ORDER BY applies before DISTINCT.  This optimization applies only
+      * in a subset of cases unlike the more general {@link #optDistinctToReduced} optimization.
+      * <p>
+      * See {@link TransformOrderByDistinctApplication} for more discussion on exactly when this may apply
+      * </p>
+      */
+     public static final Symbol optOrderByDistinctApplication = ARQConstants.allocSymbol("optOrderByDistinctApplication");
+ 
+     /** 
+      *  Context key controlling whether the standard optimizer applies
+      *  optimizations to equalities in FILTERs.
+      *  This optimization is conservative - it does not take place if
+      *  there is a potential risk of changing query semantics. 
+      */  
+     public static final Symbol optFilterEquality = ARQConstants.allocSymbol("optFilterEquality") ;
+     
+     /**
+      * Context key controlling whether the standard optimizer applies 
+      * optimizations to inequalities in FILTERs
+      * This optimization is conservative - it does not take place if
+      * there is a potential risk of changing query semantics
+      */
+     public static final Symbol optFilterInequality = ARQConstants.allocSymbol("optFilterInequality") ;
+     
+     /**
+      * Context key controlling whether the standard optimizer applies optimizations to implicit joins in FILTERs.
+      * This optimization is conservative - it does not take place if there is a potential risk of changing query semantics.
+      */
+     public static final Symbol optFilterImplicitJoin = ARQConstants.allocSymbol("optFilterImplicitJoin");
+     
+     /**
+      * Context key controlling whether the standard optimizer applies optimizations to implicit left joins.
+      * This optimization is conservative - it does not take place if there is a potential risk of changing query semantics.
+      */
+     public static final Symbol optImplicitLeftJoin = ARQConstants.allocSymbol("optImplicitLeftJoin");
+ 
+     /** 
+      *  Context key for a declaration that xsd:strings and simple literals are
+      *  different in the storage.  They are the same value in a memory store.
+      *  When in doubt, xsd:strings are assumed to be the same value as simple literals   
+      */  
+     public static final Symbol optTermStrings = ARQConstants.allocSymbol("optTermStrings") ;
+     
+     /**
+      * Context key controlling whether the standard optimizer applies constant folding to expressions
+      */
+     public static final Symbol optExprConstantFolding = ARQConstants.allocSymbol("optExprConstantFolding");
+ 
+     /** 
+      *  Context key controlling whether the standard optimizer applies
+      *  optimizations to conjunctions (&&) in filters.
+      */  
+     public static final Symbol optFilterConjunction = ARQConstants.allocSymbol("optFilterConjunction") ;
+ 
+     /** 
+      *  Context key controlling whether the standard optimizer applies
+      *  optimizations to IN and NOT IN.
+      */  
+     public static final Symbol optFilterExpandOneOf = ARQConstants.allocSymbol("optFilterExpandOneOf") ;
+ 
+     /** 
+      *  Context key controlling whether the standard optimizer applies
+      *  optimizations to disjunctions (||) in filters.
+      */  
+     public static final Symbol optFilterDisjunction = ARQConstants.allocSymbol("optFilterDisjunction") ;
+     
+     /**
+      * Context key controlling whether the standard optimizer applies table empty promotion
+      */
+     public static final Symbol optPromoteTableEmpty = ARQConstants.allocSymbol("optPromoteTableEmpty") ;
+     
+     /**
+      * Context key controlling whether the standard optimizer applies optimizations to the evaluation
+      * of joins to favour index joins wherever possible
+      */
+     public static final Symbol optIndexJoinStrategy = ARQConstants.allocSymbol("optIndexJoinStrategy");
+     
+     /**
++     * Context key controlling whether the standard optimizer applies optimizations where by some
++     * assignments may be eliminated/inlined into the operators where their values are used only once
++     */
++    public static final Symbol optInlineAssignments = ARQConstants.allocSymbol("optInlineAssignments");
++    
++    /**
++     * Context key controlling whether the standard optimizer aggressively inlines assignments whose
++     * values are used only once into operators where those expressions may be evaluated multiple times e.g. order
++     */
++    public static final Symbol optInlineAssignmentsAggressive = ARQConstants.allocSymbol("optInlineAssignmentsAggressive");
++    
++    /**
+      * Context key controlling whether the standard optimizater applies optimizations to joined BGPs to
+      * merge them into single BGPs.
+      * By default, this transformation is applied.
+      */
+     public static final Symbol optMergeBGPs = ARQConstants.allocSymbol("optMergeBGPs");
+     
+     /**
+      * Context key controlling whether the standard optimizater applies the optimization
+      * to combine stacks of (extend) into one compound operation.  Ditto (assign). 
+      * By default, this transformation is applied.
+      */
+     public static final Symbol optMergeExtends = ARQConstants.allocSymbol("optMergeExtends");
+ 
+     /** 
+      *  Context key controlling whether the main query engine processes property functions.
+      *  
+      */  
+     public static final Symbol propertyFunctions = ARQConstants.allocSymbol("propertyFunctions") ;
+     
+     /**
+      * Expression evaluation without extension types (e.g. xsd:date, language tags)
+      */
+     public static final Symbol extensionValueTypes = ARQConstants.allocSymbol("extensionValueTypesExpr") ;
+ 
+     /**
+      * Generate the ToList operation in the algebra (as ARQ is stream based, ToList is a non-op).
+      * Default is not to do so.  Strict mode will also enable this.
+      */
+     public static final Symbol generateToList = ARQConstants.allocSymbol("generateToList") ;
+ 
+     /** Set strict mode, including expression evaluation */
+     public static void setStrictMode() { setStrictMode(ARQ.getContext()) ; }
+     
+     /** Set strict mode for a given Context.
+      *  
+      *  Does not influence expression evaluation because NodeValues
+      *  are controlled globally, not per context.
+      */
+     public static void setStrictMode(Context context)
+     {
+         SystemARQ.StrictDateTimeFO      = true ;
+         SystemARQ.ValueExtensions       = false ;
+         SystemARQ.EnableRomanNumerals   = false ;
+         
+         context.set(optimization,                   false) ;
+         context.set(hideNonDistiguishedVariables,   true) ;
+         context.set(strictSPARQL,                   true) ;
+         context.set(enablePropertyFunctions,        false) ;
+         
+         context.set(extensionValueTypes,            false) ;
+         context.set(constantBNodeLabels,            false) ;
+         context.set(generateToList,                 true) ;
+         context.set(regexImpl,                      xercesRegex) ;
+         
+         //context.set(filterPlacement,            false) ;
+     }
+ 
+     public static boolean isStrictMode()       { return ARQ.getContext().isTrue(strictSPARQL) ; }
+     
+     /** Set normal mode, including expression evaluation */
+     public static void setNormalMode() {
+         SystemARQ.StrictDateTimeFO      = false ;
+         SystemARQ.ValueExtensions       = true ;
+         SystemARQ.EnableRomanNumerals   = false ;
+         setNormalMode(ARQ.getContext()) ; 
+     }
+         
+     /** Explicitly set the values for normal operation.
+      *  Does not influence expression evaluation.
+      */
+     public static void setNormalMode(Context context)
+     {
+         context.set(optimization,                   true) ;
+         context.set(hideNonDistiguishedVariables,   false) ;
+         context.set(strictSPARQL,                   false) ;
+         context.set(enablePropertyFunctions,        true) ;
+         
+         context.set(extensionValueTypes,            true) ;
+         context.set(constantBNodeLabels,            true) ;
+         context.set(generateToList,                 false) ;
+         context.set(regexImpl,                      javaRegex) ;
+     }
+     
+     // ----------------------------------
+     
+     /** The root package name for ARQ */   
+     public static final String PATH         = "org.apache.jena.arq";
+    
+     static private String metadataLocation  = "org/apache/jena/arq/arq-properties.xml" ;
+ 
+     static private Metadata metadata        = new Metadata(metadataLocation) ;
+     
+     /** The product name */   
+     public static final String NAME         = "ARQ";
+    
+     /** The full name of the current ARQ version */   
+     public static final String VERSION      = metadata.get(PATH+".version", "unknown") ;
+    
+     /** The date and time at which this release was built */   
+     public static final String BUILD_DATE   = metadata.get(PATH+".build.datetime", "unset") ;
+     
+     // A correct way to manage without synchonized using the double checked locking pattern.
+     //   http://en.wikipedia.org/wiki/Double-checked_locking
+     //   http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html 
+     private static volatile boolean initialized = false ;
+     private static final Object initLock = new Object() ;
+ 
+     private static Context globalContext = null ;
+ 
+     /** Ensure things have started - applications do not need call this.
+      * The method is public so any part of ARQ can call it.
+      * Note the final static initializer call 
+      */
+     
+     public static void init()
+     { 
+         if ( initialized )
+             return ;
+         synchronized(initLock)
+         {
+             if ( initialized )
+                 return ;
+             initialized = true ;
+             globalContext = defaultSettings() ;
+             
+             RIOT.init() ;
+             StageBuilder.init() ;
+             ARQMgt.init() ;         // After context and after PATH/NAME/VERSION/BUILD_DATE are set
+             MappingRegistry.addPrefixMapping(ARQ.arqSymbolPrefix, ARQ.arqParamNS) ;
+             
+             // This is the pattern for any subsystem to register. 
+             SystemInfo sysInfo = new SystemInfo(ARQ.arqIRI, ARQ.PATH, ARQ.VERSION, ARQ.BUILD_DATE) ;
+             SystemARQ.registerSubSystem(sysInfo) ;
+ 
+             // Register RIOT details here, not earlier, to avoid
+             // initialization loops with RIOT.init() called directly.
+             RIOT.register() ;
+         }
+     }
+     
+     // Force a call
+     static { init() ; }
+     
+     /* Side effects */
+     private static Context defaultSettings()
+     {
+         SystemARQ.StrictDateTimeFO      = false ;
+         SystemARQ.ValueExtensions       = true ;
+         SystemARQ.EnableRomanNumerals   = false ; 
+ 
+         Context context = new Context() ;
+         context.unset(optimization) ;
+         //context.set(hideNonDistiguishedVariables, true) ;
+         context.set(strictSPARQL,                  false) ; 
+         context.set(constantBNodeLabels,           true) ;
+         context.set(enablePropertyFunctions,       true) ;
+         context.set(regexImpl,                     javaRegex) ;
+ 
+         return context ; 
+     }
+ 
+     public static Context getContext()
+     { 
+         //ARQ.init() ;
+         return globalContext ;
+     }
+     
+     // Convenience call-throughs
+     public static void set(Symbol symbol, boolean value)  { getContext().set(symbol, value) ; }
+     public static void setTrue(Symbol symbol)             { getContext().setTrue(symbol) ; }
+     public static void setFalse(Symbol symbol)            { getContext().setFalse(symbol) ; }
+     public static void unset(Symbol symbol)               { getContext().unset(symbol) ; }
+     public static boolean isTrue(Symbol symbol)           { return getContext().isTrue(symbol) ; }
+     public static boolean isFalse(Symbol symbol)          { return getContext().isFalse(symbol) ; }
+     public static boolean isTrueOrUndef(Symbol symbol)    { return getContext().isTrueOrUndef(symbol) ; }
+     public static boolean isFalseOrUndef(Symbol symbol)   { return getContext().isFalseOrUndef(symbol) ; }
+ 
+ }

http://git-wip-us.apache.org/repos/asf/jena/blob/9d684173/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/Optimize.java
----------------------------------------------------------------------
diff --cc jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/Optimize.java
index 0000000,342b50d..034e233
mode 000000,100644..100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/Optimize.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/Optimize.java
@@@ -1,0 -1,300 +1,304 @@@
+ /*
+  * 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 org.apache.jena.sparql.algebra.optimize;
+ 
+ import org.apache.jena.query.ARQ ;
+ import org.apache.jena.sparql.ARQConstants ;
+ import org.apache.jena.sparql.algebra.* ;
+ import org.apache.jena.sparql.algebra.op.OpLabel ;
+ import org.apache.jena.sparql.engine.ExecutionContext ;
+ import org.apache.jena.sparql.util.Context ;
+ import org.apache.jena.sparql.util.Symbol ;
+ import org.slf4j.Logger ;
+ import org.slf4j.LoggerFactory ;
+ 
+ 
+ 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) ;
+             // and merge adjacent BGPs (part 1)
+             if ( context.isTrueOrUndef(ARQ.optMergeBGPs) )
+                 op = apply("Merge BGPs", new TransformMergeBGPs(), 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);
+         
++        // Eliminate/Inline assignments where possible
++        if ( context.isTrue(ARQ.optInlineAssignments) )
++            op = TransformEliminateAssignments.eliminate(op, context.isTrue(ARQ.optInlineAssignmentsAggressive));
++        
+         // 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) ;
+         
+         // Merge (extend) and (assign) stacks
+         if ( context.isTrueOrUndef(ARQ.optMergeExtends) )
+             op = apply("Combine BIND/LET", new TransformExtendCombine(), 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 ;
+     }
+ }

http://git-wip-us.apache.org/repos/asf/jena/blob/9d684173/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
----------------------------------------------------------------------
diff --cc jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
index 0000000,9099486..e921f47
mode 000000,100644..100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
@@@ -1,0 -1,40 +1,41 @@@
+ /*
+  * 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 org.apache.jena.sparql.algebra.optimize;
+ 
+ import org.junit.runner.RunWith ;
+ import org.junit.runners.Suite ;
+ 
+ @RunWith(Suite.class)
+ @Suite.SuiteClasses( {
+     TestReorderBGP.class
+     , TestVarRename.class
+     , TestOptDistinctReduced.class
+     , TestSemanticEquivalence.class
+     , TestTransformConstantFolding.class
+     , TestTransformFilters.class
+     , TestTransformFilterPlacement.class
+     , TestTransformMergeBGPs.class
+     , TestTransformPromoteTableEmpty.class
++    , TestTransformEliminateAssignments.class
+     , TestTransformTopN.class
+     , TestOptimizer.class
+ })
+ 
+ public class TS_Optimization
+ {}