[teiid-commits] teiid SVN: r2663 - in trunk: documentation/reference/src/main/docbook/en-US/content and 9 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Tue Oct 19 16:10:51 EDT 2010


Author: shawkins
Date: 2010-10-19 16:10:47 -0400 (Tue, 19 Oct 2010)
New Revision: 2663

Removed:
   trunk/engine/src/main/resources/org/teiid/dqp/
Modified:
   trunk/build/kits/jboss-container/teiid-releasenotes.html
   trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
   trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
   trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
   trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
   trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
   trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/processor/HardcodedDataManager.java
   trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
   trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
Log:
TEIID-1237 finishing off the update of procedure assignment logic updates.

Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html	2010-10-19 20:10:47 UTC (rev 2663)
@@ -40,7 +40,9 @@
     <LI><B>Binary Web Service Calls</B> - the ws translator now provides an invokeHttp procedure to return the blob contents and string content type of an http/https call.
     <LI><B>Improved clustering support</B> - see the Admin Guide chapter on clustering.
     <LI><B>IPv6 support</B> - Teiid can started using IPv6 bind address and can be used with JDBC connection.
-    <LI><B>SESSION_ID</b> - A new system function "SESSION_ID" is added to the system function library.    
+    <LI><B>SESSION_ID</B> - A new system function "SESSION_ID" is added to the system function library.
+    <LI><B>Assignment Syntax Improvements<B> - Teiid's procedure syntax for assignments was clarified so that the assignment value must be a proper expression.  INSERT/UPDATE/DELETE update counts must be obtained from VARIABLES.ROWCOUNT, scalar values must be obtained via a scalar subquery.  
+    The parser will continue to accept the old syntax and convert the query into the proper form.      
 </UL>
 
 <h2><a name="Compatibility">Compatibility Issues</a></h2>

Modified: trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml	2010-10-19 20:10:47 UTC (rev 2663)
@@ -27,6 +27,9 @@
         <programlisting>SELECT * FROM MySchema.MyTable WHERE ColA &gt; 100;
 INSERT INTO MySchema.MyTable (ColA,ColB) VALUES (50, 'hi');</programlisting>
         </example>
+      <para><link linkend="exec_command">EXECUTE</link> command statements may access IN/OUT, OUT, and RETURN parameters.  To access the return value the statement will have the form <code>var = EXEC proc...</code>.  
+      To access OUT or IN/OUT values named parameter syntax must be used.  For example, <code>EXEC proc(in_param=>'1', out_param=>var)</code> will assign the value of the out parameter to the variable var.
+      It is expected that the datatype of parameter will be implicitly convertable to the datatype of the variable.</para>
     </section>
     <section id="dynamic_sql">
       <title>Dynamic SQL Command</title>
@@ -108,7 +111,7 @@
             <title>Example Assignment
             </title>
             <programlisting>EXECUTE STRING &lt;expression&gt; AS x string INTO #temp; 
