[teiid-commits] teiid SVN: r808 - in trunk/engine/src: main/java/com/metamatrix/query/optimizer/batch and 9 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Mon Apr 20 17:02:03 EDT 2009
Author: shawkins
Date: 2009-04-20 17:02:03 -0400 (Mon, 20 Apr 2009)
New Revision: 808
Removed:
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/NeedsEvaluationVisitor.java
Modified:
trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java
trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/parser/ParseInfo.java
trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SimpleQueryResolver.java
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluatableVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluateExpressionVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/util/CommandContext.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedPlanCache.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestAccessNode.java
trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestBatchedUpdateNode.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java
Log:
TEIID-81, TEIID-512 updating the planning logic to promote non-session specific commands to be globally reusable
Modified: trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/function/FunctionLibrary.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -36,6 +36,7 @@
import com.metamatrix.query.function.metadata.FunctionParameter;
import com.metamatrix.query.sql.symbol.Expression;
import com.metamatrix.query.sql.symbol.Function;
+import com.metamatrix.query.util.CommandContext;
import com.metamatrix.query.util.ErrorMessageKeys;
@@ -348,6 +349,11 @@
throw new FunctionExecutionException(ErrorMessageKeys.FUNCTION_0002, QueryPlugin.Util.getString(ErrorMessageKeys.FUNCTION_0002, localDescriptor.getName()));
}
}
+
+ if (fd.getDeterministic() >= FunctionMethod.SESSION_DETERMINISTIC && values.length > 0 && values[0] instanceof CommandContext) {
+ CommandContext cc = (CommandContext)values[0];
+ cc.setSessionFunctionEvaluated(true);
+ }
// Invoke the method and return the result
try {
Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/batch/BatchedUpdatePlanner.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -53,7 +53,7 @@
import com.metamatrix.query.sql.lang.Update;
import com.metamatrix.query.sql.symbol.GroupSymbol;
import com.metamatrix.query.sql.util.VariableContext;
-import com.metamatrix.query.sql.visitor.NeedsEvaluationVisitor;
+import com.metamatrix.query.sql.visitor.EvaluatableVisitor;
import com.metamatrix.query.util.CommandContext;
@@ -131,7 +131,7 @@
contexts.add(allContexts.get(commandIndex));
shouldEvaluate.add(Boolean.TRUE);
} else {
- shouldEvaluate.add(NeedsEvaluationVisitor.needsEvaluation(updateCommand));
+ shouldEvaluate.add(EvaluatableVisitor.needsProcessingEvaluation(updateCommand));
}
// Find out if there are other commands called on the same physical model
// immediately and contiguously after this one
@@ -144,7 +144,7 @@
contexts.add(allContexts.get(batchIndex));
shouldEvaluate.add(Boolean.TRUE);
} else {
- shouldEvaluate.add(NeedsEvaluationVisitor.needsEvaluation(batchingCandidate));
+ shouldEvaluate.add(EvaluatableVisitor.needsProcessingEvaluation(batchingCandidate));
}
} else { // Otherwise, stop batching at this point. The next command may well be the start of a new batch
break batchLoop;
Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/PlanToProcessConverter.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -82,8 +82,8 @@
import com.metamatrix.query.sql.symbol.Expression;
import com.metamatrix.query.sql.symbol.GroupSymbol;
import com.metamatrix.query.sql.util.SymbolMap;
+import com.metamatrix.query.sql.visitor.EvaluatableVisitor;
import com.metamatrix.query.sql.visitor.GroupCollectorVisitor;
-import com.metamatrix.query.sql.visitor.NeedsEvaluationVisitor;
import com.metamatrix.query.util.ErrorMessageKeys;
public class PlanToProcessConverter {
@@ -306,7 +306,7 @@
} catch (QueryMetadataException err) {
throw new MetaMatrixComponentException(err);
}
- aNode.setShouldEvaluateExpressions(NeedsEvaluationVisitor.needsEvaluation(command));
+ aNode.setShouldEvaluateExpressions(EvaluatableVisitor.needsProcessingEvaluation(command));
}
try {
Modified: trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/CriteriaCapabilityValidatorVisitor.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -54,7 +54,7 @@
import com.metamatrix.query.sql.symbol.Function;
import com.metamatrix.query.sql.symbol.SearchedCaseExpression;
import com.metamatrix.query.sql.visitor.ElementCollectorVisitor;
-import com.metamatrix.query.sql.visitor.EvaluateExpressionVisitor;
+import com.metamatrix.query.sql.visitor.EvaluatableVisitor;
/**
*/
@@ -228,7 +228,7 @@
public void visit(Function obj) {
try {
//if the function can be evaluated then return as it will get replaced during the final rewrite
- if (EvaluateExpressionVisitor.willBecomeConstant(obj, true)) {
+ if (EvaluatableVisitor.willBecomeConstant(obj, true)) {
return;
}
if(obj.getFunctionDescriptor().getPushdown() == FunctionMethod.CANNOT_PUSHDOWN || ! CapabilitiesUtil.supportsScalarFunction(modelID, obj, metadata, capFinder)) {
Modified: trunk/engine/src/main/java/com/metamatrix/query/parser/ParseInfo.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/parser/ParseInfo.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/parser/ParseInfo.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -44,4 +44,21 @@
public boolean allowDoubleQuotedVariable() {
return allowDoubleQuotedVariable;
}
+
+ @Override
+ public int hashCode() {
+ return allowDoubleQuotedVariable?1:0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof ParseInfo)) {
+ return false;
+ }
+ ParseInfo other = (ParseInfo)obj;
+ return this.allowDoubleQuotedVariable == other.allowDoubleQuotedVariable;
+ }
}
\ No newline at end of file
Modified: trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SimpleQueryResolver.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SimpleQueryResolver.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/resolver/command/SimpleQueryResolver.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -92,7 +92,7 @@
private static final String ALL_IN_GROUP_SUFFIX = ".*"; //$NON-NLS-1$
private static Command resolveVirtualGroup(GroupSymbol virtualGroup, Command parentCommand, QueryMetadataInterface metadata, AnalysisRecord analysis)
- throws QueryMetadataException, QueryResolverException, MetaMatrixComponentException, QueryParserException {
+ throws QueryMetadataException, QueryResolverException, MetaMatrixComponentException {
QueryNode qnode = null;
Object metadataID = virtualGroup.getMetadataID();
@@ -253,7 +253,7 @@
}
private static Command convertToSubquery(QueryNode qnode, boolean nocache, QueryMetadataInterface metadata)
- throws QueryResolverException, MetaMatrixComponentException, QueryParserException {
+ throws QueryResolverException, MetaMatrixComponentException {
// Parse this node's command
Command command = qnode.getCommand();
@@ -605,8 +605,6 @@
throw new MetaMatrixRuntimeException(e);
} catch(MetaMatrixComponentException e) {
throw new MetaMatrixRuntimeException(e);
- } catch (QueryParserException e) {
- throw new MetaMatrixRuntimeException(e);
}
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluatableVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluatableVisitor.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluatableVisitor.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -25,6 +25,8 @@
*/
package com.metamatrix.query.sql.visitor;
+import java.util.TreeSet;
+
import com.metamatrix.query.function.FunctionLibrary;
import com.metamatrix.query.function.metadata.FunctionMethod;
import com.metamatrix.query.metadata.TempMetadataID;
@@ -46,118 +48,124 @@
/**
* <p>This visitor class will traverse a language object tree, and determine
* if the current expression can be evaluated</p>
- *
- * <p>The public visit() methods should NOT be called directly.</p>
- *
- * There are three possible scenarios:
- *
- * duringPlanning | fullyEvaluatable
- * ---------------------------------
- * false | false = will become processing time constant
- * false | true = processing time evaluation possible
- * true | true = planning time evaluation possible (should always be deterministic)
- *
*/
public class EvaluatableVisitor extends LanguageVisitor {
+
+ public enum EvaluationLevel {
+ PLANNING,
+ PROCESSING,
+ PUSH_DOWN,
+ }
- protected boolean evaluationPossible = true;
-
- //TODO: there aren't really 16 states here, this should be minimized
- private boolean duringPlanning = false;
- private boolean fullyEvaluatable = false;
- private boolean deterministic = false;
- private boolean pushdown = false;
-
- public EvaluatableVisitor(boolean duringPlanning, boolean fullyEvaluatable) {
- this.duringPlanning = duringPlanning;
- this.fullyEvaluatable = fullyEvaluatable;
- }
-
+ private TreeSet<EvaluationLevel> levels = new TreeSet<EvaluationLevel>();
+ private EvaluationLevel targetLevel;
+ private int determinismLevel;
+ private boolean hasCorrelatedReferences;
+
public void visit(Function obj) {
+ this.setDeterminismLevel(obj.getFunctionDescriptor().getDeterministic());
if (obj.getFunctionDescriptor().getPushdown() == FunctionMethod.MUST_PUSHDOWN) {
- evaluationNotPossible();
- } else if (duringPlanning) {
- if (obj.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
- evaluationNotPossible();
- } else if (obj.getFunctionDescriptor().getDeterministic() >= FunctionMethod.COMMAND_DETERMINISTIC) {
- evaluationNotPossible();
- }
- } else if (deterministic && obj.getFunctionDescriptor().getDeterministic() == FunctionMethod.NONDETERMINISTIC) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
+ } else if (obj.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)
+ //TODO: if we had the context here we could plan better for non-prepared requests
+ || obj.getFunctionDescriptor().getDeterministic() >= FunctionMethod.COMMAND_DETERMINISTIC) {
+ evaluationNotPossible(EvaluationLevel.PROCESSING);
}
}
- private boolean evaluationNotPossible() {
- evaluationPossible = false;
- setAbort(true);
- return evaluationPossible;
+ private void setDeterminismLevel(int value) {
+ determinismLevel = Math.max(determinismLevel, value);
}
+
+ private void evaluationNotPossible(EvaluationLevel newLevel) {
+ levels.add(newLevel);
+ EvaluationLevel level = levels.last();
+ if (targetLevel != null && level.compareTo(targetLevel) > 0) {
+ setAbort(true);
+ }
+ }
public void visit(ElementSymbol obj) {
//if the element is a variable, or an element that will have a value, it will be evaluatable at runtime
- if (duringPlanning || fullyEvaluatable) {
- evaluationNotPossible();
- } else {
- //begin hack for not having the metadata passed in
- if (obj.getGroupSymbol().getMetadataID() instanceof TempMetadataID) {
- TempMetadataID tid = (TempMetadataID)obj.getGroupSymbol().getMetadataID();
- if (tid.isScalarGroup()) {
- return;
- }
- }
- evaluationNotPossible();
- }
+ //begin hack for not having the metadata passed in
+ if (obj.getGroupSymbol().getMetadataID() instanceof TempMetadataID) {
+ TempMetadataID tid = (TempMetadataID)obj.getGroupSymbol().getMetadataID();
+ if (tid.isScalarGroup()) {
+ evaluationNotPossible(EvaluationLevel.PROCESSING);
+ return;
+ }
+ }
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(ExpressionSymbol obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(AggregateSymbol obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
+ /**
+ * We assume the non-push down for correlation variables,
+ * then make specific checks when correlated variables are allowed.
+ */
public void visit(Reference obj) {
- if (duringPlanning || fullyEvaluatable) {
- evaluationNotPossible();
- } else if (pushdown && obj.isCorrelated()) {
- evaluationNotPossible();
- }
+ hasCorrelatedReferences |= obj.isCorrelated();
+ evaluationNotPossible(EvaluationLevel.PROCESSING);
}
public void visit(StoredProcedure proc){
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(ScalarSubquery obj){
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(DependentSetCriteria obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(ExistsCriteria obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(SubquerySetCriteria obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
public void visit(SubqueryCompareCriteria obj) {
- evaluationNotPossible();
+ evaluationNotPossible(EvaluationLevel.PUSH_DOWN);
}
- public boolean isEvaluationPossible() {
- return evaluationPossible;
+ private boolean isEvaluationPossible() {
+ if (levels.isEmpty()) {
+ return true;
+ }
+ return levels.last().compareTo(targetLevel) <= 0;
}
- static final boolean isEvaluatable(LanguageObject obj, boolean duringPlanning, boolean fullyEvaluatable, boolean deterministic, boolean pushdown) {
- EvaluatableVisitor visitor = new EvaluatableVisitor(duringPlanning, fullyEvaluatable);
- visitor.deterministic = deterministic;
- visitor.pushdown = pushdown;
+ public static final boolean isEvaluatable(LanguageObject obj, EvaluationLevel target) {
+ EvaluatableVisitor visitor = new EvaluatableVisitor();
+ visitor.targetLevel = target;
PreOrderNavigator.doVisit(obj, visitor);
return visitor.isEvaluationPossible();
}
+
+ public static final boolean willBecomeConstant(LanguageObject obj, boolean pushdown) {
+ EvaluatableVisitor visitor = new EvaluatableVisitor();
+ visitor.targetLevel = EvaluationLevel.PROCESSING;
+ PreOrderNavigator.doVisit(obj, visitor);
+ if (pushdown && (visitor.hasCorrelatedReferences || visitor.determinismLevel >= FunctionMethod.NONDETERMINISTIC)) {
+ return false;
+ }
+ return visitor.isEvaluationPossible();
+ }
+
+ public static final boolean needsProcessingEvaluation(LanguageObject obj) {
+ EvaluatableVisitor visitor = new EvaluatableVisitor();
+ PreOrderNavigator.doVisit(obj, visitor);
+ return visitor.levels.contains(EvaluationLevel.PROCESSING);
+ }
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluateExpressionVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluateExpressionVisitor.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/EvaluateExpressionVisitor.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -37,6 +37,7 @@
import com.metamatrix.query.sql.symbol.Expression;
import com.metamatrix.query.sql.symbol.Reference;
import com.metamatrix.query.sql.symbol.ScalarSubquery;
+import com.metamatrix.query.sql.visitor.EvaluatableVisitor.EvaluationLevel;
import com.metamatrix.query.util.CommandContext;
/**
@@ -74,7 +75,7 @@
*/
public Expression replaceExpression(Expression expr) {
//if the expression is a constant or is not evaluatable, just return
- if (expr instanceof Constant || expr instanceof ScalarSubquery || (!(expr instanceof Reference) && !EvaluatableVisitor.isEvaluatable(expr, false, true, false, false))) {
+ if (expr instanceof Constant || expr instanceof ScalarSubquery || (!(expr instanceof Reference) && !EvaluatableVisitor.isEvaluatable(expr, EvaluationLevel.PROCESSING))) {
return expr;
}
@@ -95,18 +96,14 @@
* evaluatable during planning
*/
public static final boolean willBecomeConstant(LanguageObject obj) {
- return willBecomeConstant(obj, false);
+ return EvaluatableVisitor.willBecomeConstant(obj, false);
}
- public static final boolean willBecomeConstant(LanguageObject obj, boolean pushdown) {
- return EvaluatableVisitor.isEvaluatable(obj, false, false, true, pushdown);
- }
-
/**
* Should be called to check if the object can fully evaluated
*/
public static final boolean isFullyEvaluatable(LanguageObject obj, boolean duringPlanning) {
- return EvaluatableVisitor.isEvaluatable(obj, duringPlanning, true, true, false);
+ return EvaluatableVisitor.isEvaluatable(obj, duringPlanning?EvaluationLevel.PLANNING:EvaluationLevel.PROCESSING);
}
public static final void replaceExpressions(LanguageObject obj, boolean deep, LookupEvaluator dataMgr, CommandContext context)
Deleted: trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/NeedsEvaluationVisitor.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/NeedsEvaluationVisitor.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/NeedsEvaluationVisitor.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -1,76 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package com.metamatrix.query.sql.visitor;
-
-import com.metamatrix.query.sql.LanguageObject;
-import com.metamatrix.query.sql.LanguageVisitor;
-import com.metamatrix.query.sql.lang.DependentSetCriteria;
-import com.metamatrix.query.sql.navigator.DeepPreOrderNavigator;
-import com.metamatrix.query.sql.symbol.Function;
-import com.metamatrix.query.sql.symbol.Reference;
-
-/**
- * Checks the language object for expressions or criteria that need to be evaluated at execution time
- */
-public class NeedsEvaluationVisitor extends LanguageVisitor {
-
- private boolean needsEvaluation = false;
-
- /**
- * @see com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.symbol.Reference)
- */
- @Override
- public void visit(Reference obj) {
- setNeedsEvaluation();
- }
-
- /**
- * @see com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.lang.DependentSetCriteria)
- */
- @Override
- public void visit(DependentSetCriteria obj) {
- setNeedsEvaluation();
- }
-
- /**
- * @see com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.symbol.Function)
- */
- @Override
- public void visit(Function obj) {
- if (EvaluatableVisitor.isEvaluatable(obj, false, true, false, false)) {
- setNeedsEvaluation();
- }
- }
-
- public void setNeedsEvaluation() {
- this.needsEvaluation = true;
- setAbort(true);
- }
-
- public static boolean needsEvaluation(LanguageObject obj) {
- NeedsEvaluationVisitor visitor = new NeedsEvaluationVisitor();
- DeepPreOrderNavigator.doVisit(obj, visitor);
- return visitor.needsEvaluation;
- }
-
-}
Modified: trunk/engine/src/main/java/com/metamatrix/query/util/CommandContext.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/util/CommandContext.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/com/metamatrix/query/util/CommandContext.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -98,6 +98,10 @@
private VariableContext variableContext = new VariableContext();
+ private CommandContext parent;
+
+ private boolean sessionFunctionEvaluated;
+
/**
* Construct a new context.
* @param collectNodeStatistics TODO
@@ -149,11 +153,27 @@
this.planToProcessConverter = context.planToProcessConverter;
this.queryProcessorFactory = context.queryProcessorFactory;
this.variableContext = context.variableContext;
+ this.parent = context;
}
public CommandContext() {
}
+ public boolean isSessionFunctionEvaluated() {
+ if (parent != null) {
+ return parent.isSessionFunctionEvaluated();
+ }
+ return sessionFunctionEvaluated;
+ }
+
+ public void setSessionFunctionEvaluated(boolean sessionFunctionEvaluated) {
+ if (parent != null) {
+ parent.setCollectNodeStatistics(sessionFunctionEvaluated);
+ } else {
+ this.sessionFunctionEvaluated = sessionFunctionEvaluated;
+ }
+ }
+
/**
* @return
*/
@@ -301,6 +321,9 @@
}
public double getNextRand() {
+ if (parent != null) {
+ return parent.getNextRand();
+ }
if (random == null) {
random = new Random();
}
@@ -308,6 +331,9 @@
}
public double getNextRand(long seed) {
+ if (parent != null) {
+ return parent.getNextRand(seed);
+ }
if (random == null) {
random = new Random();
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -37,7 +37,6 @@
import javax.transaction.SystemException;
import javax.transaction.xa.Xid;
-import org.teiid.connector.api.CacheScope;
import org.teiid.dqp.internal.cache.CacheID;
import org.teiid.dqp.internal.cache.DQPContextCache;
import org.teiid.dqp.internal.cache.ResultSetCache;
@@ -426,8 +425,6 @@
} catch (Exception e) {
LogManager.logWarning(LogConstants.CTX_DQP, e, "Failed to remove buffered tuples for connection " + sessionId); //$NON-NLS-1$
}
- // cleanup the prepared plan cache
- this.prepPlanCache.clear(sessionId);
if (transactionService != null) {
try {
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -29,6 +29,7 @@
import java.util.List;
import java.util.Map;
+import org.teiid.dqp.internal.process.PreparedPlanCache.CacheID;
import org.teiid.dqp.internal.process.multisource.MultiSourceMetadataWrapper;
import com.metamatrix.api.exception.MetaMatrixComponentException;
@@ -133,7 +134,7 @@
RequestWorkItem workItem = requestManager.getRequestWorkItem(requestID);
return getMetadataForCommand(workItem.getOriginalCommand());
}
- return obtainMetadataForPreparedSql(preparedSql, workContext.getConnectionID(), allowDoubleQuotedVariable);
+ return obtainMetadataForPreparedSql(preparedSql, workContext, allowDoubleQuotedVariable);
}
// For each projected symbol, construct a metadata map
@@ -204,17 +205,18 @@
return columnMetadata;
}
- private MetadataResult obtainMetadataForPreparedSql(String sql, String sessionId, boolean isDoubleQuotedVariablesAllowed) throws QueryParserException, QueryResolverException, MetaMatrixComponentException {
+ private MetadataResult obtainMetadataForPreparedSql(String sql, DQPWorkContext workContext, boolean isDoubleQuotedVariablesAllowed) throws QueryParserException, QueryResolverException, MetaMatrixComponentException {
Command command = null;
- PreparedPlanCache.PreparedPlan plan = planCache.getPreparedPlan(sessionId, sql);
+ ParseInfo info = new ParseInfo();
+ // Defect 19747 - the parser needs the following connection property to decide whether to treat double-quoted strings as variable names
+ info.allowDoubleQuotedVariable = isDoubleQuotedVariablesAllowed;
+ CacheID id = new PreparedPlanCache.CacheID(workContext, info, sql);
+ PreparedPlanCache.PreparedPlan plan = planCache.getPreparedPlan(id);
if(plan != null) {
command = plan.getCommand();
} else {
QueryParser parser = QueryParser.getQueryParser();
- ParseInfo info = new ParseInfo();
- // Defect 19747 - the parser needs the following connection property to decide whether to treat double-quoted strings as variable names
- info.allowDoubleQuotedVariable = isDoubleQuotedVariablesAllowed;
command = parser.parseCommand(sql, info);
QueryResolver.resolveCommand(command, Collections.EMPTY_MAP, false, this.metadata, AnalysisRecord.createNonRecordingRecord());
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedPlanCache.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedPlanCache.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedPlanCache.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -22,15 +22,18 @@
package org.teiid.dqp.internal.process;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
-import com.metamatrix.core.util.ArgCheck;
import com.metamatrix.core.util.HashCodeUtil;
import com.metamatrix.core.util.LRUCache;
import com.metamatrix.query.analysis.AnalysisRecord;
+import com.metamatrix.query.parser.ParseInfo;
import com.metamatrix.query.processor.ProcessorPlan;
import com.metamatrix.query.sql.lang.Command;
import com.metamatrix.query.sql.symbol.Reference;
+import com.metamatrix.vdb.runtime.VDBKey;
/**
* This class is used to cahce plan and related objects for prepared statement
@@ -38,7 +41,8 @@
public class PreparedPlanCache {
public static final int DEFAULT_MAX_SIZE_TOTAL = 100;
- private LRUCache<CacheID, PreparedPlan> cache;
+ private Map<CacheID, PreparedPlan> cache;
+ private int maxSize;
PreparedPlanCache(){
this(DEFAULT_MAX_SIZE_TOTAL);
@@ -48,7 +52,8 @@
if(maxSize < 0){
maxSize = DEFAULT_MAX_SIZE_TOTAL;
}
- cache = new LRUCache<CacheID, PreparedPlan>(maxSize);
+ this.maxSize = maxSize;
+ cache = Collections.synchronizedMap(new LRUCache<CacheID, PreparedPlan>(maxSize));
}
/**
@@ -57,71 +62,65 @@
* @param session ClientConnection
* @return PreparedPlan for the given clientConn and SQl query. Null if not exist.
*/
- public synchronized PreparedPlan getPreparedPlan(String sessionId, String sql){
- ArgCheck.isNotNull(sessionId);
- ArgCheck.isNotNull(sql);
-
- CacheID cID = new CacheID(sessionId, sql);
-
- return cache.get(cID);
+ public PreparedPlan getPreparedPlan(CacheID id){
+ id.setSessionId(id.originalSessionId);
+ PreparedPlan result = cache.get(id);
+ if (result == null) {
+ id.setSessionId(null);
+ }
+ return cache.get(id);
}
/**
* Create PreparedPlan for the given clientConn and SQl query
*/
- public synchronized PreparedPlan createPreparedPlan(String sessionId, String sql){
- ArgCheck.isNotNull(sessionId);
- ArgCheck.isNotNull(sql);
-
- CacheID cID = new CacheID(sessionId, sql);
- PreparedPlan preparedPlan = cache.get(cID);
- if(preparedPlan == null){
- preparedPlan = new PreparedPlan();
- cache.put(cID, preparedPlan);
+ public void putPreparedPlan(CacheID id, boolean sessionSpecific, PreparedPlan plan){
+ if (sessionSpecific) {
+ id.setSessionId(id.originalSessionId);
+ } else {
+ id.setSessionId(null);
}
- return preparedPlan;
+ this.cache.put(id, plan);
}
/**
- * Clear the cahced plans for the given clientConn
+ * Clear all the cached plans for all the clientConns
* @param clientConn ClientConnection
*/
- public synchronized void clear(String sessionId){
- ArgCheck.isNotNull(sessionId);
- //do not do anything
- }
-
- /**
- * Clear all the cahced plans for all the clientConns
- * @param clientConn ClientConnection
- */
- public synchronized void clearAll(){
+ public void clearAll(){
cache.clear();
}
static class CacheID{
- private String sessionId;
private String sql;
- int hashCode;
- private boolean isPreparedBatchUpdate;
-
- CacheID(String sessionId, String sql){
- this.sessionId = sessionId;
+ private VDBKey vdbInfo;
+ private ParseInfo pi;
+ private String sessionId;
+ private String originalSessionId;
+ private int hashCode;
+
+ CacheID(DQPWorkContext context, ParseInfo pi, String sql){
this.sql = sql;
- hashCode = HashCodeUtil.hashCode(HashCodeUtil.hashCode(0, sessionId), sql);
+ this.vdbInfo = new VDBKey(context.getVdbName(), context.getVdbVersion());
+ this.pi = pi;
+ this.originalSessionId = context.getConnectionID();
}
+ private void setSessionId(String sessionId) {
+ this.sessionId = sessionId;
+ hashCode = HashCodeUtil.hashCode(HashCodeUtil.hashCode(HashCodeUtil.hashCode(HashCodeUtil.hashCode(0, vdbInfo), sql), pi), sessionId);
+ }
+
public boolean equals(Object obj){
if(obj == this) {
return true;
- } else if(obj == null || ! (obj instanceof CacheID)) {
+ }
+ if(! (obj instanceof CacheID)) {
return false;
- } else {
- CacheID that = (CacheID)obj;
- return this.sessionId.equals(that.sessionId)
- && this.isPreparedBatchUpdate == that.isPreparedBatchUpdate
- && this.sql.equals(that.sql);
- }
+ }
+ CacheID that = (CacheID)obj;
+ return this.pi.equals(that.pi) && this.vdbInfo.equals(that.vdbInfo) && this.sql.equals(that.sql)
+ && ((this.sessionId == null && that.sessionId == null) || this.sessionId.equals(that.sessionId));
}
public int hashCode() {
@@ -207,7 +206,7 @@
return cache.size();
}
int getSpaceAllowed() {
- return cache.getSpaceLimit();
+ return maxSize;
}
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -26,6 +26,8 @@
import java.util.LinkedList;
import java.util.List;
+import org.teiid.dqp.internal.process.PreparedPlanCache.CacheID;
+
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.ExpressionEvaluationException;
import com.metamatrix.api.exception.query.QueryMetadataException;
@@ -138,12 +140,12 @@
* @see org.teiid.dqp.internal.process.Request#generatePlan()
*/
protected Command generatePlan() throws QueryPlannerException, QueryParserException, QueryResolverException, QueryValidatorException, MetaMatrixComponentException {
-
String sqlQuery = requestMsg.getCommands()[0];
- prepPlan = prepPlanCache.getPreparedPlan(this.workContext.getConnectionID(), sqlQuery);
+ CacheID id = new PreparedPlanCache.CacheID(this.workContext, Request.createParseInfo(this.requestMsg), sqlQuery);
+ prepPlan = prepPlanCache.getPreparedPlan(id);
if (prepPlan == null) {
//if prepared plan does not exist, create one
- prepPlan = prepPlanCache.createPreparedPlan(this.workContext.getConnectionID(), sqlQuery);
+ prepPlan = new PreparedPlanCache.PreparedPlan();
LogManager.logTrace(LogConstants.CTX_DQP, new Object[] { "Query does not exist in cache: ", sqlQuery}); //$NON-NLS-1$
}
@@ -153,10 +155,11 @@
if (cachedPlan == null) {
prepPlan.setRewritenCommand(super.generatePlan());
- if (!this.addedLimit) { //TODO: this is a little problematic
+ if (!this.addedLimit) { //TODO: this is a little problematic
// Defect 13751: Clone the plan in its current state (i.e. before processing) so that it can be used for later queries
prepPlan.setPlan((ProcessorPlan)processPlan.clone());
prepPlan.setAnalysisRecord(analysisRecord);
+ this.prepPlanCache.putPreparedPlan(id, this.context.isSessionFunctionEvaluated(), prepPlan);
}
command = prepPlan.getCommand();
} else {
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -335,8 +335,7 @@
private Command parseCommand() throws QueryParserException {
String[] commands = requestMsg.getCommands();
- ParseInfo parseInfo = new ParseInfo();
- parseInfo.allowDoubleQuotedVariable = requestMsg.isDoubleQuotedVariableAllowed();
+ ParseInfo parseInfo = createParseInfo(this.requestMsg);
if (!requestMsg.isBatchedUpdate()) {
String commandStr = commands[0];
return QueryParser.getQueryParser().parseCommand(commandStr, parseInfo);
@@ -349,6 +348,12 @@
return new BatchedUpdateCommand(parsedCommands);
}
+ public static ParseInfo createParseInfo(RequestMessage requestMsg) {
+ ParseInfo parseInfo = new ParseInfo();
+ parseInfo.allowDoubleQuotedVariable = requestMsg.isDoubleQuotedVariableAllowed();
+ return parseInfo;
+ }
+
public static void validateWithVisitor(
AbstractValidationVisitor visitor,
QueryMetadataInterface metadata,
Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestAccessNode.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestAccessNode.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestAccessNode.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -31,6 +31,7 @@
import com.metamatrix.common.buffer.TupleSource;
import com.metamatrix.query.parser.QueryParser;
import com.metamatrix.query.processor.ProcessorDataManager;
+import com.metamatrix.query.resolver.TestResolver;
import com.metamatrix.query.sql.lang.Command;
import com.metamatrix.query.sql.lang.CompoundCriteria;
import com.metamatrix.query.sql.lang.IsNullCriteria;
@@ -40,6 +41,7 @@
import com.metamatrix.query.sql.symbol.Constant;
import com.metamatrix.query.sql.symbol.ElementSymbol;
import com.metamatrix.query.sql.symbol.GroupSymbol;
+import com.metamatrix.query.unittest.FakeMetadataFactory;
import com.metamatrix.query.util.CommandContext;
@@ -66,7 +68,7 @@
}
public void testOpen_Defect16059() throws Exception {
- Query query = (Query)QueryParser.getQueryParser().parseCommand("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5 AND ? IS NULL"); //$NON-NLS-1$
+ Query query = (Query)TestResolver.helpResolve("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5 AND ? IS NULL", FakeMetadataFactory.example1Cached(), null); //$NON-NLS-1$
IsNullCriteria nullCrit = (IsNullCriteria)((CompoundCriteria)query.getCriteria()).getCriteria(1);
nullCrit.setExpression(new Constant(null));
@@ -74,7 +76,7 @@
}
public void testOpen_Defect16059_2() throws Exception {
- Query query = (Query)QueryParser.getQueryParser().parseCommand("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5 AND ? IS NOT NULL"); //$NON-NLS-1$
+ Query query = (Query)TestResolver.helpResolve("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5 AND ? IS NOT NULL", FakeMetadataFactory.example1Cached(), null); //$NON-NLS-1$
IsNullCriteria nullCrit = (IsNullCriteria)((CompoundCriteria)query.getCriteria()).getCriteria(1);
nullCrit.setExpression(new Constant(null));
@@ -84,7 +86,7 @@
public void testExecCount()throws Exception{
// Setup
AccessNode node = new AccessNode(1);
- Query query = (Query)QueryParser.getQueryParser().parseCommand("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5"); //$NON-NLS-1$
+ Query query = (Query)TestResolver.helpResolve("SELECT e1, e2 FROM pm1.g1 WHERE e2 = 5", FakeMetadataFactory.example1Cached(), null); //$NON-NLS-1$
node.setCommand(query);
CommandContext context = new CommandContext();
context.setProcessorID("processorID"); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestBatchedUpdateNode.java
===================================================================
--- trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestBatchedUpdateNode.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/test/java/com/metamatrix/query/processor/relational/TestBatchedUpdateNode.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -41,7 +41,7 @@
import com.metamatrix.query.processor.ProcessorDataManager;
import com.metamatrix.query.sql.lang.BatchedUpdateCommand;
import com.metamatrix.query.sql.lang.Command;
-import com.metamatrix.query.sql.visitor.NeedsEvaluationVisitor;
+import com.metamatrix.query.sql.visitor.EvaluatableVisitor;
import com.metamatrix.query.unittest.FakeMetadataFactory;
import com.metamatrix.query.util.CommandContext;
@@ -55,7 +55,7 @@
List<Command> commands = TestBatchedUpdatePlanner.helpGetCommands(sql, md);
List<Boolean> shouldEvaluate = new ArrayList<Boolean>(commands.size());
for (Command command : commands) {
- shouldEvaluate.add(NeedsEvaluationVisitor.needsEvaluation(command));
+ shouldEvaluate.add(EvaluatableVisitor.needsProcessingEvaluation(command));
}
BatchedUpdateNode node = new BatchedUpdateNode(1, commands, null, shouldEvaluate, "myModelName"); //$NON-NLS-1$
CommandContext context = new CommandContext();
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedPlanCache.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -26,46 +26,56 @@
import java.util.HashMap;
import java.util.Map;
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
import org.teiid.dqp.internal.process.PreparedPlanCache;
+import org.teiid.dqp.internal.process.PreparedPlanCache.CacheID;
-import junit.framework.TestCase;
-
import com.metamatrix.api.exception.query.QueryParserException;
import com.metamatrix.query.analysis.AnalysisRecord;
+import com.metamatrix.query.parser.ParseInfo;
import com.metamatrix.query.parser.QueryParser;
import com.metamatrix.query.processor.relational.ProjectNode;
import com.metamatrix.query.processor.relational.RelationalPlan;
import com.metamatrix.query.sql.lang.Command;
-
-public class TestPreparedPlanCache extends TestCase{
+public class TestPreparedPlanCache {
private static final String EXAMPLE_QUERY = "SELECT * FROM table"; //$NON-NLS-1$
- private final static String token = "1"; //$NON-NLS-1$
- private final static String token2 = "2"; //$NON-NLS-1$
-
- public TestPreparedPlanCache(String name) {
- super(name);
- }
+ private final static DQPWorkContext token = new DQPWorkContext();
+ private final static DQPWorkContext token2 = new DQPWorkContext();
+
+ private final static ParseInfo pi = new ParseInfo();
+
+ @BeforeClass public static void setUpOnce() {
+ token.setVdbName("foo"); //$NON-NLS-1$
+ token.setVdbVersion("1"); //$NON-NLS-1$
+ token2.setVdbName("foo"); //$NON-NLS-1$
+ token2.setVdbVersion("2"); //$NON-NLS-1$
+ }
//====Tests====//
- public void testCreatePreparedPlan(){
+ @Test public void testPutPreparedPlan(){
PreparedPlanCache cache = new PreparedPlanCache();
+ CacheID id = new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 1);
+
//No PreparedPlan at the begining
- assertNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 1));
+ assertNull(cache.getPreparedPlan(id));
//create one
- cache.createPreparedPlan(token, EXAMPLE_QUERY + 1);
+ cache.putPreparedPlan(id, true, new PreparedPlanCache.PreparedPlan());
//should have one now
- assertNotNull("Unable to get prepared plan from cache", cache.getPreparedPlan(token, EXAMPLE_QUERY + 1)); //$NON-NLS-1$
+ assertNotNull("Unable to get prepared plan from cache", cache.getPreparedPlan(id)); //$NON-NLS-1$
}
- public void testGetPreparedPlan(){
+ @Test public void testGetPreparedPlan(){
PreparedPlanCache cache = new PreparedPlanCache();
- helpCreatePreparedPlans(cache, token, 0, 10);
- helpCreatePreparedPlans(cache, token2, 0, 15);
+ helpPutPreparedPlans(cache, token, 0, 10);
+ helpPutPreparedPlans(cache, token2, 0, 15);
//read an entry for session2 (token2)
- PreparedPlanCache.PreparedPlan pPlan = cache.getPreparedPlan(token2, EXAMPLE_QUERY + 12);
+ PreparedPlanCache.PreparedPlan pPlan = cache.getPreparedPlan(new PreparedPlanCache.CacheID(token2, pi, EXAMPLE_QUERY + 12));
assertNotNull("Unable to get prepared plan from cache", pPlan); //$NON-NLS-1$
assertEquals("Error getting plan from cache", new RelationalPlan(new ProjectNode(12)).toString(), pPlan.getPlan().toString()); //$NON-NLS-1$
assertEquals("Error getting command from cache", EXAMPLE_QUERY + 12, pPlan.getCommand().toString()); //$NON-NLS-1$
@@ -73,55 +83,55 @@
assertEquals("Error gettting reference from cache", "ref12", pPlan.getReferences().get(0)); //$NON-NLS-1$ //$NON-NLS-2$
}
- public void testClearAll(){
+ @Test public void testClearAll(){
PreparedPlanCache cache = new PreparedPlanCache();
//create one for each session token
- cache.createPreparedPlan(token, EXAMPLE_QUERY + 1);
- cache.createPreparedPlan(token2, EXAMPLE_QUERY + 1);
+ helpPutPreparedPlans(cache, token, 1, 1);
+ helpPutPreparedPlans(cache, token2, 1, 1);
//should have one
- assertNotNull("Unable to get prepared plan from cache for token", cache.getPreparedPlan(token, EXAMPLE_QUERY + 1)); //$NON-NLS-1$
+ assertNotNull("Unable to get prepared plan from cache for token", cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 1))); //$NON-NLS-1$
cache.clearAll();
//should not exist for token
- assertNull("Failed remove from cache", cache.getPreparedPlan(token, EXAMPLE_QUERY + 1)); //$NON-NLS-1$
+ assertNull("Failed remove from cache", cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 1))); //$NON-NLS-1$
//should not exist for token2
- assertNull("Unable to get prepared plan from cache for token2", cache.getPreparedPlan(token2, EXAMPLE_QUERY + 1)); //$NON-NLS-1$
+ assertNull("Unable to get prepared plan from cache for token2", cache.getPreparedPlan(new PreparedPlanCache.CacheID(token2, pi, EXAMPLE_QUERY + 1))); //$NON-NLS-1$
}
- public void testMaxSize(){
+ @Test public void testMaxSize(){
PreparedPlanCache cache = new PreparedPlanCache(100);
- helpCreatePreparedPlans(cache, token, 0, 101);
+ helpPutPreparedPlans(cache, token, 0, 101);
//the first one should be gone because the max size is 100
- assertNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 0));
+ assertNull(cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 0)));
- assertNotNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 12));
- helpCreatePreparedPlans(cache, token, 102, 50);
+ assertNotNull(cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 12)));
+ helpPutPreparedPlans(cache, token, 102, 50);
//"sql12" should still be there based on lru policy
- assertNotNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 12));
+ assertNotNull(cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 12)));
- helpCreatePreparedPlans(cache, token2, 0, 121);
- helpCreatePreparedPlans(cache, token, 0, 50);
+ helpPutPreparedPlans(cache, token2, 0, 121);
+ helpPutPreparedPlans(cache, token, 0, 50);
assertTrue(cache.getSpaceUsed() <= 100);
}
- public void testZeroSizeCache() {
+ @Test public void testZeroSizeCache() {
// Create with 0 size cache
PreparedPlanCache cache = new PreparedPlanCache(0);
assertEquals(0, cache.getSpaceAllowed());
// Add 1 plan and verify it is not in the cache
- helpCreatePreparedPlans(cache, token, 0, 1);
- assertNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 0));
+ helpPutPreparedPlans(cache, token, 0, 1);
+ assertNull(cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 0)));
assertEquals(0, cache.getSpaceUsed());
// Add another plan and verify it is not in the cache
- helpCreatePreparedPlans(cache, token, 1, 1);
- assertNull(cache.getPreparedPlan(token, EXAMPLE_QUERY + 1));
+ helpPutPreparedPlans(cache, token, 1, 1);
+ assertNull(cache.getPreparedPlan(new PreparedPlanCache.CacheID(token, pi, EXAMPLE_QUERY + 1)));
assertEquals(0, cache.getSpaceUsed());
}
// set init size to negative number, which should default to 100 (default)
- public void testNegativeSizeCacheUsesDefault() {
+ @Test public void testNegativeSizeCacheUsesDefault() {
PreparedPlanCache negativeSizedCache = new PreparedPlanCache(-1000);
PreparedPlanCache defaultSizedCache = new PreparedPlanCache();
@@ -130,15 +140,18 @@
}
//====Help methods====//
- private void helpCreatePreparedPlans(PreparedPlanCache cache, String token, int start, int count){
- for(int i=start; i<count; i++){
+ private void helpPutPreparedPlans(PreparedPlanCache cache, DQPWorkContext session, int start, int count){
+ for(int i=0; i<count; i++){
Command dummy;
try {
- dummy = QueryParser.getQueryParser().parseCommand(EXAMPLE_QUERY + i);
+ dummy = QueryParser.getQueryParser().parseCommand(EXAMPLE_QUERY + (start + i));
} catch (QueryParserException e) {
throw new RuntimeException(e);
}
- PreparedPlanCache.PreparedPlan pPlan = cache.createPreparedPlan(token, dummy.toString());
+ CacheID id = new PreparedPlanCache.CacheID(session, pi, dummy.toString());
+
+ PreparedPlanCache.PreparedPlan pPlan = new PreparedPlanCache.PreparedPlan();
+ cache.putPreparedPlan(id, true, pPlan);
pPlan.setCommand(dummy);
pPlan.setPlan(new RelationalPlan(new ProjectNode(i)));
Map props = new HashMap();
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java 2009-04-20 20:41:11 UTC (rev 807)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/TestPreparedStatement.java 2009-04-20 21:02:03 UTC (rev 808)
@@ -27,13 +27,10 @@
import java.util.HashMap;
import java.util.List;
-import org.teiid.dqp.internal.process.DQPWorkContext;
-import org.teiid.dqp.internal.process.PreparedPlanCache;
-import org.teiid.dqp.internal.process.PreparedStatementRequest;
+import junit.framework.TestCase;
+
import org.teiid.dqp.internal.process.TestRequest.FakeApplicationEnvironment;
-import junit.framework.TestCase;
-
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.QueryParserException;
import com.metamatrix.api.exception.query.QueryPlannerException;
@@ -52,7 +49,6 @@
import com.metamatrix.query.optimizer.capabilities.SourceCapabilities.Capability;
import com.metamatrix.query.processor.FakeDataManager;
import com.metamatrix.query.processor.ProcessorDataManager;
-import com.metamatrix.query.processor.ProcessorPlan;
import com.metamatrix.query.processor.TestProcessor;
import com.metamatrix.query.unittest.FakeMetadataFacade;
import com.metamatrix.query.unittest.FakeMetadataFactory;
@@ -68,14 +64,14 @@
int hitCount;
@Override
- public synchronized PreparedPlan getPreparedPlan(
- String clientConn, String sql) {
- PreparedPlan plan = super.getPreparedPlan(clientConn, sql);
- if (plan != null && plan.getPlan() != null) {
+ public PreparedPlan getPreparedPlan(CacheID id) {
+ PreparedPlan result = super.getPreparedPlan(id);
+ if (result != null) {
hitCount++;
}
- return plan;
+ return result;
}
+
}
public TestPreparedStatement(String name) {
@@ -89,8 +85,12 @@
helpTestProcessing(preparedSql, values, expected, dataManager, metadata, callableStatement);
}
-
+
static void helpTestProcessing(String preparedSql, List values, List[] expected, ProcessorDataManager dataManager, QueryMetadataInterface metadata, boolean callableStatement) throws Exception {
+ helpTestProcessing(preparedSql, values, expected, dataManager, metadata, callableStatement, false);
+ }
+
+ static void helpTestProcessing(String preparedSql, List values, List[] expected, ProcessorDataManager dataManager, QueryMetadataInterface metadata, boolean callableStatement, boolean differentPlan) throws Exception {
TestablePreparedPlanCache prepPlan = new TestablePreparedPlanCache();
//Create plan
PreparedStatementRequest plan = TestPreparedStatement.helpGetProcessorPlan(preparedSql, values, new DefaultCapabilitiesFinder(), metadata, prepPlan, SESSION_ID, callableStatement, false);
@@ -110,7 +110,7 @@
//get the plan again with a new connection
assertNotNull(TestPreparedStatement.helpGetProcessorPlan(preparedSql, values, new DefaultCapabilitiesFinder(), metadata, prepPlan, 7, callableStatement, false));
- assertEquals("new connection should not have used the same plan", 1, prepPlan.hitCount); //$NON-NLS-1$
+ assertEquals(differentPlan?1:2, prepPlan.hitCount);
}
public void testWhere() throws Exception {
@@ -129,6 +129,23 @@
helpTestProcessing(preparedSql, values, expected, FakeMetadataFactory.example1Cached(), false);
}
+ public void testSessionSpecificFunction() throws Exception {
+ // Create query
+ String preparedSql = "SELECT user(), e2, pm1.g1.e3 as a, e4 as b FROM pm1.g1 WHERE e2=?"; //$NON-NLS-1$
+
+ // Create expected results
+ List[] expected = new List[] {
+ Arrays.asList(new Object[] { "foo", new Integer(0), Boolean.FALSE, new Double(2.0) }), //$NON-NLS-1$
+ Arrays.asList(new Object[] { "foo", new Integer(0), Boolean.FALSE, new Double(2.0) }) //$NON-NLS-1$
+ };
+
+ List values = new ArrayList();
+ values.add(new Short((short)0));
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+ helpTestProcessing(preparedSql, values, expected, dataManager, FakeMetadataFactory.example1Cached(), false, true);
+ }
+
public void testFunctionWithReferencePushDown() throws Exception {
// Create query
String preparedSql = "SELECT pm1.g1.e1 FROM pm1.g1, pm1.g2 WHERE pm1.g1.e1 = pm1.g2.e1 and pm1.g1.e2+2=?"; //$NON-NLS-1$
More information about the teiid-commits
mailing list