| /* |
| |
| Derby - Class org.apache.derby.impl.sql.compile.OptimizerFactoryImpl |
| |
| 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.derby.impl.sql.compile; |
| |
| import java.util.Properties; |
| import org.apache.derby.iapi.error.StandardException; |
| import org.apache.derby.iapi.services.monitor.ModuleControl; |
| import org.apache.derby.iapi.services.property.PropertyUtil; |
| import org.apache.derby.iapi.sql.compile.CostEstimate; |
| import org.apache.derby.iapi.sql.compile.JoinStrategy; |
| import org.apache.derby.iapi.sql.compile.OptimizableList; |
| import org.apache.derby.iapi.sql.compile.OptimizablePredicateList; |
| import org.apache.derby.iapi.sql.compile.Optimizer; |
| import org.apache.derby.iapi.sql.compile.OptimizerFactory; |
| import org.apache.derby.iapi.sql.compile.OptimizerPlan; |
| import org.apache.derby.iapi.sql.compile.RequiredRowOrdering; |
| import org.apache.derby.iapi.sql.conn.LanguageConnectionContext; |
| import org.apache.derby.iapi.sql.dictionary.DataDictionary; |
| |
| /** |
| This is simply the factory for creating an optimizer. |
| */ |
| |
| public class OptimizerFactoryImpl |
| implements ModuleControl, OptimizerFactory { |
| |
| protected String optimizerId = null; |
| protected boolean ruleBasedOptimization = false; |
| protected boolean noTimeout = false; |
| protected boolean useStatistics = true; |
| protected int maxMemoryPerTable = 1048576; |
| |
| /* |
| ** The fact that we have one set of join strategies for use by all |
| ** optimizers means that the JoinStrategy[] must be immutable, and |
| ** also each JoinStrategy must be immutable. |
| */ |
| protected JoinStrategy[] joinStrategySet; |
| |
| /* Do join order optimization by default */ |
| private boolean joinOrderOptimization = true; |
| |
| |
| // |
| // ModuleControl interface |
| // |
| |
| public void boot(boolean create, Properties startParams) |
| throws StandardException { |
| |
| /* |
| ** This system property determines whether to optimize join order |
| ** by default. It is used mainly for testing - there are many tests |
| ** that assume the join order is fixed. |
| */ |
| String opt = |
| PropertyUtil.getSystemProperty(Optimizer.JOIN_ORDER_OPTIMIZATION); |
| if (opt != null) |
| { |
| joinOrderOptimization = Boolean.parseBoolean(opt); |
| } |
| |
| /* |
| ** This property determines whether to use rule-based or cost-based |
| ** optimization. It is used mainly for testing - there are many tests |
| ** that assume rule-based optimization. The default is cost-based |
| ** optimization. |
| */ |
| ruleBasedOptimization = |
| Boolean.valueOf( |
| PropertyUtil.getSystemProperty(Optimizer.RULE_BASED_OPTIMIZATION) |
| ).booleanValue(); |
| |
| /* |
| ** This property determines whether the optimizer should ever stop |
| ** optimizing a query because it has spent too long in optimization. |
| ** The default is that it will. |
| */ |
| noTimeout = |
| Boolean.valueOf( |
| PropertyUtil.getSystemProperty(Optimizer.NO_TIMEOUT) |
| ).booleanValue(); |
| |
| /* |
| ** This property determines the maximum size of memory (in KB) |
| ** the optimizer can use for each table. If an access path takes |
| ** memory larger than that size for a table, the access path is skipped. |
| ** Default is 1024 (KB). |
| */ |
| String maxMemValue = PropertyUtil.getSystemProperty(Optimizer.MAX_MEMORY_PER_TABLE); |
| if (maxMemValue != null) |
| { |
| int intValue = Integer.parseInt(maxMemValue); |
| if (intValue >= 0) |
| maxMemoryPerTable = intValue * 1024; |
| } |
| |
| String us = PropertyUtil.getSystemProperty(Optimizer.USE_STATISTICS); |
| if (us != null) |
| useStatistics = (Boolean.valueOf(us)).booleanValue(); |
| |
| /* Allocation of joinStrategySet deferred til |
| * getOptimizer(), even though we only need 1 |
| * array for this factory. We defer allocation |
| * to improve boot time on small devices. |
| */ |
| } |
| |
| public void stop() { |
| } |
| |
| // |
| // OptimizerFactory interface |
| // |
| |
| /** |
| * @see OptimizerFactory#getOptimizer |
| * |
| * @exception StandardException Thrown on error |
| */ |
| public Optimizer getOptimizer(OptimizableList optimizableList, |
| OptimizablePredicateList predList, |
| DataDictionary dDictionary, |
| RequiredRowOrdering requiredRowOrdering, |
| int numTablesInQuery, |
| OptimizerPlan overridingPlan, |
| LanguageConnectionContext lcc) |
| throws StandardException |
| { |
| /* Get/set up the array of join strategies. |
| * See comment in boot(). If joinStrategySet |
| * is null, then we may do needless allocations |
| * in a multi-user environment if multiple |
| * users find it null on entry. However, |
| * assignment of array is atomic, so system |
| * will be consistent even in rare case |
| * where users get different arrays. |
| */ |
| if (joinStrategySet == null) |
| { |
| JoinStrategy[] jss = new JoinStrategy[2]; |
| jss[0] = new NestedLoopJoinStrategy(); |
| jss[1] = new HashJoinStrategy(); |
| joinStrategySet = jss; |
| } |
| |
| return getOptimizerImpl(optimizableList, |
| predList, |
| dDictionary, |
| requiredRowOrdering, |
| numTablesInQuery, |
| overridingPlan, |
| lcc); |
| } |
| |
| /** |
| * @see OptimizerFactory#getCostEstimate |
| */ |
| public CostEstimate getCostEstimate() |
| { |
| return new CostEstimateImpl(); |
| } |
| |
| /** |
| * @see OptimizerFactory#supportsOptimizerTrace |
| */ |
| public boolean supportsOptimizerTrace() |
| { |
| return true; |
| } |
| |
| // |
| // class interface |
| // |
| public OptimizerFactoryImpl() { |
| } |
| |
| protected Optimizer getOptimizerImpl(OptimizableList optimizableList, |
| OptimizablePredicateList predList, |
| DataDictionary dDictionary, |
| RequiredRowOrdering requiredRowOrdering, |
| int numTablesInQuery, |
| OptimizerPlan overridingPlan, |
| LanguageConnectionContext lcc) |
| throws StandardException |
| { |
| |
| return new OptimizerImpl( |
| optimizableList, |
| predList, |
| dDictionary, |
| ruleBasedOptimization, |
| noTimeout, |
| useStatistics, |
| maxMemoryPerTable, |
| joinStrategySet, |
| lcc.getLockEscalationThreshold(), |
| requiredRowOrdering, |
| numTablesInQuery, |
| overridingPlan, |
| lcc); |
| } |
| |
| /** |
| * @see OptimizerFactory#getMaxMemoryPerTable |
| */ |
| public int getMaxMemoryPerTable() |
| { |
| return maxMemoryPerTable; |
| } |
| |
| @Override |
| public boolean doJoinOrderOptimization() |
| { |
| return joinOrderOptimization; |
| } |
| } |
| |