-DECLARE string VARIABLES.RESULT = SEELCT x FROM #temp;</programlisting>
+DECLARE string VARIABLES.RESULT = (SELECT x FROM #temp);</programlisting>
           </example>
         </listitem>
         <listitem>
@@ -178,11 +181,15 @@
           <para>The VARIABLES group is always implied even if it is not specified.
           </para>
         </listitem>
+        <listitem>
+          <para>The assignment value follows the same rules as for an Assignment Statement.
+          </para>
+        </listitem>
       </itemizedlist>
     </section>
     <section>
       <title>Assignment Statement</title>
-      <para>An assignment statement assigns a value to a variable by either evaluating an expression or executing a SELECT command that returns a column value from a single row.</para>
+      <para>An assignment statement assigns a value to a variable by either evaluating an expression.</para>
       <para>
         Usage:
         <synopsis label="Usage" >&lt;variable reference&gt; = &lt;expression&gt;;</synopsis>
@@ -194,10 +201,21 @@
           </para>
         </listitem>
         <listitem>
-          <para>VARIABLES.x = SELECT Column1 FROM MySchema.MyTable;
+          <para>VARIABLES.x = (SELECT Column1 FROM MySchema.MyTable);
           </para>
         </listitem>
       </itemizedlist>
+      <section>
+	      <title>Special Variables</title>
+	      <para><code>VARIABLES.ROWCOUNT</code> integer variable will contain the numbers of rows affected by the last insert/update/delete command statement executed.  Inserts that are processed by dynamic sql with an into clause will also update the ROWCOUNT.</para>
+	      <example>
+			<title>Sample Usage</title>
+			<programlisting language="SQL"><![CDATA[...
+UPDATE FOO SET X = 1 WHERE Y = 2;
+DECLARE INTEGER UPDATED = VARIABLES.ROWCOUNT;
+...]]></programlisting>
+		  </example>
+  	  </section>
     </section>
     <section>
       <title>If Statement</title>
@@ -282,8 +300,8 @@
         the procedure. The BEGIN and END keywords are used to denote block
         boundaries. Within the body of the procedure, any valid <link linkend="procedure_language">statement</link> may be used.
       </para>
-      <para>The last command statement executed in the procedure will be
-        return as the result. The output of that statement must match the
+      <para>There is no explict cursoring or return statement, rather the last command statement executed in the procedure that returns a result set will be
+        returned as the result. The output of that statement must match the
         expected result set and parameters of the procedure.</para>      
     </section>
     <section>
@@ -374,30 +392,13 @@
         or variables in the procedure.</para>
       <para> A virtual procedure call will return a result set just like any
         SELECT, so you can use this in many places you can use a SELECT.
-        However, within a virtual procedure itself you cannot always use an
-        EXEC directly. Instead, you use the following syntax:</para>
-      <programlisting>SELECT * FROM (EXEC ...) AS x</programlisting>
-      <itemizedlist>
-        <para>The following are some examples of how you can use the
-          results of a virtual procedure call within a virtual procedure
-          definition:</para>
-        <listitem>
-          <para>LOOP instruction - you can walk through the results and
-            do work on a row-by-row basis</para>
-        </listitem>
-        <listitem>
-          <para>Assignment instruction - you can run a command and
-            set the first column / first row value returned to a variable
-          </para>
-        </listitem>
-        <listitem>
-          <para><code>SELECT * INTO #temp FROM (EXEC ...) AS x</code> - you can
-            select the results from a virtual procedure into a temp table,
-            which you can then query against as if it were a physical table.
-          </para>
-        </listitem>
-      </itemizedlist>  
+        Typically you'll use the following syntax:</para>
+      <programlisting>SELECT * FROM (EXEC ...) AS x</programlisting>  
     </section>
+    <section>
+    	<title>Limitations</title>
+    	<para>Teiid virtual procedures can only be defined in Teiid Designer.  They also cannot use IN/OUT, OUT, or RETURN paramters and may only return 1 result set.</para>
+    </section>
   </section>  
   <section id="update_procedures">
     <title>Update Procedures</title>
@@ -427,7 +428,7 @@
   ...
 END</synopsis>
       </para>
-      <para>The CREATE VIRTUAL PROCEDURE line demarcates the beginning of
+      <para>The CREATE PROCEDURE line demarcates the beginning of
         the procedure. The BEGIN and END keywords are used to denote block
         boundaries. Within the body of the procedure, any valid <link linkend="procedure_language">statement</link> may be used.
       </para>
@@ -472,13 +473,20 @@
       </section>
       <section id="rowsupdated_variable">
         <title>ROWS_UPDATED Variable</title>
-        <para> Teiid returns the value of the VARIABLES.ROWS_UPDATED variable as a response to an update command executed against
+        <para> Teiid returns the value of the integer VARIABLES.ROWS_UPDATED variable as a response to an update command executed against
           the view. Your procedure must set the value that returns
           when an application executes an update command against the view, 
           which triggers invocation of the update procedure. For
           example, if an UPDATE command is issued that affects 5 records, the
           ROWS_UPDATED should be set appropriately so that the user will
           receive '5' for the count of records affected.</para>
+          <example>
+			<title>Sample Usage</title>
+			<programlisting language="SQL"><![CDATA[...
+UPDATE FOO SET X = 1 WHERE TRANSLATE CRITERIA;
+VARIABLES.ROWS_UPDATED = VARIABLES.ROWCOUNT;
+...]]></programlisting>
+		  </example>
       </section>
     </section>  
     <section>

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/ProcedurePlanner.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -22,6 +22,9 @@
 
 package org.teiid.query.optimizer;
 
+import java.util.LinkedHashMap;
+import java.util.Map;
+
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryPlannerException;
 import org.teiid.core.TeiidComponentException;
@@ -46,6 +49,8 @@
 import org.teiid.query.processor.proc.WhileInstruction;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.DynamicCommand;
+import org.teiid.query.sql.lang.SPParameter;
+import org.teiid.query.sql.lang.StoredProcedure;
 import org.teiid.query.sql.proc.AssignmentStatement;
 import org.teiid.query.sql.proc.Block;
 import org.teiid.query.sql.proc.CommandStatement;
@@ -55,7 +60,9 @@
 import org.teiid.query.sql.proc.RaiseErrorStatement;
 import org.teiid.query.sql.proc.Statement;
 import org.teiid.query.sql.proc.WhileStatement;
+import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.Reference;
 import org.teiid.query.sql.visitor.CommandCollectorVisitor;
 import org.teiid.query.util.CommandContext;
 
@@ -228,6 +235,29 @@
 							command.getType() == Command.TYPE_INSERT 
 							|| command.getType() == Command.TYPE_UPDATE
 							|| command.getType() == Command.TYPE_DELETE);
