[teiid-commits] teiid SVN: r492 - in trunk/engine/src: main/java/com/metamatrix/query/optimizer/relational/rules and 9 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Feb 24 16:52:30 EST 2009


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) {
+        	
+        }
+        
+    }
 
 }




More information about the teiid-commits mailing list