Author: ghelblin
Date: 2009-02-24 16:52:30 -0500 (Tue, 24 Feb 2009)
New Revision: 492
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/proc/ProcedurePlanner.java
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanProcedures.java
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ExecDynamicSqlInstruction.java
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureAccessNode.java
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureCriteriaProcessor.java
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureExecutionNode.java
trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/com/metamatrix/query/rewriter/VariableSubstitutionVisitor.java
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Delete.java
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Insert.java
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/ProcedureContainer.java
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/StoredProcedure.java
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Update.java
trunk/engine/src/main/java/com/metamatrix/query/sql/symbol/Reference.java
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
trunk/engine/src/main/resources/com/metamatrix/query/execution/i18n.properties
trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcedureRelational.java
trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java
Log:
TEIID-148 - Allow runtime checking of NULL values
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/proc/ProcedurePlanner.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/optimizer/proc/ProcedurePlanner.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/optimizer/proc/ProcedurePlanner.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -25,6 +25,7 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.QueryMetadataException;
@@ -54,6 +55,7 @@
import com.metamatrix.query.sql.lang.Command;
import com.metamatrix.query.sql.lang.DynamicCommand;
import com.metamatrix.query.sql.lang.Into;
+import com.metamatrix.query.sql.lang.ProcedureContainer;
import com.metamatrix.query.sql.lang.Query;
import com.metamatrix.query.sql.proc.AssignmentStatement;
import com.metamatrix.query.sql.proc.Block;
@@ -107,6 +109,7 @@
// get the current command on the current node of the tree
Command procCommand = node.getCommand();
+
// set state of the planner with child nodes
// to be used while planning
List childNodes = node.getChildren();
@@ -135,6 +138,16 @@
ProcedureEnvironment env = new ProcedureEnvironment();
env.getProgramStack().push(programBlock);
ProcedurePlan plan = new ProcedurePlan(env);
+
+ // propagate procedure parameters to the plan to allow runtime type checking
+ ProcedureContainer container =
(ProcedureContainer)((CreateUpdateProcedureCommand) procCommand).getUserCommand();
+
+ if (container != null) {
+ Map params = container.getProcedureParameters();
+ plan.setParams(params);
+ plan.setMetadata(metadata);
+ }
+
env.initialize(plan);
env.setUpdateProcedure(((CreateUpdateProcedureCommand)procCommand).isUpdateProcedure());
env.setOutputElements(((CreateUpdateProcedureCommand)procCommand).getProjectedSymbols());
@@ -265,9 +278,9 @@
intoGroup = into.getGroup();
}
}
- List references = ReferenceCollectorVisitor.getReferences(command);
- ProcessorPlan commandPlan =
((CommandTreeNode)childNodes.get(childIndex.getChildIndex())).getProcessorPlan();
- childIndex.incrementChildIndex();
+ List references = ReferenceCollectorVisitor.getReferences(command);
+ ProcessorPlan commandPlan =
((CommandTreeNode)childNodes.get(childIndex.getChildIndex())).getProcessorPlan();
+ childIndex.incrementChildIndex();
if (command.getType() == Command.TYPE_DYNAMIC){
instruction = new
ExecDynamicSqlInstruction(parentProcCommand,((DynamicCommand)command), references,
metadata, idGenerator, capFinder );
@@ -343,7 +356,7 @@
}
return instruction;
}
-
+
static class ChildIndexHolder{
private int childIndex;
Modified:
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanProcedures.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanProcedures.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/optimizer/relational/rules/RulePlanProcedures.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -32,11 +32,9 @@
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.QueryMetadataException;
import com.metamatrix.api.exception.query.QueryPlannerException;
-import com.metamatrix.common.log.LogManager;
import com.metamatrix.query.analysis.AnalysisRecord;
import com.metamatrix.query.execution.QueryExecPlugin;
import com.metamatrix.query.metadata.QueryMetadataInterface;
-import com.metamatrix.query.metadata.SupportConstants;
import com.metamatrix.query.optimizer.capabilities.CapabilitiesFinder;
import com.metamatrix.query.optimizer.relational.OptimizerRule;
import com.metamatrix.query.optimizer.relational.RuleStack;
@@ -60,7 +58,6 @@
import com.metamatrix.query.sql.symbol.Reference;
import com.metamatrix.query.sql.visitor.ReferenceCollectorVisitor;
import com.metamatrix.query.util.CommandContext;
-import com.metamatrix.query.util.LogConstants;
public class RulePlanProcedures implements OptimizerRule {
@@ -95,9 +92,6 @@
List conjuncts = new LinkedList();
HashSet coveredParams = new HashSet();
//List preExecNodes = new LinkedList();
-
- // Case 6395 - maintain a list of non-nullable elements that are set IS NULL.
- List nonNullableElems = new LinkedList();
if (!proc.isProcedureRelational()) {
continue;
@@ -111,13 +105,8 @@
inputSymbols.add(symbol);
}
- findInputNodes(inputSymbols, critNode, conjuncts, coveredParams,
nonNullableElems, metadata);
+ findInputNodes(inputSymbols, critNode, conjuncts, coveredParams);
- // Check for non-nullable elements that are set IS NULL. throws exception if
any found.
- if(!nonNullableElems.isEmpty()) {
- throw new
QueryPlannerException(QueryExecPlugin.Util.getString("RulePlanProcedures.nonNullableParam",
nonNullableElems.get(0))); //$NON-NLS-1$
- }
-
List defaults = new LinkedList();
for (Iterator params = inputReferences.iterator(); params.hasNext();) {
@@ -162,8 +151,7 @@
private void findInputNodes(final HashSet inputs,
PlanNode critNode,
- final List conjuncts, final Set params, final List
nonNullableElems,
- final QueryMetadataInterface metadata) throws
QueryMetadataException, MetaMatrixComponentException {
+ final List conjuncts, final Set params) {
while (critNode.getType() == NodeConstants.Types.SELECT) {
final PlanNode currentNode = critNode;
@@ -201,24 +189,10 @@
setAbort(true);
}
- // method to add invalid isNull element
- private void addInvalidElem(ElementSymbol symbol) {
- nonNullableElems.add(symbol);
- }
-
- public void visit(IsNullCriteria isNull) {
+ public void visit(IsNullCriteria isNull){
if (isNull.isNegated()) {
return;
}
- // Case 6395 - check for non-nullable Elems that are IS NULL
- Expression expr = isNull.getExpression();
- if(expr instanceof Reference) {
- expr = ((Reference)expr).getExpression();
- }
- if(expr instanceof ElementSymbol
&&!isNullable((ElementSymbol)expr,metadata)) {
- addInvalidElem((ElementSymbol)expr);
- }
-
if (checkForInput(isNull.getExpression())) {
addInputNode((Reference)isNull.getExpression());
}
@@ -262,24 +236,13 @@
}
return false;
}
-
- boolean isNullable(ElementSymbol element, QueryMetadataInterface
metadata) {
- Object elemID = element.getMetadataID();
- try {
- return metadata.elementSupports(elemID,
SupportConstants.Element.NULL) ||
- metadata.elementSupports(elemID,
SupportConstants.Element.NULL_UNKNOWN);
- } catch (Exception e){
- LogManager.logWarning(LogConstants.CTX_QUERY_PLANNER, e ,
"Error getting isNullable on element: "+element.getShortName()); //$NON-NLS-1$
- return false;
- }
- }
};
PreOrderNavigator.doVisit(crit, visitor);
}
}
-
+
/**
* @see java.lang.Object#toString()
*/
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ExecDynamicSqlInstruction.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ExecDynamicSqlInstruction.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ExecDynamicSqlInstruction.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -43,6 +43,7 @@
import com.metamatrix.query.eval.Evaluator;
import com.metamatrix.query.execution.QueryExecPlugin;
import com.metamatrix.query.metadata.QueryMetadataInterface;
+import com.metamatrix.query.metadata.TempMetadataAdapter;
import com.metamatrix.query.metadata.TempMetadataStore;
import com.metamatrix.query.optimizer.QueryOptimizer;
import com.metamatrix.query.optimizer.capabilities.CapabilitiesFinder;
@@ -66,6 +67,7 @@
import com.metamatrix.query.sql.lang.Select;
import com.metamatrix.query.sql.lang.SetClause;
import com.metamatrix.query.sql.lang.SubqueryFromClause;
+import com.metamatrix.query.sql.lang.UnaryFromClause;
import com.metamatrix.query.sql.proc.CreateUpdateProcedureCommand;
import com.metamatrix.query.sql.symbol.AliasSymbol;
import com.metamatrix.query.sql.symbol.Constant;
@@ -212,7 +214,7 @@
// validation visitor?
- VariableSubstitutionVisitor.substituteVariables(command,
command.getVariableValues(), command.getType(), false);
+ VariableSubstitutionVisitor.substituteVariables(command,
command.getVariableValues(), command.getType());
QueryRewriter.rewrite(command, parentProcCommand, metadata,
procEnv.getContext());
@@ -334,14 +336,30 @@
Query query = new Query();
query.setSelect(select);
From from = new From();
- SubqueryFromClause sqfc = new SubqueryFromClause(subquery_group_name,
- command);
- from.addClause(sqfc);
- query.setFrom(from);
+
+ GroupSymbol inlineGroup = new GroupSymbol(subquery_group_name);
+
+ from.addClause(new UnaryFromClause(inlineGroup));
+ TempMetadataStore store = new TempMetadataStore();
+ TempMetadataAdapter tma = new TempMetadataAdapter(metadata, store);
+
+ store.addTempGroup(inlineGroup.getName(), command.getProjectedSymbols());
+ inlineGroup.setMetadataID(store.getTempGroupID(inlineGroup.getName()));
+ query.setFrom(from);
+ QueryResolver.resolveCommand(query, tma);
+ query.setOption(command.getOption());
+
+ from.getClauses().clear();
+ SubqueryFromClause sqfc = new SubqueryFromClause(inlineGroup.getName());
+ sqfc.setCommand(command);
+ sqfc.getGroupSymbol().setMetadataID(inlineGroup.getMetadataID());
+ from.addClause(sqfc);
+ //copy the metadata onto the new query so that temp metadata adapters will be
used in later calls
+ query.getTemporaryMetadata().putAll(store.getData());
+
if (dynamicCommand.getIntoGroup() != null) {
query.setInto(new Into(dynamicCommand.getIntoGroup()));
}
- QueryResolver.resolveCommand(query, metadata);
return query;
}
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/proc/ProcedurePlan.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -25,11 +25,13 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.MetaMatrixProcessingException;
+import com.metamatrix.api.exception.query.QueryValidatorException;
import com.metamatrix.common.buffer.BlockedException;
import com.metamatrix.common.buffer.BufferManager;
import com.metamatrix.common.buffer.TupleBatch;
@@ -39,9 +41,11 @@
import com.metamatrix.common.buffer.BufferManager.TupleSourceType;
import com.metamatrix.common.log.LogManager;
import com.metamatrix.core.MetaMatrixCoreException;
-import com.metamatrix.core.log.MessageLevel;
import com.metamatrix.core.util.Assertion;
+import com.metamatrix.query.eval.Evaluator;
import com.metamatrix.query.execution.QueryExecPlugin;
+import com.metamatrix.query.metadata.QueryMetadataInterface;
+import com.metamatrix.query.metadata.SupportConstants;
import com.metamatrix.query.processor.BaseProcessorPlan;
import com.metamatrix.query.processor.DescribableUtil;
import com.metamatrix.query.processor.ProcessorDataManager;
@@ -51,6 +55,9 @@
import com.metamatrix.query.processor.program.Program;
import com.metamatrix.query.processor.program.ProgramInstruction;
import com.metamatrix.query.processor.program.ProgramUtil;
+import com.metamatrix.query.sql.symbol.ElementSymbol;
+import com.metamatrix.query.sql.symbol.Expression;
+import com.metamatrix.query.sql.util.VariableContext;
import com.metamatrix.query.tempdata.TempTableStore;
import com.metamatrix.query.tempdata.TempTableStoreImpl;
import com.metamatrix.query.util.CommandContext;
@@ -79,7 +86,9 @@
private TupleSource finalTupleSource;
private int beginBatch = 1;
private List batchRows;
- private boolean lastBatch = false;
+ private boolean lastBatch = false;
+ private Map params;
+ private QueryMetadataInterface metadata;
/**
* Constructor for ProcedurePlan.
@@ -187,8 +196,8 @@
return env.getOutputElements();
}
- public void open()
- throws MetaMatrixComponentException {
+ public void open() throws MetaMatrixProcessingException, MetaMatrixComponentException
{
+ evaluateParams();
}
/**
@@ -336,7 +345,11 @@
clonedEnv.getProgramStack().push(originalProgram.clone());
clonedEnv.setUpdateProcedure(this.env.isUpdateProcedure());
clonedEnv.setOutputElements(this.env.getOutputElements());
- return new ProcedurePlan(clonedEnv);
+ ProcedurePlan plan = new ProcedurePlan(clonedEnv);
+ plan.setParams(params);
+ plan.setMetadata(metadata);
+
+ return plan;
}
protected void addBatchRow(List row) {
@@ -388,4 +401,35 @@
public Collection getChildPlans() {
return this.originalProgram.getChildPlans();
}
+
+ public void setMetadata( QueryMetadataInterface metadata ) {
+ this.metadata = metadata;
+ }
+
+ public void setParams( Map params ) {
+ this.params = params;
+ }
+
+ public void evaluateParams() throws BlockedException, MetaMatrixComponentException,
MetaMatrixProcessingException {
+
+ if ( params == null ) {
+ return;
+ }
+
+ for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
+ Map.Entry entry = (Map.Entry)iter.next();
+ ElementSymbol param = (ElementSymbol)entry.getKey();
+ Expression expr = (Expression)entry.getValue();
+
+ VariableContext context = env.getCurrentVariableContext();
+ Object value = new Evaluator(null, null, getContext()).evaluate(expr, null);
+
+ //check constraint
+ if (value == null && !metadata.elementSupports(param.getMetadataID(),
SupportConstants.Element.NULL)) {
+ throw new
QueryValidatorException(QueryExecPlugin.Util.getString("ProcedurePlan.nonNullableParam",
expr)); //$NON-NLS-1$
+ }
+ context.setValue(param, value);
+ }
+
+ }
}
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureAccessNode.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureAccessNode.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureAccessNode.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -28,6 +28,7 @@
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.MetaMatrixProcessingException;
+import com.metamatrix.query.eval.Evaluator;
import com.metamatrix.query.sql.lang.Command;
import com.metamatrix.query.sql.lang.Criteria;
@@ -93,7 +94,7 @@
protected boolean prepareNextCommand(Command atomicCommand) throws
MetaMatrixComponentException, MetaMatrixProcessingException {
if (this.criteriaProcessor == null) {
- this.criteriaProcessor = new DependentProcedureCriteriaProcessor(this,
(Criteria)inputCriteria.clone(), inputReferences, inputDefaults);
+ this.criteriaProcessor = new DependentProcedureCriteriaProcessor(this,
(Criteria)inputCriteria.clone(), inputReferences, inputDefaults, new Evaluator(null, null,
getContext()));
}
return criteriaProcessor.prepareNextCommand();
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureCriteriaProcessor.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureCriteriaProcessor.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureCriteriaProcessor.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -44,13 +44,15 @@
private List inputReferences;
private List inputDefaults;
private Criteria critInProgress;
+ private Evaluator eval;
public DependentProcedureCriteriaProcessor(RelationalNode dependentNode,
Criteria dependentCriteria,
List references,
- List defaults) {
+ List defaults,
+ Evaluator eval) {
super(1, dependentNode, dependentCriteria);
-
+ this.eval = eval;
this.inputDefaults = defaults;
this.inputReferences = references;
}
@@ -106,7 +108,7 @@
}
if (value instanceof Expression) {
- value = Evaluator.evaluate((Expression)value);
+ value = eval.evaluate((Expression)value, null);
}
if (value == null && !nullAllowed) {
Modified:
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureExecutionNode.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureExecutionNode.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/processor/relational/DependentProcedureExecutionNode.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -30,6 +30,7 @@
import com.metamatrix.api.exception.MetaMatrixProcessingException;
import com.metamatrix.common.buffer.BlockedException;
import com.metamatrix.common.buffer.TupleSourceNotFoundException;
+import com.metamatrix.query.eval.Evaluator;
import com.metamatrix.query.sql.lang.Criteria;
public class DependentProcedureExecutionNode extends PlanExecutionNode {
@@ -96,7 +97,7 @@
MetaMatrixComponentException,
MetaMatrixProcessingException {
if (this.criteriaProcessor == null) {
- this.criteriaProcessor = new DependentProcedureCriteriaProcessor(this,
(Criteria)inputCriteria.clone(), inputReferences, inputDefaults);
+ this.criteriaProcessor = new DependentProcedureCriteriaProcessor(this,
(Criteria)inputCriteria.clone(), inputReferences, inputDefaults, new Evaluator(null, null,
getContext()));
}
return criteriaProcessor.prepareNextCommand();
Modified: trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java 2009-02-24
18:28:11 UTC (rev 491)
+++ trunk/engine/src/main/java/com/metamatrix/query/rewriter/QueryRewriter.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -48,8 +48,10 @@
import com.metamatrix.api.exception.query.FunctionExecutionException;
import com.metamatrix.api.exception.query.InvalidFunctionException;
import com.metamatrix.api.exception.query.QueryMetadataException;
+import com.metamatrix.api.exception.query.QueryProcessingException;
import com.metamatrix.api.exception.query.QueryResolverException;
import com.metamatrix.api.exception.query.QueryValidatorException;
+import com.metamatrix.common.buffer.BlockedException;
import com.metamatrix.common.types.DataTypeManager;
import com.metamatrix.common.types.Transform;
import com.metamatrix.common.util.TimestampWithTimezone;
@@ -62,6 +64,7 @@
import com.metamatrix.query.function.FunctionLibrary;
import com.metamatrix.query.function.FunctionLibraryManager;
import com.metamatrix.query.metadata.QueryMetadataInterface;
+import com.metamatrix.query.metadata.SupportConstants;
import com.metamatrix.query.metadata.TempMetadataAdapter;
import com.metamatrix.query.metadata.TempMetadataID;
import com.metamatrix.query.metadata.TempMetadataStore;
@@ -188,8 +191,6 @@
*/
private static Command rewriteCommand(Command command, Command procCommand, final
QueryMetadataInterface metadata, final CommandContext context) throws
QueryValidatorException {
- boolean referencesRequired = false;
-
//TODO: this should be merged with the normal functioning of the rewriter
CorrelatedVariableSubstitutionVisitor.substituteVariables(command);
@@ -234,11 +235,9 @@
if (command instanceof ProcedureContainer) {
try {
- Map variables = QueryResolver.getVariableValues(command, metadata);
- //if we know at this point that the procedure wrapper can be
removed, then references will be forwarded in the call below
- boolean forwardReferences =
canRemoveProceduralWrapper((ProcedureContainer)command);
-
- referencesRequired |=
VariableSubstitutionVisitor.substituteVariables(subCommand, variables, command.getType(),
forwardReferences);
+ Map variables = QueryResolver.getVariableValues(command, metadata);
+ VariableSubstitutionVisitor.substituteVariables(subCommand,
variables, command.getType());
+
} catch (QueryMetadataException err) {
throw new QueryValidatorException(err, err.getMessage());
} catch (QueryResolverException err) {
@@ -253,24 +252,7 @@
}
}
- //there's a chance that rewriting caused the procedure to simplify, which
means that we should check again if the wrapper can be removed
- //TODO: handle empty procedure blocks
- if (!referencesRequired && (command instanceof ProcedureContainer)
&& canRemoveProceduralWrapper((ProcedureContainer)command)) {
- ProcedureContainer container = (ProcedureContainer)command;
- Block block =
((CreateUpdateProcedureCommand)container.getSubCommand()).getBlock();
- Command subCommand =
((CommandStatement)(block.getStatements().get(0))).getCommand();
-
- if ( subCommand.getOption() == null ) {
- subCommand.setOption( command.getOption() );
- } else {
- Option merged = mergeOptions( command.getOption(), subCommand.getOption()
);
- subCommand.setOption(merged);
- }
-
- return subCommand;
- }
-
- return command;
+ return removeProceduralWrapper(command, metadata);
}
private static Option mergeOptions( Option sourceOption, Option targetOption ) {
@@ -291,38 +273,70 @@
}
- private static boolean canRemoveProceduralWrapper(ProcedureContainer container)
throws QueryValidatorException {
+ private static Command removeProceduralWrapper(Command command,
QueryMetadataInterface metadata) throws QueryValidatorException {
- if (container instanceof StoredProcedure &&
((StoredProcedure)container).isProcedureRelational()) {
- return false;
+ if (!(command instanceof StoredProcedure)) {
+ return command;
}
+ StoredProcedure container = (StoredProcedure)command;
+ if (container.isProcedureRelational()) {
+ return command;
+ }
+
if (!(container.getSubCommand() instanceof CreateUpdateProcedureCommand)) {
- return false;
+ return command;
}
CreateUpdateProcedureCommand subCommand =
(CreateUpdateProcedureCommand)container.getSubCommand();
if (subCommand == null) {
- return false;
+ return command;
}
+
+ //if all parameters can be evaluated, we need to validate their values before
removing the procedure wrapper
+ for (Iterator iter = container.getInputParameters().iterator(); iter.hasNext();)
{
+ SPParameter param = (SPParameter)iter.next();
+ Expression expr = param.getExpression();
+ if (!EvaluateExpressionVisitor.isFullyEvaluatable(expr, true)) {
+ return command;
+ }
+ try {
+ Object value = Evaluator.evaluate(expr);
+
+ //check contraint
+ if (value == null &&
!metadata.elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+ throw new
QueryValidatorException(QueryExecPlugin.Util.getString("ProcedurePlan.nonNullableParam",
expr)); //$NON-NLS-1$
+ }
+ } catch (ExpressionEvaluationException err) {
+ } catch (BlockedException err) {
+ } catch (MetaMatrixComponentException err) {
+ }
+ }
+
Block block = subCommand.getBlock();
if (block.getStatements().size() != 1) {
- return false;
+ return command;
}
Statement statement = (Statement)block.getStatements().get(0);
if (statement.getType() != Statement.TYPE_COMMAND) {
- return false;
+ return command;
}
- Command command = (((CommandStatement)statement).getCommand());
+ Command child = (((CommandStatement)statement).getCommand());
- if (command != null && command.getType() != Command.TYPE_DYNAMIC) {
- return true;
+ if (child != null && child.getType() != Command.TYPE_DYNAMIC) {
+ if ( child.getOption() == null ) {
+ child.setOption( command.getOption() );
+ } else {
+ Option merged = mergeOptions( command.getOption(), child.getOption() );
+ child.setOption(merged);
+ }
+
+ return child;
}
-
- return false;
+ return command;
}
private static Command rewriteUpdateProcedure(CreateUpdateProcedureCommand procCommand,
QueryMetadataInterface metadata, CommandContext context)
Modified:
trunk/engine/src/main/java/com/metamatrix/query/rewriter/VariableSubstitutionVisitor.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/rewriter/VariableSubstitutionVisitor.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/rewriter/VariableSubstitutionVisitor.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -74,8 +74,6 @@
// substitution
private Collection invalidInput;
private int commandType;
- private boolean forwardReferences;
- private boolean referenceRequired;
private QueryResolverException conversionException = null;
@@ -83,10 +81,9 @@
* Construct a new visitor with the list of references.
* @param references A list of references on to be collected
*/
- public VariableSubstitutionVisitor(Map variableValues, int commandType, boolean
forwardReferences) {
+ public VariableSubstitutionVisitor(Map variableValues, int commandType) {
super(variableValues);
this.commandType = commandType;
- this.forwardReferences = forwardReferences;
}
// ############### Visitor methods for language objects ##################
@@ -196,21 +193,16 @@
Expression value =
(Expression)this.getVariableValues().get(symbol.getCanonicalName());
if (value != null) {
- expr = value;
- //don't forward references, instead wrap in a new reference
- //that will prevent setting the reference value by any other scope
than the what
- //created the reference
- if (!forwardReferences &&
!ReferenceCollectorVisitor.getReferences(expr).isEmpty()) {
- expr = new Reference(0, value);
- referenceRequired = true;
+ //don't forward references
+ if (!ReferenceCollectorVisitor.getReferences(value).isEmpty()) {
+ return expr;
}
+ expr = value;
} else if (grpName.equals(ProcedureReservedWords.INPUT)) {
expr = new Constant(null, symbol.getType());
} else if (grpName.equals(ProcedureReservedWords.CHANGING)) {
Assertion.failed("Changing value should not be null");
//$NON-NLS-1$
- } else if (grpName.equals(ProcedureReservedWords.VARIABLES) ||
!GroupSymbol.isTempGroupName(grpName)) {
- expr = new Reference(0, symbol);
- }
+ }
}
}
@@ -234,14 +226,14 @@
* @throws QueryValidatorException
* @throws QueryValidatorException
*/
- public static final boolean substituteVariables(
+ public static final void substituteVariables(
LanguageObject obj,
Map variableValues,
- int commandType, boolean forwardReferences) throws QueryValidatorException {
+ int commandType) throws QueryValidatorException {
VariableSubstitutionVisitor visitor =
- new VariableSubstitutionVisitor(variableValues, commandType, forwardReferences);
+ new VariableSubstitutionVisitor(variableValues, commandType);
if (obj == null) {
- return false;
+ return;
}
DeepPreOrderNavigator.doVisit(obj, visitor);
@@ -252,7 +244,6 @@
if (visitor.conversionException != null) {
throw new QueryValidatorException(visitor.conversionException,
visitor.conversionException.getMessage());
}
-
- return visitor.referenceRequired;
- }
+ }
+
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Delete.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Delete.java 2009-02-24
18:28:11 UTC (rev 491)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Delete.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -22,7 +22,9 @@
package com.metamatrix.query.sql.lang;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
import com.metamatrix.core.util.EquivalenceUtil;
import com.metamatrix.core.util.HashCodeUtil;
@@ -159,6 +161,14 @@
return EquivalenceUtil.areEqual(getGroup(), other.getGroup()) &&
EquivalenceUtil.areEqual(getCriteria(), other.getCriteria());
}
+
+ /**
+ * @see com.metamatrix.query.sql.lang.ProcedureContainer#getParameters()
+ * @since 5.0
+ */
+ public Map getProcedureParameters() {
+ return Collections.EMPTY_MAP;
+ }
/**
* Return a copy of this Delete.
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Insert.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Insert.java 2009-02-24
18:28:11 UTC (rev 491)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Insert.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -23,16 +23,20 @@
package com.metamatrix.query.sql.lang;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import com.metamatrix.core.util.EquivalenceUtil;
import com.metamatrix.core.util.HashCodeUtil;
import com.metamatrix.query.sql.LanguageVisitor;
+import com.metamatrix.query.sql.ProcedureReservedWords;
import com.metamatrix.query.sql.symbol.ElementSymbol;
import com.metamatrix.query.sql.symbol.Expression;
import com.metamatrix.query.sql.symbol.GroupSymbol;
+import com.metamatrix.query.sql.symbol.SingleElementSymbol;
/**
* Represents a SQL Insert statement of the form:
@@ -210,6 +214,23 @@
EquivalenceUtil.areEqual(getVariables(), other.getVariables()) &&
EquivalenceUtil.areEqual(getQueryExpression(),
other.getQueryExpression());
}
+
+ /**
+ * @see com.metamatrix.query.sql.lang.ProcedureContainer#getParameters()
+ * @since 5.0
+ */
+ public Map getProcedureParameters() {
+
+ int iSize = getVariables().size();
+ HashMap map = new HashMap();
+
+ for (int j = 0; j < iSize; j++) {
+ ElementSymbol symbol = (ElementSymbol)((ElementSymbol)variables.get( j
)).clone();
+ symbol.setName(ProcedureReservedWords.INPUT + SingleElementSymbol.SEPARATOR +
symbol.getShortCanonicalName());
+ map.put(symbol, values.get( j ) );
+ } // for
+ return map;
+ }
/**
* Return a deep copy of this Insert.
Modified:
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/ProcedureContainer.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/ProcedureContainer.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/ProcedureContainer.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import com.metamatrix.api.exception.MetaMatrixComponentException;
import com.metamatrix.api.exception.query.QueryMetadataException;
@@ -128,5 +129,6 @@
}
this.updateCount = updateCount;
}
-
+
+ public abstract Map getProcedureParameters();
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/StoredProcedure.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/StoredProcedure.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/sql/lang/StoredProcedure.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -414,6 +414,22 @@
public void setCallableStatement(boolean isCallableStatement) {
this.isCallableStatement = isCallableStatement;
}
+
+ /**
+ * @see com.metamatrix.query.sql.lang.ProcedureContainer#getProcedureParameters()
+ * @since 5.0
+ */
+ public Map getProcedureParameters() {
+
+ HashMap map = new HashMap();
+ for (Iterator iter = this.getInputParameters().iterator(); iter.hasNext();) {
+
+ SPParameter element = (SPParameter)iter.next();
+ map.put(element.getParameterSymbol(), element.getExpression());
+ } // for
+
+ return map;
+ }
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Update.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Update.java 2009-02-24
18:28:11 UTC (rev 491)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/lang/Update.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -22,14 +22,19 @@
package com.metamatrix.query.sql.lang;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import com.metamatrix.core.util.EquivalenceUtil;
import com.metamatrix.core.util.HashCodeUtil;
import com.metamatrix.query.sql.LanguageVisitor;
+import com.metamatrix.query.sql.ProcedureReservedWords;
import com.metamatrix.query.sql.symbol.ElementSymbol;
import com.metamatrix.query.sql.symbol.Expression;
import com.metamatrix.query.sql.symbol.GroupSymbol;
+import com.metamatrix.query.sql.symbol.SingleElementSymbol;
import com.metamatrix.query.sql.visitor.SQLStringVisitor;
/**
@@ -250,6 +255,25 @@
return false;
}
+ /**
+ * @see com.metamatrix.query.sql.lang.ProcedureContainer#getProcedureParameters()
+ * @since 5.0
+ */
+ public Map getProcedureParameters() {
+
+ HashMap map = new HashMap();
+
+ for (Iterator iter = getChangeList().getClauses().iterator(); iter.hasNext();) {
+ SetClause setClause = (SetClause)iter.next();
+ ElementSymbol symbol = (ElementSymbol)(setClause.getSymbol()).clone();
+ symbol.setName(ProcedureReservedWords.INPUT + SingleElementSymbol.SEPARATOR +
symbol.getShortCanonicalName());
+ map.put( symbol, setClause.getValue() );
+
+ } // for
+
+ return map;
+ }
+
}
Modified: trunk/engine/src/main/java/com/metamatrix/query/sql/symbol/Reference.java
===================================================================
--- trunk/engine/src/main/java/com/metamatrix/query/sql/symbol/Reference.java 2009-02-24
18:28:11 UTC (rev 491)
+++ trunk/engine/src/main/java/com/metamatrix/query/sql/symbol/Reference.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -23,6 +23,7 @@
package com.metamatrix.query.sql.symbol;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -109,6 +110,10 @@
}
public Object getValue(LookupEvaluator dataMgr, CommandContext context) throws
ExpressionEvaluationException, MetaMatrixComponentException {
+ if ( elements == null ) {
+ elements = Collections.EMPTY_MAP;
+ }
+
return new Evaluator(elements, dataMgr, context).evaluate(expression, tuple);
}
Modified:
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
---
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/java/com/metamatrix/query/sql/visitor/ExpressionMappingVisitor.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -278,26 +278,7 @@
}
obj.setRowLimit(replaceExpression(obj.getRowLimit()));
}
-
- public void visit(Insert obj) {
- // iterate over the list containing virtual elements/constants
- Iterator valuesIter = obj.getValues().iterator();
-
- // create a new list containing physical elements and constants
- List valuesList = new ArrayList(obj.getValues().size());
- while(valuesIter.hasNext()) {
- Expression exp = (Expression) valuesIter.next();
- valuesList.add( replaceExpression(exp) );
- }
- obj.setValues(valuesList);
- }
-
- public void visit(AssignmentStatement obj) {
- if (obj.hasExpression()) {
- obj.setExpression(replaceExpression(obj.getExpression()));
- }
- }
-
+
public void visit(DynamicCommand obj) {
obj.setSql(replaceExpression(obj.getSql()));
if (obj.getUsing() != null) {
@@ -342,5 +323,25 @@
protected Map getVariableValues() {
return symbolMap;
}
-
+
+ /**
+ * @see
com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.proc.AssignmentStatement)
+ * @since 5.0
+ */
+ public void visit(AssignmentStatement obj) {
+ if (obj.hasExpression()) {
+ obj.setExpression(replaceExpression(obj.getExpression()));
+ }
+ }
+
+ /**
+ * @see
com.metamatrix.query.sql.LanguageVisitor#visit(com.metamatrix.query.sql.lang.Insert)
+ * @since 5.0
+ */
+ public void visit(Insert obj) {
+ for (int i = 0; i < obj.getValues().size(); i++) {
+ obj.getValues().set(i,
replaceExpression((Expression)obj.getValues().get(i)));
+ }
+ }
+
}
Modified: trunk/engine/src/main/resources/com/metamatrix/query/execution/i18n.properties
===================================================================
---
trunk/engine/src/main/resources/com/metamatrix/query/execution/i18n.properties 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/main/resources/com/metamatrix/query/execution/i18n.properties 2009-02-24
21:52:30 UTC (rev 492)
@@ -195,8 +195,8 @@
tuple_not_found=Tuple source results for the mapping class {0} are not found;
unmapped_reference=Reference value for {0} is not supplied; can not continue.
RulePlanProcedures.no_values=No valid criteria specified for procedure parameter {0}
-RulePlanProcedures.nonNullableParam=The procedure parameter is not nullable, but is set
to null: {0}
-
+ProcedurePlan.nonNullableParam=The procedure parameter is not nullable, but is set to
null: {0}
+
BufferManagerImpl.no_memory_available=No memory available
BufferManagerImpl.tuple_source_not_found=Tuple source does not exist: {0}
FileStoreageManager.file_exists=Unable to create {0} as it already exists
Modified:
trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcedureRelational.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcedureRelational.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/test/java/com/metamatrix/query/processor/TestProcedureRelational.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -27,6 +27,7 @@
import junit.framework.TestCase;
+import com.metamatrix.api.exception.query.QueryValidatorException;
import com.metamatrix.common.types.DataTypeManager;
import com.metamatrix.dqp.message.ParameterInfo;
import com.metamatrix.query.mapping.relational.QueryNode;
@@ -523,7 +524,24 @@
TestProcedureProcessor.helpTestProcess(plan, expected, new FakeDataManager());
}
-
+
+ //virtual group with procedure in transformation
+ public void testCase6395ProcAsVirtualGroup9(){
+ String sql = "SELECT P.e2 as ve3, P.e1 as ve4 FROM pm1.vsp47 as P where
param1=1 and param2='a' OPTION DEBUG"; //$NON-NLS-1$
+
+ // Create expected results
+ List[] expected = new List[] {
+ Arrays.asList(new Object[] { new Integer(1), "FOO" }),
//$NON-NLS-1$
+ };
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+ // Plan query
+ ProcessorPlan plan = TestProcessor.helpGetPlan(sql,
FakeMetadataFactory.example1Cached());
+ // Run query
+ TestProcessor.helpProcess(plan, dataManager, expected);
+ }
+
/**
* Case 6395 - This test case will now raise a QueryPlannerException. param2 is
required
* and not nullable. This case is expected to fail because of 'param2 is
null'
@@ -538,16 +556,14 @@
FakeDataManager dataManager = new FakeDataManager();
TestProcessor.sampleData1(dataManager);
// Plan query
- ProcessorPlan plan = null;
try {
- plan = TestProcessor.helpGetPlan(sql, FakeMetadataFactory.example1Cached());
+ ProcessorPlan plan = TestProcessor.helpGetPlan(sql,
FakeMetadataFactory.example1Cached());
// Run query
- TestProcessor.helpProcess(plan, dataManager, expected);
- } catch (Exception e) {
+ TestProcessor.doProcess(plan, dataManager, expected,
TestProcessor.createCommandContext());
+ fail("QueryPlannerException was expected."); //$NON-NLS-1$
+ } catch (QueryValidatorException e) {
assertEquals("The procedure parameter is not nullable, but is set to null:
pm1.vsp26.param2",e.getMessage()); //$NON-NLS-1$
- return;
}
- fail("QueryPlannerException was expected."); //$NON-NLS-1$
}
/**
@@ -569,6 +585,24 @@
// Run query
TestProcessor.helpProcess(plan, dataManager, expected);
}
+
+ /**
+ * Case 6395 - This will not throw an exception and the proc will not be invoked.
+ */
+ public void testProcAsVirtualGroup2WithNull3() throws Exception {
+ String sql = "select e1 from (SELECT * FROM pm1.vsp26 as P where
P.e1='a') x where param1=1 and param2 = commandpayload()"; //$NON-NLS-1$
+
+ // Create expected results
+ List[] expected = new List[] {
+ };
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ TestProcessor.sampleData1(dataManager);
+ // Plan query
+ ProcessorPlan plan = TestProcessor.helpGetPlan(sql,
FakeMetadataFactory.example1Cached());
+ // Run query
+ TestProcessor.helpProcess(plan, dataManager, expected);
+ }
/*
* The following are tests that were removed from the validator. We are no longer
trying to validate a priori whether
Modified: trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java
===================================================================
---
trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java 2009-02-24
18:28:11 UTC (rev 491)
+++
trunk/engine/src/test/java/com/metamatrix/query/rewriter/TestQueryRewriter.java 2009-02-24
21:52:30 UTC (rev 492)
@@ -22,54 +22,55 @@
package com.metamatrix.query.rewriter;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+import com.metamatrix.api.exception.MetaMatrixComponentException;
+import com.metamatrix.api.exception.MetaMatrixException;
+import com.metamatrix.api.exception.query.QueryMetadataException;
+import com.metamatrix.api.exception.query.QueryParserException;
+import com.metamatrix.api.exception.query.QueryResolverException;
+import com.metamatrix.api.exception.query.QueryValidatorException;
+import com.metamatrix.common.types.DataTypeManager;
+import com.metamatrix.core.MetaMatrixRuntimeException;
+import com.metamatrix.dqp.message.ParameterInfo;
+import com.metamatrix.query.metadata.QueryMetadataInterface;
+import com.metamatrix.query.parser.QueryParser;
+import com.metamatrix.query.resolver.QueryResolver;
+import com.metamatrix.query.sql.lang.Command;
+import com.metamatrix.query.sql.lang.CompareCriteria;
+import com.metamatrix.query.sql.lang.CompoundCriteria;
+import com.metamatrix.query.sql.lang.Criteria;
+import com.metamatrix.query.sql.lang.MatchCriteria;
+import com.metamatrix.query.sql.lang.Query;
+import com.metamatrix.query.sql.lang.QueryCommand;
+import com.metamatrix.query.sql.lang.SPParameter;
+import com.metamatrix.query.sql.lang.SetCriteria;
+import com.metamatrix.query.sql.lang.SetQuery;
+import com.metamatrix.query.sql.lang.StoredProcedure;
+import com.metamatrix.query.sql.lang.Update;
+import com.metamatrix.query.sql.symbol.Constant;
+import com.metamatrix.query.sql.symbol.ElementSymbol;
+import com.metamatrix.query.sql.symbol.ExpressionSymbol;
+import com.metamatrix.query.sql.symbol.Function;
+import com.metamatrix.query.sql.symbol.GroupSymbol;
+import com.metamatrix.query.sql.symbol.SingleElementSymbol;
+import com.metamatrix.query.sql.visitor.CorrelatedReferenceCollectorVisitor;
+import com.metamatrix.query.unittest.FakeMetadataFacade;
+import com.metamatrix.query.unittest.FakeMetadataFactory;
+import com.metamatrix.query.unittest.FakeMetadataObject;
+import com.metamatrix.query.util.CommandContext;
+import com.metamatrix.query.util.ContextProperties;
-import junit.framework.TestCase;
-
-import com.metamatrix.api.exception.MetaMatrixComponentException;
-import com.metamatrix.api.exception.MetaMatrixException;
-import com.metamatrix.api.exception.query.QueryMetadataException;
-import com.metamatrix.api.exception.query.QueryParserException;
-import com.metamatrix.api.exception.query.QueryResolverException;
-import com.metamatrix.api.exception.query.QueryValidatorException;
-import com.metamatrix.common.types.DataTypeManager;
-import com.metamatrix.core.MetaMatrixRuntimeException;
-import com.metamatrix.dqp.message.ParameterInfo;
-import com.metamatrix.query.metadata.QueryMetadataInterface;
-import com.metamatrix.query.parser.QueryParser;
-import com.metamatrix.query.resolver.QueryResolver;
-import com.metamatrix.query.sql.lang.Command;
-import com.metamatrix.query.sql.lang.CompareCriteria;
-import com.metamatrix.query.sql.lang.CompoundCriteria;
-import com.metamatrix.query.sql.lang.Criteria;
-import com.metamatrix.query.sql.lang.MatchCriteria;
-import com.metamatrix.query.sql.lang.Query;
-import com.metamatrix.query.sql.lang.QueryCommand;
-import com.metamatrix.query.sql.lang.SPParameter;
-import com.metamatrix.query.sql.lang.SetCriteria;
-import com.metamatrix.query.sql.lang.SetQuery;
-import com.metamatrix.query.sql.lang.StoredProcedure;
-import com.metamatrix.query.sql.lang.Update;
-import com.metamatrix.query.sql.symbol.Constant;
-import com.metamatrix.query.sql.symbol.ElementSymbol;
-import com.metamatrix.query.sql.symbol.Function;
-import com.metamatrix.query.sql.symbol.GroupSymbol;
-import com.metamatrix.query.sql.symbol.SingleElementSymbol;
-import com.metamatrix.query.sql.visitor.CorrelatedReferenceCollectorVisitor;
-import com.metamatrix.query.unittest.FakeMetadataFacade;
-import com.metamatrix.query.unittest.FakeMetadataFactory;
-import com.metamatrix.query.unittest.FakeMetadataObject;
-import com.metamatrix.query.util.CommandContext;
-import com.metamatrix.query.util.ContextProperties;
-
public class TestQueryRewriter extends TestCase {
private static final String TRUE_STR = "1 = 1"; //$NON-NLS-1$
@@ -176,7 +177,7 @@
private Command helpTestRewriteCommand(String original, String expected,
QueryMetadataInterface metadata) throws MetaMatrixException {
Command command = QueryParser.getQueryParser().parseCommand(original);
QueryResolver.resolveCommand(command, metadata);
- Command rewriteCommand = QueryRewriter.rewrite(command, null,
FakeMetadataFactory.example1Cached(), null);
+ Command rewriteCommand = QueryRewriter.rewrite(command, null, metadata, null);
assertEquals("Rewritten command was not expected", expected,
rewriteCommand.toString()); //$NON-NLS-1$
return rewriteCommand;
}
@@ -1733,6 +1734,17 @@
public void testDefect16879_7(){
helpTestRewriteCommand("SELECT decodeinteger(e1, 'a, b, null, d, e')
FROM pm1.g1", "SELECT CASE WHEN e1 = 'a' THEN 'b' WHEN e1 IS
NULL THEN 'd' ELSE 'e' END FROM pm1.g1"); //$NON-NLS-1$
//$NON-NLS-2$
}
+
+ public void testCaseExpressionThatResolvesToNull() {
+ String sqlBefore = "SELECT CASE 'x' WHEN 'Old Inventory
System' THEN NULL WHEN 'New Inventory System' THEN NULL END";
//$NON-NLS-1$
+ String sqlAfter = "SELECT null"; //$NON-NLS-1$
+
+ Command cmd = helpTestRewriteCommand( sqlBefore, sqlAfter );
+
+ ExpressionSymbol es = (ExpressionSymbol)cmd.getProjectedSymbols().get(0);
+ assertEquals( DataTypeManager.DefaultDataClasses.STRING, es.getType() );
+ }
+
//note that the env is now treated as deterministic, however it is really only
deterministic within a session
public void testRewriteExecEnv() throws Exception {
@@ -2097,5 +2109,17 @@
public void testRewriteCoalesce() throws Exception {
helpTestRewriteCriteria("coalesce(convert(pm1.g1.e2, double), pm1.g1.e4) =
1", "ifnull(convert(pm1.g1.e2, double), pm1.g1.e4) = 1", true);
//$NON-NLS-1$ //$NON-NLS-2$
}
+
+ public void testProcWithNull() throws Exception {
+ String sql = "exec pm1.vsp26(1, null)"; //$NON-NLS-1$
+
+ try {
+ helpTestRewriteCommand(sql, "",
FakeMetadataFactory.example1Cached());
+ fail("expected exception");
+ } catch (QueryValidatorException e) {
+
+ }
+
+ }
}