+					//handle stored procedure calls
+					if (command.getType() == Command.TYPE_STORED_PROCEDURE) {
+						StoredProcedure sp = (StoredProcedure)command;
+						if (sp.isCallableStatement()) {
+							Map<ElementSymbol, ElementSymbol> assignments = new LinkedHashMap<ElementSymbol, ElementSymbol>();
+							for (SPParameter param : sp.getParameters()) {
+								if (param.getParameterType() == SPParameter.RESULT_SET 
+										|| param.getParameterType() == SPParameter.IN) {
+									continue;
+								}
+								Expression expr = param.getExpression();
+								if (expr instanceof Reference) {
+									expr = ((Reference)expr).getExpression();
+								}
+								ElementSymbol symbol = null;
+								if (expr instanceof ElementSymbol) {
+									symbol = (ElementSymbol)expr; 
+								}
+								assignments.put(param.getParameterSymbol(), symbol);
+							}
+							((CreateCursorResultSetInstruction)instruction).setProcAssignments(assignments);
+						}
+					}
 				}
                 
 				if(debug) {

Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/CreateCursorResultSetInstruction.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -26,11 +26,14 @@
 
 import static org.teiid.query.analysis.AnalysisRecord.*;
 
+import java.util.Map;
+
 import org.teiid.client.plan.PlanNode;
 import org.teiid.common.buffer.BlockedException;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.processor.ProcessorPlan;
+import org.teiid.query.sql.symbol.ElementSymbol;
 
 
 /**
@@ -42,6 +45,7 @@
     protected String rsName;
     protected ProcessorPlan plan;
     private boolean update;
+    private Map<ElementSymbol, ElementSymbol> procAssignments;
     
     public CreateCursorResultSetInstruction(String rsName, ProcessorPlan plan, boolean update){
         this.rsName = rsName;
@@ -49,15 +53,11 @@
         this.update = update;
     }
     
-    /**
-     * If the result set named rsName does not exist yet in the {@link ProcedurePlan}, then
-     * this instruction will define that result set.  It will then throw a BlockedException if
-     * this result set is selecting from other than temp groups (because those results will be
-     * delivered asynchronously).  IF the result set named rsName does already exist, this 
-     * instruction will just increment the program counter and do nothing else.
-     * @throws BlockedException if this result set is not selecting from
-     * only temp groups
-     */
+    public void setProcAssignments(
+			Map<ElementSymbol, ElementSymbol> procAssignments) {
+		this.procAssignments = procAssignments;
+	}
+    
     public void process(ProcedurePlan procEnv)
         throws BlockedException, TeiidComponentException, TeiidProcessingException {
 
@@ -65,7 +65,7 @@
             procEnv.removeResults(rsName);
         }
         
-        procEnv.executePlan(plan, rsName);
+        procEnv.executePlan(plan, rsName, procAssignments, !update);
         
         if (update) {
         	boolean hasNext = procEnv.iterateCursor(rsName);
@@ -83,7 +83,9 @@
      */
     public CreateCursorResultSetInstruction clone(){
         ProcessorPlan clonedPlan = this.plan.clone();
-        return new CreateCursorResultSetInstruction(this.rsName, clonedPlan, update);
+        CreateCursorResultSetInstruction clone = new CreateCursorResultSetInstruction(this.rsName, clonedPlan, update);
+        clone.setProcAssignments(procAssignments);
+        return clone;
     }
     
     public String toString(){

Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/LoopInstruction.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -91,7 +91,7 @@
 
     public boolean testCondition(ProcedurePlan procEnv) throws TeiidComponentException, TeiidProcessingException {
         if(!procEnv.resultSetExists(rsName)) {
-            procEnv.executePlan(plan, rsName);            
+            procEnv.executePlan(plan, rsName, null, false);            
         }
         
         return procEnv.iterateCursor(rsName);

Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -22,7 +22,7 @@
 
 package org.teiid.query.processor.proc;
 
-import static org.teiid.query.analysis.AnalysisRecord.PROP_OUTPUT_COLS;
+import static org.teiid.query.analysis.AnalysisRecord.*;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -42,9 +42,13 @@
 import org.teiid.common.buffer.BufferManager;
 import org.teiid.common.buffer.IndexedTupleSource;
 import org.teiid.common.buffer.TupleBatch;
+import org.teiid.common.buffer.TupleBuffer;
 import org.teiid.common.buffer.TupleSource;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.Assertion;
 import org.teiid.logging.LogManager;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.analysis.AnalysisRecord;
@@ -73,6 +77,7 @@
 		QueryProcessor processor;
 		IndexedTupleSource ts;
 		List<?> currentRow;
+		TupleBuffer resultsBuffer;
 	}
 	
     private Program originalProgram;
@@ -418,7 +423,7 @@
 		return this.currentVarContext;
     }
 
-    public void executePlan(ProcessorPlan command, String rsName)
+    public void executePlan(ProcessorPlan command, String rsName, Map<ElementSymbol, ElementSymbol> procAssignments, boolean keepRs)
         throws TeiidComponentException, TeiidProcessingException {
     	
         CursorState state = this.cursorStates.get(rsName.toUpperCase());
@@ -433,16 +438,45 @@
 		        state = new CursorState();
 		        state.processor = new QueryProcessor(command, subContext, this.bufferMgr, this.dataMgr);
 		        state.ts = new BatchIterator(state.processor);
-		        
-	            //keep a reference to the tuple source
-	            //it may be the last one
-	            this.lastTupleSource = state.ts;
-	            
+		        if (procAssignments != null && state.processor.getOutputElements().size() - procAssignments.size() > 0) {
+		        	state.resultsBuffer = bufferMgr.createTupleBuffer(state.processor.getOutputElements().subList(0, state.processor.getOutputElements().size() - procAssignments.size()), getContext().getConnectionID(), TupleSourceType.PROCESSOR);
+		        }
 	            this.currentState = state;
         	}
         	//force execution to the first batch
         	this.currentState.ts.hasNext();
+            if (procAssignments != null) {
+            	while (this.currentState.ts.hasNext()) {
+            		if (this.currentState.currentRow != null && this.currentState.resultsBuffer != null) {
+            			this.currentState.resultsBuffer.addTuple(this.currentState.currentRow.subList(0, this.currentState.resultsBuffer.getSchema().size()));
+            			this.currentState.currentRow = null;
+            		}
+            		this.currentState.currentRow = this.currentState.ts.nextTuple();
+            	}
+            	//process assignments
+            	Assertion.assertTrue(this.currentState.currentRow != null);
+            	for (Map.Entry<ElementSymbol, ElementSymbol> entry : procAssignments.entrySet()) {
+            		if (entry.getValue() == null) {
+            			continue;
+            		}
+            		int index = this.currentState.processor.getOutputElements().indexOf(entry.getKey());
+            		getCurrentVariableContext().setValue(entry.getValue(), DataTypeManager.transformValue(this.currentState.currentRow.get(index), entry.getValue().getType()));
+				}
+            	//no resultset
+            	if (this.currentState.resultsBuffer == null) {
+            		this.currentState.processor.closeProcessing();
+            		this.currentState = null;
+            		return;
+            	}
+            	this.currentState.resultsBuffer.close();
+            	this.currentState.ts = this.currentState.resultsBuffer.createIndexedTupleSource();
+            }
 	        this.cursorStates.put(rsName.toUpperCase(), this.currentState);
+	        //keep a reference to the tuple source
+            //it may be the last one
+	        if (keepRs) {
+	        	this.lastTupleSource = this.currentState.ts;
+	        }
 	        this.currentState = null;
         }
     }
@@ -542,6 +576,9 @@
         CursorState state = this.cursorStates.remove(rsKey);
         if (state != null) {
         	state.processor.closeProcessing();
+        	if (state.resultsBuffer != null) {
+        		state.resultsBuffer.remove();
+        	}
         }
     }
 

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -270,34 +270,41 @@
             while(paramIter.hasNext()) {
                 SPParameter param = (SPParameter) paramIter.next();
                 Expression expr = param.getExpression();
-                if(expr != null) {
-                    for (SubqueryContainer container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr)) {
-                        QueryResolver.setChildMetadata(container.getCommand(), command);
-                        
-                        QueryResolver.resolveCommand(container.getCommand(), Collections.EMPTY_MAP, metadata.getMetadata(), analysis);
-                    }
-                    ResolverVisitor.resolveLanguageObject(expr, null, externalGroups, metadata);
-                    Class paramType = param.getClassType();
-
-                    ResolverUtil.setDesiredType(expr, paramType, storedProcedureCommand);
+                if(expr == null) {
+                	continue;
+                }
+                for (SubqueryContainer container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr)) {
+                    QueryResolver.setChildMetadata(container.getCommand(), command);
                     
-                    // Compare type of parameter expression against parameter type
-                    // and add implicit conversion if necessary
-                    Class exprType = expr.getType();
-                    if(paramType == null || exprType == null) {
-                        throw new QueryResolverException("ERR.015.008.0061", QueryPlugin.Util.getString("ERR.015.008.0061", storedProcedureCommand.getProcedureName(), param.getName())); //$NON-NLS-1$ //$NON-NLS-2$
-                    }
-                    String tgtType = DataTypeManager.getDataTypeName(paramType);
-                    String srcType = DataTypeManager.getDataTypeName(exprType);
-                    Expression result = null;
-                    
-                    try {
-                        result = ResolverUtil.convertExpression(expr, tgtType, metadata);
-                    } catch (QueryResolverException e) {
-                        throw new QueryResolverException(e, QueryPlugin.Util.getString("ExecResolver.Param_convert_fail", new Object[] { srcType, tgtType}));                                     //$NON-NLS-1$
-                    }                                                       
-                    param.setExpression(result);
+                    QueryResolver.resolveCommand(container.getCommand(), Collections.EMPTY_MAP, metadata.getMetadata(), analysis);
                 }
+                ResolverVisitor.resolveLanguageObject(expr, null, externalGroups, metadata);
+                Class paramType = param.getClassType();
+
+                ResolverUtil.setDesiredType(expr, paramType, storedProcedureCommand);
+                
+                // Compare type of parameter expression against parameter type
+                // and add implicit conversion if necessary
+                Class exprType = expr.getType();
+                if(paramType == null || exprType == null) {
+                    throw new QueryResolverException("ERR.015.008.0061", QueryPlugin.Util.getString("ERR.015.008.0061", storedProcedureCommand.getProcedureName(), param.getName())); //$NON-NLS-1$ //$NON-NLS-2$
+                }
+                String tgtType = DataTypeManager.getDataTypeName(paramType);
+                String srcType = DataTypeManager.getDataTypeName(exprType);
+                Expression result = null;
+                                
+                if (param.getParameterType() == SPParameter.RETURN_VALUE || param.getParameterType() == SPParameter.OUT) {
+                	if (!ResolverUtil.canImplicitlyConvert(tgtType, srcType)) {
+                		throw new QueryResolverException(QueryPlugin.Util.getString("ExecResolver.out_type_mismatch", param.getParameterSymbol(), tgtType, srcType)); //$NON-NLS-1$
+                	}
+                } else {
+	                try {
+	                    result = ResolverUtil.convertExpression(expr, tgtType, metadata);
+	                } catch (QueryResolverException e) {
+	                    throw new QueryResolverException(e, QueryPlugin.Util.getString("ExecResolver.Param_convert_fail", new Object[] { srcType, tgtType}));                                     //$NON-NLS-1$
+	                }                                                       
+	                param.setExpression(result);
+                }
             }
         }
     }

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2010-10-19 20:10:47 UTC (rev 2663)
@@ -634,6 +634,7 @@
 Evaluator.xmlquery=Error evaluating XMLQuery: {0}
 ExecResolver.Param_convert_fail=Unable to convert procedural parameter of type {0} to expected type {1}
 ExecResolver.return_expected=Procedure {0} does not have a return value.
+ExecResolver.out_type_mismatch=OUT/RETURN parameter {0} with type {1} cannot be converted to {2}
 DynamicCommandResolver.SQL_String=Expected dynamic command sql to be of type STRING instead of type {0}.
 UnionQueryResolver.type_conversion=The Expression {0} used in a nested UNION ORDER BY clause cannot be implicitly converted from type {1} to type {2}.
 ValidationVisitor.select_into_no_implicit_conversion=There is no implicit conversion between the source element type ({0}) and the target element type ({1}) at position {2} of the query: {3}

Modified: trunk/engine/src/test/java/org/teiid/query/processor/HardcodedDataManager.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/HardcodedDataManager.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/test/java/org/teiid/query/processor/HardcodedDataManager.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -43,7 +43,7 @@
                                  ProcessorDataManager {
 
     // sql string to data
-    private Map data = new HashMap();
+    private Map<String, List[]> data = new HashMap<String, List[]>();
     
     // valid models - if null, any is assumed valid
     private Set validModels;
@@ -53,7 +53,7 @@
     private boolean blockOnce;
     
     // Collect all commands run against this class
-    private List commandHistory = new ArrayList(); // Commands
+    private List<Command> commandHistory = new ArrayList<Command>(); // Commands
     
     public HardcodedDataManager() {
     	this(true);
@@ -123,7 +123,7 @@
         
         List projectedSymbols = command.getProjectedSymbols();
 
-        List[] rows = (List[]) data.get(command.toString());
+        List[] rows = data.get(command.toString());
         if(rows == null) {
             if (mustRegisterCommands) {
                 throw new TeiidComponentException("Unknown command: " + command.toString());  //$NON-NLS-1$

Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -28,7 +28,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.junit.Ignore;
 import org.junit.Test;
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.api.exception.query.QueryProcessingException;
@@ -2651,14 +2650,14 @@
         helpTestProcess(plan, expected, new HardcodedDataManager(), metadata);
     }
     
-    @Ignore
-    @Test public void testProcReturn() throws Exception {
+    @Test public void testParameterAssignments() throws Exception {
         TransformationMetadata metadata = RealMetadataFactory.exampleBQTCached();
         String userQuery = "EXEC TEIIDSP7(1)"; //$NON-NLS-1$
         HardcodedDataManager dataMgr = new HardcodedDataManager();
         ProcessorPlan plan = getProcedurePlan(userQuery, metadata);
         dataMgr.addData("VARIABLES.x = EXEC spTest9(1)", new List[] {Arrays.asList(3)});
-        List[] expected = new List[] {Arrays.asList(new Object[] {new Integer(3)})};
+        dataMgr.addData("EXEC spTest11(3, null)", new List[] {Arrays.asList("1", 1, null), Arrays.asList(null, null, 4)});
+        List[] expected = new List[] {Arrays.asList("34")};
         helpTestProcess(plan, expected, dataMgr, metadata);
     }
     

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -2883,6 +2883,10 @@
     	assertEquals(3, proc.getProjectedSymbols().size());
     }
     
+    @Test public void testOutWithWrongType() {
+    	helpResolveException("exec pm2.spTest8(inkey=>1, outkey=>{t '12:00:00'})", FakeMetadataFactory.exampleBQTCached());
+    }
+    
     @Test public void testProcRelationalWithOutParam() {
     	Query proc = (Query)helpResolve("select * from pm2.spTest8 where inkey = 1", FakeMetadataFactory.exampleBQTCached(), null);
     	assertEquals(3, proc.getProjectedSymbols().size());

Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java	2010-10-19 19:10:06 UTC (rev 2662)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java	2010-10-19 20:10:47 UTC (rev 2663)
@@ -259,7 +259,7 @@
         
         ColumnSet<Procedure> vsprs7 = createResultSet("TEIIDSP7.vsprs1", new String[] { "StringKey" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$
         ProcedureParameter vsp7p1 = createParameter("p1", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
-        QueryNode vspqn7 = new QueryNode("TEIIDSP7", "CREATE VIRTUAL PROCEDURE BEGIN declare integer x; x = exec spTest9(p1); select convert(x, string); END"); //$NON-NLS-1$ //$NON-NLS-2$
+        QueryNode vspqn7 = new QueryNode("TEIIDSP7", "CREATE VIRTUAL PROCEDURE BEGIN declare integer x; x = exec spTest9(p1); declare integer y; exec spTest11(inkey=>x, outkey=>y); select convert(x, string) || y; END"); //$NON-NLS-1$ //$NON-NLS-2$
         Procedure vsp7 = createVirtualProcedure("TEIIDSP7", mmspTest1, Arrays.asList(vsp7p1), vspqn7); //$NON-NLS-1$
         vsp7.setResultSet(vsprs7);
         



More information about the teiid-commits mailing list