[teiid-commits] teiid SVN: r4382 - in trunk: api/src/main/java/org/teiid/metadata and 27 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Aug 30 13:48:03 EDT 2012


Author: shawkins
Date: 2012-08-30 13:48:02 -0400 (Thu, 30 Aug 2012)
New Revision: 4382

Modified:
   trunk/api/src/main/java/org/teiid/language/SQLConstants.java
   trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
   trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
   trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
   trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
   trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
   trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
   trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java
   trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
   trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java
   trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
   trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
   trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java
   trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java
   trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
   trunk/engine/src/main/java/org/teiid/query/sql/lang/SPParameter.java
   trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/Constant.java
   trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
   trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
   trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
   trunk/engine/src/main/resources/org/teiid/metadata/SYSADMIN.sql
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java
   trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
   trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
   trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
   trunk/engine/src/test/java/org/teiid/query/resolver/CheckNoTempMetadataIDsVisitor.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
   trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
   trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
   trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestConstant.java
Log:
TEIID-2111 adding support for procedure varargs

Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -119,11 +119,12 @@
 		
 		public static final String TRIM = "TRIM"; //$NON-NLS-1$
 		public static final String RESULT = "RESULT"; //$NON-NLS-1$
-		public static final Object OBJECTTABLE = "OBJECTTABLE"; //$NON-NLS-1$
-		public static final Object VERSION = "VERSION"; //$NON-NLS-1$
-		public static final Object INCLUDING = "INCLUDING"; //$NON-NLS-1$
-		public static final Object EXCLUDING = "EXCLUDING"; //$NON-NLS-1$
-		public static final Object XMLDECLARATION = "XMLDECLARATION"; //$NON-NLS-1$
+		public static final String OBJECTTABLE = "OBJECTTABLE"; //$NON-NLS-1$
+		public static final String VERSION = "VERSION"; //$NON-NLS-1$
+		public static final String INCLUDING = "INCLUDING"; //$NON-NLS-1$
+		public static final String EXCLUDING = "EXCLUDING"; //$NON-NLS-1$
+		public static final String XMLDECLARATION = "XMLDECLARATION"; //$NON-NLS-1$
+		public static final String VARIADIC = "VARIADIC"; //$NON-NLS-1$
 	}
 	
 	public interface Reserved {

Modified: trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/api/src/main/java/org/teiid/metadata/FunctionMethod.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -485,14 +485,14 @@
 			FunctionMethod function) {
 		String deterministic = procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "deterministic", true); //$NON-NLS-1$
 		boolean nullOnNull = Boolean.valueOf(procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "null-on-null", true)); //$NON-NLS-1$
-		boolean varargs = Boolean.valueOf(procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "varargs", true)); //$NON-NLS-1$
+		String varargs = procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "varargs", true); //$NON-NLS-1$
 		boolean aggregate = Boolean.valueOf(procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "aggregate", true)); //$NON-NLS-1$
 		if (deterministic != null) {
 			function.setDeterminism(Boolean.valueOf(deterministic)?Determinism.DETERMINISTIC:Determinism.NONDETERMINISTIC);
 		}
 		function.setNullOnNull(nullOnNull);
-		if (varargs && !function.getInputParameters().isEmpty()) {
-			function.getInputParameters().get(function.getInputParameterCount() - 1).setVarArg(varargs);
+		if (varargs != null && !function.getInputParameters().isEmpty()) {
+			function.getInputParameters().get(function.getInputParameterCount() - 1).setVarArg(Boolean.valueOf(varargs));
 		}
 		if (aggregate) {
 			boolean analytic = Boolean.valueOf(procedureRecord.getProperty(AbstractMetadataRecord.RELATIONAL_URI + "analytic", true)); //$NON-NLS-1$

Modified: trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/api/src/main/java/org/teiid/metadata/MetadataFactory.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -31,6 +31,7 @@
 import java.util.TreeMap;
 
 import org.teiid.connector.DataPlugin;
+import org.teiid.metadata.ProcedureParameter.Type;
 import org.teiid.translator.TranslatorException;
 import org.teiid.translator.TypeFacility;
 
@@ -297,8 +298,15 @@
 		param.setType(parameterType);
 		param.setProcedure(procedure);
 		setColumnType(type, param);
-		procedure.getParameters().add(param);
-		param.setPosition(procedure.getParameters().size()); //1 based indexing
+		if (parameterType == Type.ReturnValue) {
+			procedure.getParameters().add(0, param);
+			for (int i = 0; i < procedure.getParameters().size(); i++) {
+				procedure.getParameters().get(i).setPosition(i+1); //1 based indexing
+			}
+		} else {
+			procedure.getParameters().add(param);
+			param.setPosition(procedure.getParameters().size()); //1 based indexing
+		}
 		return param;
 	}
 	

Modified: trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java
===================================================================
--- trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/common-core/src/main/java/org/teiid/core/types/DataTypeManager.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -23,6 +23,7 @@
 package org.teiid.core.types;
 
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Array;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.sql.Blob;
@@ -65,6 +66,7 @@
  */
 public class DataTypeManager {
 	
+	private static final String ARRAY_SUFFIX = "[]"; //$NON-NLS-1$
 	private static final boolean USE_VALUE_CACHE = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.useValueCache", false); //$NON-NLS-1$
 	private static final boolean COMPARABLE_LOBS = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.comparableLobs", false); //$NON-NLS-1$
 	private static final boolean COMPARABLE_OBJECT = PropertiesUtils.getBooleanProperty(System.getProperties(), "org.teiid.comparableObject", false); //$NON-NLS-1$
@@ -377,6 +379,9 @@
 		}
 
 		if (dataTypeClass == null) {
+			if (name.endsWith(ARRAY_SUFFIX)) {
+				return getArrayType(getDataTypeClass(name.substring(0, name.length() - 2)));
+			}
 			dataTypeClass = DefaultDataClasses.OBJECT;
 		}
 		return dataTypeClass;
@@ -386,9 +391,11 @@
 		if (typeClass == null) {
 			return DefaultDataTypes.NULL;
 		}
-
 		String result = dataTypeClasses.get(typeClass);
 		if (result == null) {
+			if (typeClass.isArray()) {
+				return getDataTypeName(typeClass.getComponentType()) + ARRAY_SUFFIX; 
+			}
 			result = DefaultDataTypes.OBJECT;
 		}
 
@@ -905,4 +912,8 @@
 				|| type == DataTypeManager.DefaultDataClasses.OBJECT);
 	}
 
+	public static Class<?> getArrayType(Class<?> classType) {
+		return Array.newInstance(classType, 0).getClass();
+	}
+
 }

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -551,7 +551,7 @@
     }
     
     org.teiid.language.Array translate(Array array) {
-    	return new org.teiid.language.Array(array.getBaseType(), translateExpressionList(array.getExpressions()));
+    	return new org.teiid.language.Array(array.getComponentType(), translateExpressionList(array.getExpressions()));
     }
     
     org.teiid.language.WindowFunction translate(WindowFunction windowFunction) {
@@ -819,6 +819,14 @@
             //we can assume for now that all arguments will be literals, which may be multivalued
             Literal value = null;
             if (direction != Direction.OUT) {
+            	if (param.isVarArg()) {
+            		ArrayValue av = (ArrayValue) ((Constant)param.getExpression()).getValue();
+            		for (Object obj : av.getValues()) {
+                        Argument arg = new Argument(direction, new Literal(obj, param.getClassType().getComponentType()), param.getClassType().getComponentType(), metadataParam);
+                        translatedParameters.add(arg);
+            		}
+            		break;
+            	}
             	value = (Literal)translate(param.getExpression());
             }
             Argument arg = new Argument(direction, value, param.getClassType(), metadataParam);

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/DataTierManagerImpl.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -344,7 +344,7 @@
 					for (Procedure proc : schema.getProcedures().values()) {
 						for (ProcedureParameter param : proc.getParameters()) {
 							Datatype dt = param.getDatatype();
-							rows.add(Arrays.asList(vdbName, proc.getParent().getName(), proc.getName(), param.getName(), dt!=null?dt.getRuntimeTypeName():null, param.getPosition(), param.getType().toString(), param.isOptional(), 
+							rows.add(Arrays.asList(vdbName, proc.getParent().getName(), proc.getName(), param.getName(), dt!=null?dt.getRuntimeTypeName():null, param.getPosition(), param.getType().name(), param.isOptional(), 
 									param.getPrecision(), param.getLength(), param.getScale(), param.getRadix(), param.getNullType().toString(), param.getUUID(), param.getAnnotation(), oid++));
 						}
 						if (proc.getResultSet() != null) {

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/MetaDataProcessor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -22,6 +22,7 @@
 
 package org.teiid.dqp.internal.process;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -178,7 +179,7 @@
         if (originalCommand instanceof StoredProcedure) {
         	StoredProcedure sp = (StoredProcedure)originalCommand;
         	paramMap = new HashMap<Reference, String>();
-        	List<SPParameter> params = sp.getParameters();
+        	Collection<SPParameter> params = sp.getParameters();
         	for (SPParameter spParameter : params) {
 				if (spParameter.getParameterType() != SPParameter.INOUT 
 						&& spParameter.getParameterType() != SPParameter.IN
@@ -190,7 +191,7 @@
 					ex = ((Function)ex).getArg(0);
 				}
 				if (ex instanceof Reference) {
-					paramMap.put((Reference)ex, Symbol.getShortName(spParameter.getName()));
+					paramMap.put((Reference)ex, spParameter.getParameterSymbol().getShortName());
 				}
 			}
         }

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/PreparedStatementRequest.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -74,56 +74,15 @@
     @Override
     protected void checkReferences(List<Reference> references)
     		throws QueryValidatorException {
+    	for (Iterator<Reference> i = references.iterator(); i.hasNext();) {
+    		if (i.next().isOptional()) {
+    			i.remove(); //remove any optional parameter, which accounts for out params - the client does not send any bindings
+    		}
+    	}
         prepPlan.setReferences(references);
     }
     
     /** 
-     * @see org.teiid.dqp.internal.process.Request#resolveCommand(org.teiid.query.sql.lang.Command)
-     */
-    @Override
-    protected void resolveCommand(Command command) throws QueryResolverException,
-                                                  TeiidComponentException {
-    	handleCallableStatement(command);
-    	
-    	super.resolveCommand(command);
-    }
-
-    /**
-     * TODO: this is a hack that maintains pre 5.6 behavior, which ignores output parameters for resolving
-     * @param command
-     * @param references
-     */
-	private void handleCallableStatement(Command command) {
-		if (!this.requestMsg.isCallableStatement() || !(command instanceof StoredProcedure)) {
-    		return;
-    	}
-		StoredProcedure proc = (StoredProcedure)command;
-		if (!proc.isCallableStatement()) {
-			return;
-		}
-		List<?> values = requestMsg.getParameterValues();
-		List<SPParameter> spParams = proc.getParameters();
-		proc.clearParameters();
-		int inParameterCount = values.size();
-		if (this.requestMsg.isBatchedUpdate() && values.size() > 0) {
-			inParameterCount = ((List)values.get(0)).size();
-		}
-		int index = 1;
-		for (Iterator<SPParameter> params = spParams.iterator(); params.hasNext();) {
-			SPParameter param = params.next();
-			if (param.getParameterType() == SPParameter.RETURN_VALUE) {
-				inParameterCount++;
-			} else if (param.getExpression() instanceof Reference && index > inParameterCount) {
-				//assume it's an output parameter
-				this.prepPlan.getReferences().remove(param.getExpression());
-				continue;
-			}
-			param.setIndex(index++);
-			proc.setParameter(param);					
-		}
-	}
-    
-    /** 
      * @throws TeiidComponentException 
      * @throws TeiidProcessingException 
      * @see org.teiid.dqp.internal.process.Request#generatePlan()

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -386,12 +386,12 @@
 
         List<Reference> references = ReferenceCollectorVisitor.getReferences(command);
         
-        checkReferences(references);
-        
         this.analysisRecord = new AnalysisRecord(requestMsg.getShowPlan() != ShowPlan.OFF, requestMsg.getShowPlan() == ShowPlan.DEBUG);
                 
         resolveCommand(command);
 
+        checkReferences(references);
+        
         validateAccess(requestMsg.getCommands(), command, CommandType.USER);
         
     	this.userCommand = (Command) command.clone();

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -65,7 +65,6 @@
 import org.teiid.query.sql.symbol.Constant;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.Symbol;
 import org.teiid.query.util.CommandContext;
 
 
@@ -247,7 +246,7 @@
 				if (param.getParameterType() != SPParameter.IN) {
 					continue;
 				}
-				String shortName = Symbol.getShortName(param.getName());        
+				String shortName = param.getParameterSymbol().getShortName();        
 			    if(shortName.equalsIgnoreCase(MultiSourceElement.MULTI_SOURCE_ELEMENT_NAME)) {
 		        	Constant source = (Constant)param.getExpression();
 		    		params.remove();

Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -529,5 +529,7 @@
     	TEIID31109, //invalid scripting language
     	TEIID31110, //invalid script
     	TEIID31111, //invalid teiid script
+    	TEIID31112, //invalid vararg
+    	TEIID31113
 	}
 }

Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -539,7 +539,21 @@
 
 	public static Boolean compare(AbstractCompareCriteria criteria, Object leftValue,
 			Object value) throws AssertionError {
-		int compare = Constant.COMPARATOR.compare(leftValue, value);
+		int compare = 0;
+		//TODO: we follow oracle style array comparison
+		//semantics.  each element is treated as an individual comparison,
+		//so null implies unknown. h2 (and likely other dbms) allow for null
+		//array element equality
+		if (leftValue instanceof ArrayValue) {
+			ArrayValue av = (ArrayValue)leftValue;
+			try {
+				compare = av.compareTo((ArrayValue)value, true);
+			} catch (ArrayValue.NullException e) {
+				return null;
+			}
+		} else {
+			compare = Constant.COMPARATOR.compare(leftValue, value);
+		}
 		// Compare two non-null values using specified operator
 		Boolean result = null;
 		switch(criteria.getOperator()) {
@@ -653,9 +667,6 @@
 		   Object[] result = new Object[exprs.size()];
 		   for (int i = 0; i < exprs.size(); i++) {
 			   result[i] = internalEvaluate(exprs.get(i), tuple);
-			   if (result[i] == null) {
-				   return null; //TODO: this is a hack
-			   }
 		   }
 		   return new ArrayValue(result);
 	   } else {

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -38,6 +38,7 @@
 import org.teiid.metadata.FunctionMethod.Determinism;
 import org.teiid.metadata.FunctionMethod.PushDown;
 import org.teiid.query.QueryPlugin;
+import org.teiid.query.sql.symbol.ArrayValue;
 import org.teiid.query.util.CommandContext;
 
 
@@ -57,6 +58,7 @@
     private String schema; //TODO: remove me - we need to create a proper schema for udf and system functions
     private Object metadataID;
     private boolean hasWrappedArgs;
+    private boolean calledWithVarArgArrayParam; //TODO: could store this on the function and pass to invoke
     
     // This is transient as it would be useless to invoke this method in 
     // a different VM.  This function descriptor can be used to look up 
@@ -154,9 +156,9 @@
     }
 
     @Override
-	public Object clone() {
+	public FunctionDescriptor clone() {
         try {
-            return super.clone();
+            return (FunctionDescriptor) super.clone();
         } catch (CloneNotSupportedException e) {
              throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30381, e);
         }
@@ -221,20 +223,46 @@
         		}
         	}
         	if (method.isVarArgs()) {
-        		int i = invocationMethod.getParameterTypes().length;
-        		Object[] newValues = Arrays.copyOf(values, i);
-        		Object varArgs = null;
-        		if (invocationMethod.getParameterTypes()[i - 1].getComponentType() != Object.class) {
-	        		int varArgCount = values.length - i + 1;
-	        		varArgs = Array.newInstance(invocationMethod.getParameterTypes()[i - 1].getComponentType(), varArgCount);
-	        		for (int j = 0; j < varArgCount; j++) {
-	        			Array.set(varArgs, j, values[i-1+j]);
+        		if (calledWithVarArgArrayParam) {
+        			ArrayValue av = (ArrayValue)values[values.length -1];
+        			if (av != null) {
+        				Object[] vals = av.getValues();
+        				values[values.length - 1] = vals;
+	    				if (hasWrappedArgs && types[types.length - 1] == DataTypeManager.DefaultDataClasses.VARBINARY) {
+	    					vals = Arrays.copyOf(vals, vals.length);
+	        				for (int i = 0; i < vals.length; i++) {
+	        					if (vals[i] != null) {
+	        						vals[i] = ((BinaryType)vals[i]).getBytesDirect();
+	        					}
+	        				}
+	        				values[values.length - 1] = vals;
+	        			}
+	    				Class<?> arrayType = invocationMethod.getParameterTypes()[types.length - 1];
+						if (arrayType.getComponentType() != Object.class
+	    						&& vals.getClass() != arrayType) {
+	    					Object varArgs = Array.newInstance(arrayType.getComponentType(), vals.length);
+	    					for (int i = 0; i < vals.length; i++) {
+			        			Array.set(varArgs, i, vals[i]);
+			        		}
+	        				values[values.length -1] = varArgs;
+	    				}
+        			}
+        		} else {
+	        		int i = invocationMethod.getParameterTypes().length;
+	        		Object[] newValues = Arrays.copyOf(values, i);
+	        		Object varArgs = null;
+	        		if (invocationMethod.getParameterTypes()[i - 1].getComponentType() != Object.class) {
+		        		int varArgCount = values.length - i + 1;
+		        		varArgs = Array.newInstance(invocationMethod.getParameterTypes()[i - 1].getComponentType(), varArgCount);
+		        		for (int j = 0; j < varArgCount; j++) {
+		        			Array.set(varArgs, j, values[i-1+j]);
+		        		}
+	        		} else {
+	        			varArgs = Arrays.copyOfRange(values, i - 1, values.length);
 	        		}
-        		} else {
-        			varArgs = Arrays.copyOfRange(values, i - 1, values.length);
+	        		newValues[i - 1] = varArgs;
+	        		values = newValues;
         		}
-        		newValues[i - 1] = varArgs;
-        		values = newValues;
         	}
             Object result = invocationMethod.invoke(functionTarget, values);
             if (context != null && getDeterministic().ordinal() <= Determinism.USER_DETERMINISTIC.ordinal()) {
@@ -277,4 +305,13 @@
 		}
 		return result;
 	}    
+	
+	public boolean isCalledWithVarArgArrayParam() {
+		return calledWithVarArgArrayParam;
+	}
+	
+	public void setCalledWithVarArgArrayParam(boolean calledWithVarArgArrayParam) {
+		this.calledWithVarArgArrayParam = calledWithVarArgArrayParam;
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionLibrary.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -92,6 +92,7 @@
     public static final String COALESCE = "coalesce"; //$NON-NLS-1$
 
     public static final String SPACE = "space"; //$NON-NLS-1$
+	public static final String ARRAY_GET = "array_get"; //$NON-NLS-1$
 	
     // Function tree for system functions (never reloaded)
     private FunctionTree systemFunctions;
@@ -237,7 +238,6 @@
             //no implicit conversion is possible
             int i = 0;
             for(; i < types.length; i++) {
-            	//treat all varags as the same type
                 final String tmpTypeName = methodTypes.get(Math.min(i, methodTypes.size() - 1)).getType();
                 Class<?> targetType = DataTypeManager.getDataTypeClass(tmpTypeName);
 
@@ -246,7 +246,14 @@
                     currentScore++;
                     continue;
                 }
-                
+                if (sourceType.isArray()) {
+                    if (isVarArgArrayParam(nextMethod, types, i, targetType)) {
+                		//vararg array parameter
+                		continue;
+                	}
+                    //treat the array as object type until proper type handling is added
+                	sourceType = DataTypeManager.DefaultDataClasses.OBJECT;
+                }
 				try {
 					Transform t = getConvertFunctionDescriptor(sourceType, targetType);
 					if (t != null) {
@@ -320,11 +327,21 @@
             if (sourceType == null) {
                 result[i] = findTypedConversionFunction(DataTypeManager.DefaultDataClasses.NULL, targetType);
             } else if (sourceType != targetType){
+            	if (isVarArgArrayParam(method, types, i, targetType)) {
+            		//vararg array parameter
+            		continue;
+            	}
             	result[i] = findTypedConversionFunction(sourceType, targetType);
             }
         }
         return result;
 	}
+
+	public boolean isVarArgArrayParam(FunctionMethod method, Class<?>[] types,
+			int i, Class<?> targetType) {
+		return i == types.length - 1 && method.isVarArgs() && i == method.getInputParameterCount() - 1 
+				&& types[i].getComponentType() == targetType;
+	}
 	
 	private Transform getConvertFunctionDescriptor(Class<?> sourceType, Class<?> targetType) throws InvalidFunctionException {
         //If exact match no conversion necessary
@@ -345,7 +362,8 @@
      * @param targetType The target type class
      * @return A CONVERT function descriptor or null if not possible
      */
-    public FunctionDescriptor findTypedConversionFunction(Class<?> sourceType, Class<?> targetType) {
+    public FunctionDescriptor findTypedConversionFunction(Class<?> sourceType, Class<?> targetType) {
+    	//TODO: should array to string be prohibited?    	
         FunctionDescriptor fd = findFunction(CONVERT, new Class[] {sourceType, DataTypeManager.DefaultDataClasses.STRING});
         if (fd != null) {
             return copyFunctionChangeReturnType(fd, targetType);
@@ -362,7 +380,7 @@
     public FunctionDescriptor copyFunctionChangeReturnType(FunctionDescriptor fd, Class<?> returnType) {
         if(fd != null) {
         	FunctionDescriptor fdImpl = fd;
-            FunctionDescriptor copy = (FunctionDescriptor)fdImpl.clone();
+            FunctionDescriptor copy = fdImpl.clone();
             copy.setReturnType(returnType);
             return copy;
         }

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionMethods.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -59,6 +59,7 @@
 import org.teiid.language.SQLConstants;
 import org.teiid.language.SQLConstants.NonReserved;
 import org.teiid.query.QueryPlugin;
+import org.teiid.query.sql.symbol.ArrayValue;
 import org.teiid.query.util.CommandContext;
 
 /**
@@ -1407,6 +1408,9 @@
 			if (array instanceof java.sql.Array) {
 				return Array.get(((java.sql.Array)array).getArray(index, 1), 0);
 			}
+			if (array instanceof ArrayValue) {
+				return ((ArrayValue)array).getValues()[index - 1];
+			}
 		} catch (ArrayIndexOutOfBoundsException e) {
 			 throw new FunctionExecutionException(QueryPlugin.Event.TEIID30415, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30415, index));
 		}
@@ -1420,6 +1424,9 @@
 		if (array instanceof java.sql.Array) {
 			return Array.getLength(((java.sql.Array)array).getArray());
 		}
+		if (array instanceof ArrayValue) {
+			return ((ArrayValue)array).getValues().length;
+		}
 		 throw new FunctionExecutionException(QueryPlugin.Event.TEIID30416, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30416, array.getClass()));
 	}
 	

Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -22,7 +22,6 @@
 
 package org.teiid.query.function;
 
-import java.lang.reflect.Array;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
@@ -33,6 +32,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 
 import org.teiid.UserDefinedAggregate;
 import org.teiid.core.CoreConstants;
@@ -62,18 +62,18 @@
 public class FunctionTree {
 
     // Constant used to look up the special descriptor key in a node map
-    private static final Integer DESCRIPTOR_KEY = new Integer(-1);
+    private static final Integer DESCRIPTOR_KEY = -1;
 
     private Map<String, Set<String>> categories = new HashMap<String, Set<String>>();
 
-    private Map<String, List<FunctionMethod>> functionsByName = new HashMap<String, List<FunctionMethod>>();
+    private Map<String, List<FunctionMethod>> functionsByName = new TreeMap<String, List<FunctionMethod>>(String.CASE_INSENSITIVE_ORDER);
     
     private Set<FunctionMethod> allFunctions = new HashSet<FunctionMethod>();
 
 	/**
 	 * Function lookup and invocation use: Function name (uppercase) to Map (recursive tree)
 	 */
-    private Map treeRoot = new HashMap();
+    private Map<String, Map<Object, Object>> treeRoot = new TreeMap<String, Map<Object, Object>>(String.CASE_INSENSITIVE_ORDER);
     private boolean validateClass;
     
     /**
@@ -176,7 +176,7 @@
      */
     List<FunctionMethod> findFunctionMethods(String name, int args) {
         final List<FunctionMethod> allMatches = new ArrayList<FunctionMethod>();
-        List<FunctionMethod> methods = functionsByName.get(name.toUpperCase());
+        List<FunctionMethod> methods = functionsByName.get(name);
         if(methods == null || methods.size() == 0) {
             return allMatches;
         }
@@ -248,17 +248,23 @@
 	        }
 	        knownMethods.add(method);
 
-        	Map node = treeRoot;
-	        Object[] path = buildPath(methodName, types);
-	        for(int pathIndex = 0; pathIndex < path.length; pathIndex++) {
-	            Object pathPart = path[pathIndex];
-	            Map children = (Map) node.get(pathPart);
+        	Map<Object, Object> node = treeRoot.get(methodName);
+        	if (node == null) {
+        		node = new HashMap<Object, Object>(2);
+        		treeRoot.put(methodName, node);
+        	}
+	        for(int pathIndex = 0; pathIndex < types.length; pathIndex++) {
+	            Class<?> pathPart = types[pathIndex];
+	            Map<Object, Object> children = (Map<Object, Object>) node.get(pathPart);
 	            if(children == null) {
-	                children = new HashMap();
+	                children = new HashMap<Object, Object>(2);
 	                node.put(pathPart, children);
 	            }
-	            if (method.isVarArgs() && pathIndex == path.length - 1) {
+	            if (method.isVarArgs() && pathIndex == types.length - 1) {
 	        		node.put(DESCRIPTOR_KEY, descriptor);
+	                Map<Object, Object> alternate = new HashMap<Object, Object>(2);
+	                alternate.put(DESCRIPTOR_KEY, descriptor);
+	                node.put(DataTypeManager.getArrayType(pathPart), alternate);
 	            }
 	            node = children;
 	        }
@@ -300,7 +306,7 @@
 	        }
         }
         if (method.isVarArgs()) {
-        	inputTypes.set(inputTypes.size() - 1, Array.newInstance(inputTypes.get(inputTypes.size() - 1), 0).getClass());
+        	inputTypes.set(inputTypes.size() - 1, DataTypeManager.getArrayType(inputTypes.get(inputTypes.size() - 1)));
         }
 
         Method invocationMethod = null;
@@ -368,16 +374,23 @@
      * @return Descriptor which can be used to invoke the function
      */
     FunctionDescriptor getFunction(String name, Class<?>[] argTypes) {
-        // Build search path
-        Object[] path = buildPath(name, argTypes);
-
         // Walk path in tree
-        Map node = treeRoot;
-        for(int i=0; i<path.length; i++) {
-        	node = (Map)node.get(path[i]);
-        	if (node == null) {
-        		return null;
+        Map<Object, Object> node = treeRoot.get(name);
+        if (node == null) {
+        	return null;
+        }
+        for(int i=0; i<argTypes.length; i++) {
+        	Map<Object, Object> nextNode = (Map<Object, Object>)node.get(argTypes[i]);
+        	if (nextNode == null) {
+        		if (argTypes[i].isArray()) {
+        			//array types are not yet considered in the function typing logic
+        			nextNode = (Map<Object, Object>) node.get(DataTypeManager.DefaultDataClasses.OBJECT);
+        		}
+        		if (nextNode == null) {
+        			return null;
+        		}
             }
+        	node = nextNode;
         }
 
         // Look for key at the end
@@ -389,17 +402,4 @@
         return null;
     }
 
-    /**
-     * Build the path in the function storage tree.  The path for a function consists
-     * of it's name (uppercased) and each of the argument classes.
-     * @param name Name of function
-     * @param argTypes Types of each arguments
-     * @return Path in function storage tree
-     */
-    private Object[] buildPath(String name, Class<?>[] argTypes) {
-        Object[] path = new Object[argTypes.length + 1];
-        path[0] = name.toUpperCase();
-        System.arraycopy(argTypes, 0, path, 1, argTypes.length);
-        return path;
-    }
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -33,9 +33,11 @@
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.eval.TeiidScriptEngine;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
+import org.teiid.query.sql.lang.ObjectTable;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.GroupSymbol;
 
@@ -524,8 +526,26 @@
 	}
 	
 	@Override
-	public ScriptEngine getScriptEngine(String langauge) throws TeiidProcessingException {
+	public ScriptEngine getScriptEngine(String language) throws TeiidProcessingException {
+		if (language == null || ObjectTable.DEFAULT_LANGUAGE.equals(language)) {
+			return new TeiidScriptEngine();
+		}
+		return getScriptEngineDirect(language);
+	}
+	
+	/**
+	 * 
+	 * @param language
+	 * @return
+	 * @throws TeiidProcessingException
+	 */
+	public ScriptEngine getScriptEngineDirect(String language) throws TeiidProcessingException {
 		return null;
 	}
 	
+	@Override
+	public boolean isVariadic(Object metadataID) {
+		return false;
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -402,4 +402,9 @@
 		return actualMetadata.getScriptEngine(langauge);
 	}
 	
+	@Override
+	public boolean isVariadic(Object metadataID) {
+		return actualMetadata.isVariadic(metadataID);
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/DDLStringVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -586,9 +586,22 @@
 
 	private void visit(ProcedureParameter param) {
 		Type type = param.getType();
-		String typeStr = type.name().toUpperCase();
-		if (type == Type.ReturnValue) {
-			typeStr = Type.Out.name().toUpperCase();
+		String typeStr = null;
+		switch (type) {
+		case InOut:
+			typeStr = INOUT;
+			break;
+		case ReturnValue:
+		case Out:
+			typeStr = OUT;
+			break;
+		case In:
+			if (param.isVarArg()) {
+				typeStr = NonReserved.VARIADIC;
+			} else {
+				typeStr = IN;
+			}
+			break;
 		}
 		buffer.append(typeStr).append(SPACE);
 		appendColumn(buffer, param, true, true);
@@ -666,6 +679,9 @@
 	}
 
 	private void visit(FunctionParameter param) {
+		if (param.isVarArg()) {
+			buffer.append(NonReserved.VARIADIC).append(SPACE);
+		}
 		buffer.append(SQLStringVisitor.escapeSinglePart(param.getName())).append(SPACE).append(param.getType());
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -119,6 +119,9 @@
 					boolean hasReturn = false;
 					names.clear();
 					for (ProcedureParameter param : p.getParameters()) {
+						if (param.isVarArg() && param != p.getParameters().get(p.getParameters().size() -1)) {
+							metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31112, p.getFullName()));
+						}
 						if (param.getType() == ProcedureParameter.Type.ReturnValue) {
 							if (hasReturn) {
 								metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31107, p.getFullName()));
@@ -135,6 +138,11 @@
 				}
 				
 				for (FunctionMethod func:schema.getFunctions().values()) {
+					for (FunctionParameter param : func.getInputParameters()) {
+						if (param.isVarArg() && param != func.getInputParameters().get(func.getInputParameterCount() -1)) {
+							metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31112, func.getFullName()));
+						}
+					}
 					if (func.getPushdown().equals(FunctionMethod.PushDown.MUST_PUSHDOWN) && !model.isSource()) {
 						metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31078, func.getName(), model.getName()));
 					}

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -657,4 +657,6 @@
 	QueryMetadataInterface getSessionMetadata();
 
 	Set<String> getImportedModels();
+
+	boolean isVariadic(Object metadataID);
 }

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -47,20 +47,11 @@
 import org.teiid.core.util.LRUCache;
 import org.teiid.core.util.ObjectConverterUtil;
 import org.teiid.core.util.StringUtil;
-import org.teiid.metadata.AbstractMetadataRecord;
-import org.teiid.metadata.Column;
-import org.teiid.metadata.ColumnSet;
-import org.teiid.metadata.ForeignKey;
-import org.teiid.metadata.KeyRecord;
-import org.teiid.metadata.Procedure;
-import org.teiid.metadata.ProcedureParameter;
-import org.teiid.metadata.Schema;
-import org.teiid.metadata.Table;
+import org.teiid.metadata.*;
 import org.teiid.metadata.BaseColumn.NullType;
 import org.teiid.metadata.Column.SearchType;
 import org.teiid.metadata.ProcedureParameter.Type;
 import org.teiid.query.QueryPlugin;
-import org.teiid.query.eval.TeiidScriptEngine;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.function.FunctionTree;
 import org.teiid.query.mapping.relational.QueryNode;
@@ -363,6 +354,10 @@
                     SPParameter spParam = new SPParameter(paramRecord.getPosition(), direction, paramRecord.getFullName());
                     spParam.setMetadataID(paramRecord);
                     spParam.setClassType(DataTypeManager.getDataTypeClass(runtimeType));
+                    if (paramRecord.isVarArg()) {
+                    	spParam.setVarArg(true);
+                    	spParam.setClassType(DataTypeManager.getArrayType(spParam.getClassType()));
+                    }
                     procInfo.addParameter(spParam);
                 }
 
@@ -1116,13 +1111,11 @@
 	}
 	
 	@Override
-	public ScriptEngine getScriptEngine(String language) throws TeiidProcessingException {
+	public ScriptEngine getScriptEngineDirect(String language)
+			throws TeiidProcessingException {
 		if (this.scriptEngineManager == null) {
 			this.scriptEngineManager = new ScriptEngineManager();
 		}
-		if (language == null || ObjectTable.DEFAULT_LANGUAGE.equals(language)) {
-			return new TeiidScriptEngine();
-		}
 		ScriptEngine engine = null;
 		if (allowedLanguages == null || allowedLanguages.contains(language)) {
 			/*
@@ -1155,4 +1148,15 @@
 		return engine;
 	}
 	
+	@Override
+	public boolean isVariadic(Object metadataID) {
+		if (metadataID instanceof ProcedureParameter) {
+			return ((ProcedureParameter)metadataID).isVarArg();
+		}
+		if (metadataID instanceof FunctionParameter) {
+			return ((FunctionParameter)metadataID).isVarArg();
+		}
+		return false;
+	}
+	
 }
\ No newline at end of file

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -33,8 +33,8 @@
 import org.teiid.core.TeiidRuntimeException;
 import org.teiid.core.id.IDGenerator;
 import org.teiid.dqp.internal.process.PreparedPlan;
+import org.teiid.metadata.Procedure;
 import org.teiid.metadata.FunctionMethod.Determinism;
-import org.teiid.metadata.Procedure;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.analysis.AnalysisRecord;
 import org.teiid.query.metadata.QueryMetadataInterface;

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	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -71,6 +71,7 @@
 import org.teiid.query.sql.ProcedureReservedWords;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.Criteria;
+import org.teiid.query.sql.symbol.ArrayValue;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.util.VariableContext;
@@ -245,9 +246,20 @@
 	private void checkNotNull(ElementSymbol param, Object value)
 			throws TeiidComponentException, QueryMetadataException,
 			QueryValidatorException {
-		if (value == null && !metadata.elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+		if (metadata.elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+			return;
+		}
+		if (value == null) {
 		     throw new QueryValidatorException(QueryPlugin.Event.TEIID30164, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30164, param));
 		}
+		if (value instanceof ArrayValue && metadata.isVariadic(param.getMetadataID())) {
+			ArrayValue av = (ArrayValue)value;
+			for (Object o : av.getValues()) {
+				if (o == null) {
+				     throw new QueryValidatorException(QueryPlugin.Event.TEIID30164, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30164, param));
+				}
+			}
+		}
 	}
 
 	protected void setParameterValue(ElementSymbol param,

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentValueSource.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -121,7 +121,7 @@
         	int index = 0;
         	Class<?> type = null;
         	if (valueExpression instanceof Array) {
-        		type = ((Array)valueExpression).getBaseType();
+        		type = ((Array)valueExpression).getComponentType();
         	} else { 	
         		if (valueExpression != null) {
 	        		index = schema.indexOf(valueExpression);

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	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -23,6 +23,7 @@
 package org.teiid.query.resolver.command;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -51,8 +52,10 @@
 import org.teiid.query.sql.lang.SPParameter;
 import org.teiid.query.sql.lang.StoredProcedure;
 import org.teiid.query.sql.lang.SubqueryContainer;
+import org.teiid.query.sql.symbol.Array;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.Reference;
 import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
 
 
@@ -93,7 +96,7 @@
 
         // Get old parameters as they may have expressions set on them - collect
         // those expressions to copy later into the resolved parameters
-        List<SPParameter> oldParams = storedProcedureCommand.getParameters();
+        Collection<SPParameter> oldParams = storedProcedureCommand.getParameters();
 
         boolean namedParameters = storedProcedureCommand.displayNamedParameters();
         
@@ -110,7 +113,7 @@
         // the procedure was parsed with named or unnamed parameters, the keys
         // for this map will either be the String names of the parameters or
         // the Integer indices, as entered in the user query
-        Map<Integer, Expression> postionalExpressions = new HashMap<Integer, Expression>();
+        Map<Integer, Expression> positionalExpressions = new HashMap<Integer, Expression>();
         Map<String, Expression> namedExpressions = new TreeMap<String, Expression>(String.CASE_INSENSITIVE_ORDER);
         int adjustIndex = 0;
         for (SPParameter param : oldParams) {
@@ -121,16 +124,16 @@
             	continue;
             }
             if (namedParameters && param.getParameterType() != SPParameter.RETURN_VALUE) {
-                if (namedExpressions.put(param.getName(), param.getExpression()) != null) {
-                	 throw new QueryResolverException(QueryPlugin.Event.TEIID30138, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30138, param.getName().toUpperCase()));
+                if (namedExpressions.put(param.getParameterSymbol().getShortName(), param.getExpression()) != null) {
+                	 throw new QueryResolverException(QueryPlugin.Event.TEIID30138, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30138, param.getName()));
                 }
             } else {
-                postionalExpressions.put(param.getIndex() + adjustIndex, param.getExpression());
+                positionalExpressions.put(param.getIndex() + adjustIndex, param.getExpression());
             }
         }
 
         storedProcedureCommand.clearParameters();
-        int origInputs = postionalExpressions.size() + namedExpressions.size();
+        int origInputs = positionalExpressions.size() + namedExpressions.size();
         /*
          * Take the values set from the stored procedure implementation, and match up with the
          * types of parameter it is from the metadata and then reset the newly joined parameters
@@ -144,10 +147,12 @@
         int outParams = 0;
         boolean hasReturnValue = false;
         boolean optional = false;
-        for (SPParameter metadataParameter : metadataParams) {
+        boolean varargs = false;
+        for (int i = 0; i < metadataParams.size(); i++) {
+        	SPParameter metadataParameter = metadataParams.get(i);
             if( (metadataParameter.getParameterType()==ParameterInfo.IN) ||
                 (metadataParameter.getParameterType()==ParameterInfo.INOUT)){
-            	if (ResolverUtil.hasDefault(metadataParameter.getMetadataID(), metadata)) {
+            	if (ResolverUtil.hasDefault(metadataParameter.getMetadataID(), metadata) || metadataParameter.isVarArg()) {
                 	optional = true;
                 	optionalParams++;
             	} else {
@@ -158,6 +163,9 @@
                 		optionalParams = 0;
                 	}
             	}
+            	if (metadataParameter.isVarArg()) {
+            		varargs = true;
+            	}
             } else if (metadataParameter.getParameterType() == ParameterInfo.OUT) {
             	outParams++;
             	/*
@@ -178,8 +186,8 @@
         	 throw new QueryResolverException(QueryPlugin.Event.TEIID30139, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30139, storedProcedureCommand.getGroup()));
         }
 
-        if(!namedParameters && (inputParams > postionalExpressions.size())) {
-             throw new QueryResolverException(QueryPlugin.Event.TEIID30140, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30140, inputParams, origInputs, storedProcedureCommand.getGroup()));
+        if(!namedParameters && (inputParams > positionalExpressions.size()) ) {
+             throw new QueryResolverException(QueryPlugin.Event.TEIID30140, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30140, inputParams, inputParams + optionalParams + (varargs?"+":""), origInputs, storedProcedureCommand.getGroup())); //$NON-NLS-1$ //$NON-NLS-2$
         }
         
         // Walk through the resolved parameters and set the expressions from the
@@ -189,7 +197,7 @@
         if (storedProcedureCommand.isCalledWithReturn() && hasReturnValue) {
 	        for (SPParameter param : clonedMetadataParams) {
 	        	if (param.getParameterType() == SPParameter.RETURN_VALUE) {
-	        		Expression expr = postionalExpressions.remove(exprIndex++);
+	        		Expression expr = positionalExpressions.remove(exprIndex++);
 	                param.setExpression(expr);
 	                break;
 	        	}
@@ -210,14 +218,45 @@
                 } 
                 param.setExpression(expr);                    
             } else {
-            	if(param.getParameterType() == SPParameter.OUT) {
+                Expression expr = positionalExpressions.remove(exprIndex++);
+                if(param.getParameterType() == SPParameter.OUT) {
+                	if (expr != null) {
+	                	boolean isRef = expr instanceof Reference;
+						if (!isRef || exprIndex <= inputParams + 1) {
+							//for backwards compatibility, this should be treated instead as an input
+	                		exprIndex--;
+	                		positionalExpressions.put(exprIndex, expr);
+	                	} else if (isRef) {
+	                		//mimics the hack that was in PreparedStatementRequest.
+	                		Reference ref = (Reference)expr;
+	                		ref.setOptional(true); //may be an out
+	                		/*
+	                		 * Note that there is a corner case here with out parameters intermixed with optional parameters
+	                		 * there's not a good way around this.
+	                		 */
+	                	}
+                	}
             		continue;
             	}
-                Expression expr = postionalExpressions.remove(exprIndex++);
                 if (expr == null) {
-                	expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
+                	if (!param.isVarArg()) {
+                		expr = ResolverUtil.getDefault(param.getParameterSymbol(), metadata);
+                	}
                 	param.setUsingDefault(true);
                 } 
+                if (param.isVarArg()) {
+                	List<Expression> exprs = new ArrayList<Expression>(positionalExpressions.size() + 1);
+                	if (expr != null) {
+                		exprs.add(expr);
+                	}
+                	exprs.addAll(positionalExpressions.values());
+                	positionalExpressions.clear();
+                	Array array = new Array(exprs);
+                	array.setImplicit(true);
+                	array.setType(param.getClassType());
+                    param.setExpression(array);
+                	break;
+                }
                 param.setExpression(expr);
             }
         }
@@ -226,8 +265,8 @@
         if (!namedExpressions.isEmpty()) {
     		 throw new QueryResolverException(QueryPlugin.Event.TEIID30141, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30141, namedExpressions.keySet(), expected));
         }
-        if (!postionalExpressions.isEmpty()) {
-        	 throw new QueryResolverException(QueryPlugin.Event.TEIID30140, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30140, inputParams, origInputs, storedProcedureCommand.getGroup().toString()));
+        if (!positionalExpressions.isEmpty()) {
+        	 throw new QueryResolverException(QueryPlugin.Event.TEIID31113, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31113, positionalExpressions.size(), origInputs, storedProcedureCommand.getGroup().toString()));
         }
         
         // Create temporary metadata that defines a group based on either the stored proc
@@ -267,7 +306,14 @@
                 
                 QueryResolver.resolveCommand(container.getCommand(), metadata.getMetadata());
             }
-            ResolverVisitor.resolveLanguageObject(expr, null, externalGroups, metadata);
+            try {
+            	ResolverVisitor.resolveLanguageObject(expr, null, externalGroups, metadata);
+            } catch (QueryResolverException e) {
+            	if (!checkForArray(param, expr)) {
+            		throw e;
+            	}
+            	continue;
+            }
             Class<?> paramType = param.getClassType();
 
             ResolverUtil.setDesiredType(expr, paramType, storedProcedureCommand);
@@ -290,12 +336,32 @@
                 try {
                     result = ResolverUtil.convertExpression(expr, tgtType, metadata);
                 } catch (QueryResolverException e) {
-                     throw new QueryResolverException(QueryPlugin.Event.TEIID30145, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30145, new Object[] { srcType, tgtType}));
+                     throw new QueryResolverException(QueryPlugin.Event.TEIID30145, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30145, new Object[] { param.getParameterSymbol(), srcType, tgtType}));
                 }                                                       
                 param.setExpression(result);
             }
         }
     }
+
+    /**
+     * The param resolving always constructs an array, which is 
+     * not appropriate if passing an array directly
+     * @return 
+     */
+	private boolean checkForArray(SPParameter param, Expression expr) {
+		if (!param.isVarArg() || !(expr instanceof Array)) {
+			return false;
+		}
+		Array array = (Array)expr;
+		if (array.getExpressions().size() == 1) {
+			Expression first = array.getExpressions().get(0);
+			if (first.getType() != null && first.getType() == array.getType()) {
+				param.setExpression(first);
+				return true;
+			} 
+		}
+		return false;
+	}
     
     protected void resolveGroup(TempMetadataAdapter metadata,
                                 ProcedureContainer procCommand) throws TeiidComponentException,

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -320,6 +320,30 @@
             handleException(e);
         }
     }
+    
+    @Override
+    public void visit(Array array) {
+    	try {
+	    	if (array.getComponentType() != null) {
+	    		String type = DataTypeManager.getDataTypeName(array.getComponentType());
+	    		for (int i = 0; i < array.getExpressions().size(); i++) {
+	    			Expression expr = array.getExpressions().get(i);
+	    			setDesiredType(expr, array.getComponentType(), array);
+	    			array.getExpressions().set(i, ResolverUtil.convertExpression(expr, type, metadata));
+	    		}
+	    	} else {
+	    		String[] types = new String[array.getExpressions().size()];
+	    		for (int i = 0; i < array.getExpressions().size(); i++) {
+	    			Expression expr = array.getExpressions().get(i);
+	    			types[i] = DataTypeManager.getDataTypeName(expr.getType());
+	    		}
+	    		String commonType = ResolverUtil.getCommonType(types);
+	    		array.setComponentType(DataTypeManager.getDataTypeClass(commonType));
+	    	}
+    	} catch (QueryResolverException e) {
+    		handleException(e);
+    	}
+    }
 
     public void visit(CaseExpression obj) {
         try {
@@ -492,6 +516,13 @@
 	         throw new QueryResolverException(QueryPlugin.Event.TEIID30070, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30070, function));
 	    }
 	    
+	    if (fd.getMethod().isVarArgs() 
+	    		&& fd.getTypes().length == types.length 
+	    		&& library.isVarArgArrayParam(fd.getMethod(), types, types.length - 1, fd.getTypes()[types.length - 1])) {
+	    	fd = fd.clone();
+	    	fd.setCalledWithVarArgArrayParam(true);
+	    }
+	    
 	    if(fd.getName().equalsIgnoreCase(FunctionLibrary.CONVERT) || fd.getName().equalsIgnoreCase(FunctionLibrary.CAST)) {
 	        String dataType = (String) ((Constant)args[1]).getValue();
 	        Class<?> dataTypeClass = DataTypeManager.getDataTypeClass(dataType);
@@ -508,7 +539,10 @@
 	    } else if(fd.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
 			ResolverUtil.ResolvedLookup lookup = ResolverUtil.resolveLookup(function, metadata);
 			fd = library.copyFunctionChangeReturnType(fd, lookup.getReturnElement().getType());
-	    } 
+	    } else if (FunctionLibrary.ARRAY_GET.equalsIgnoreCase(fd.getName()) && args[0].getType().isArray()) {
+	    	//hack to use typed array values
+			fd = library.copyFunctionChangeReturnType(fd, args[0].getType().getComponentType());
+	    }
 	
 	    function.setFunctionDescriptor(fd);
 	    function.setType(fd.getReturnType());

Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/SPParameter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/SPParameter.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/SPParameter.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -22,7 +22,6 @@
 
 package org.teiid.query.sql.lang;
 
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -42,7 +41,7 @@
 * The connector will utilize this class to set the appropriate values at the
 * datasource layer.
 */
-public class SPParameter implements Serializable, Cloneable {
+public class SPParameter implements Cloneable {
 
     /** Constant identifying an IN parameter */
     public static final int IN = ParameterInfo.IN;
@@ -60,15 +59,14 @@
     public static final int RESULT_SET = ParameterInfo.RESULT_SET;
 
     // Basic state
-    private String name;        // Param name, qualified by full procedure name
     private int parameterType = ParameterInfo.IN;
-    private Class classType;
     private Expression expression;
     private int index;
-    private List resultSetColumns;      //contains List of columns if it is result set
-    private List resultSetIDs;          // contains List of metadataIDs for each column in the result set
-    private Object metadataID;          // metadataID for the actual metadata ID
+    private List<ElementSymbol> resultSetColumns;      //contains List of columns if it is result set
+    private List<Object> resultSetIDs;          // contains List of metadataIDs for each column in the result set
     private boolean usingDefault;
+	private boolean varArg;
+	private ElementSymbol parameterSymbol;
 
     /**
      * Constructor used when constructing a parameter during execution.  In this case we
@@ -80,6 +78,7 @@
     public SPParameter(int index, Expression expression){
         setIndex(index);
         setExpression(expression);
+        this.parameterSymbol = new ElementSymbol(""); //$NON-NLS-1$
     }
 
     /**
@@ -94,15 +93,19 @@
     public SPParameter(int index, int parameterType, String name) {
         setIndex(index);
         setParameterType(parameterType);
-        setName(name);
+        this.parameterSymbol = new ElementSymbol(name);
     }
+    
+    private SPParameter() {
+    	
+    }
 
     /**
      * Get full parameter name,.  If unknown, null is returned.
      * @return Parameter name
      */
     public String getName() {
-        return this.name;
+        return this.parameterSymbol.getName();
     }
 
     /**
@@ -110,7 +113,10 @@
      * @param name Parameter name
      */
     public void setName(String name) {
-        this.name = name;
+    	ElementSymbol es = new ElementSymbol(name);
+    	es.setMetadataID(parameterSymbol.getMetadataID());
+    	es.setType(parameterSymbol.getType());
+        this.parameterSymbol = es;
     }
 
     /**
@@ -148,16 +154,16 @@
      * @param classType See {@link org.teiid.core.types.DataTypeManager.DefaultDataClasses}
      * for types
      */
-    public void setClassType(Class classType){
-        this.classType = classType;
+    public void setClassType(Class<?> classType){
+        this.parameterSymbol.setType(classType);
     }
 
     /**
      * Get class type - MetaMatrix runtime types.
      * @return MetaMatrix runtime type description
      */
-    public Class getClassType(){
-        return this.classType;
+    public Class<?> getClassType(){
+        return this.parameterSymbol.getType();
     }
 
     /**
@@ -195,16 +201,16 @@
     /**
      * Add a result set column if this parameter is a return
      * result set.
-     * @param name Name of column
+     * @param colName Name of column
      * @param type Type of column
      */
-    public void addResultSetColumn(String name, Class type, Object id) {
+    public void addResultSetColumn(String colName, Class<?> type, Object id) {
         if(resultSetColumns == null){
-            resultSetColumns = new ArrayList();
-            resultSetIDs = new ArrayList();
+            resultSetColumns = new ArrayList<ElementSymbol>();
+            resultSetIDs = new ArrayList<Object>();
         }
 
-        ElementSymbol rsColumn = new ElementSymbol(name);
+        ElementSymbol rsColumn = new ElementSymbol(colName);
         rsColumn.setType(type);
         rsColumn.setMetadataID(id);
 
@@ -217,9 +223,9 @@
      * Get the result set columns.  If none exist, return empty list.
      * @return List of ElementSymbol representing result set columns
      */
-    public List getResultSetColumns(){
+    public List<ElementSymbol> getResultSetColumns(){
         if(resultSetColumns == null){
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
         return resultSetColumns;
     }
@@ -228,9 +234,9 @@
      * Get the result set metadata IDs.  If none exist, return empty list.
      * @return List of Object representing result set metadata IDs
      */
-    public List getResultSetIDs() {
+    public List<Object> getResultSetIDs() {
         if(resultSetIDs == null) { 
-            return Collections.EMPTY_LIST;
+            return Collections.emptyList();
         }
         return this.resultSetIDs;
     }
@@ -249,7 +255,7 @@
         //position is 1 based
         position--;
         if(position >= 0 && position < resultSetColumns.size()) {
-            return (ElementSymbol) resultSetColumns.get(position);
+            return resultSetColumns.get(position);
         }
         throw new IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0010", new Integer(position + 1))); //$NON-NLS-1$
     }
@@ -259,7 +265,7 @@
      * @return Actual metadata ID for this parameter
      */
     public Object getMetadataID() {
-        return this.metadataID;
+        return this.parameterSymbol.getMetadataID();
     }
 
     /**
@@ -267,7 +273,7 @@
      * @param metadataID Actual metadataID
      */
     public void setMetadataID(Object metadataID) {
-        this.metadataID = metadataID;
+        this.parameterSymbol.setMetadataID(metadataID);
     }
 
     /**
@@ -285,10 +291,7 @@
      * @return Element symbol representing the parameter
      */
     public ElementSymbol getParameterSymbol() {
-        ElementSymbol symbol = new ElementSymbol(this.name);
-        symbol.setType(this.classType);
-        symbol.setMetadataID(this.metadataID);
-		return symbol;
+		return parameterSymbol;
     }
 
     /**
@@ -325,23 +328,23 @@
      * @see java.lang.Object#clone()
      */
     public Object clone() {
-        SPParameter copy = new SPParameter(this.index, this.parameterType, this.name);
-        copy.setClassType(this.classType);
+        SPParameter copy = new SPParameter();
+        copy.index = this.index;
+        copy.parameterType = this.parameterType;
+        copy.parameterSymbol = this.parameterSymbol.clone();
         if(this.expression != null) {
             copy.setExpression((Expression)this.expression.clone());
         }
         if(this.resultSetColumns != null) {
-            Iterator iter = this.resultSetColumns.iterator();
-            Iterator idIter = this.resultSetIDs.iterator();
+            Iterator<ElementSymbol> iter = this.resultSetColumns.iterator();
+            Iterator<Object> idIter = this.resultSetIDs.iterator();
             while(iter.hasNext()) {
-                ElementSymbol column = (ElementSymbol) iter.next();
+                ElementSymbol column = iter.next();
                 copy.addResultSetColumn(column.getName(), column.getType(), idIter.next());
             }
         }
-
-        copy.setMetadataID(this.getMetadataID());
         copy.setUsingDefault(this.usingDefault);
-
+        copy.varArg = this.varArg;
         return copy;
     }
 
@@ -363,4 +366,12 @@
 		this.usingDefault = usingDefault;
 	}
 
+	public void setVarArg(boolean varArg) {
+		this.varArg = varArg;
+	}
+	
+	public boolean isVarArg() {
+		return varArg;
+	}
+
 }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -23,6 +23,7 @@
 package org.teiid.query.sql.lang;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -146,7 +147,7 @@
             throw new IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0011")); //$NON-NLS-1$
         }
 
-        Integer key = new Integer(parameter.getIndex());
+        Integer key = parameter.getIndex();
         if(parameter.getParameterType() == ParameterInfo.RESULT_SET){
         	resultSetParameterKey = key;
         }
@@ -158,9 +159,8 @@
     * Returns a List of SPParameter objects for this stored procedure
     *
     */
-    public List<SPParameter> getParameters(){
-        List<SPParameter> listOfParameters = new ArrayList<SPParameter>(mapOfParameters.values());
-        return listOfParameters;
+    public Collection<SPParameter> getParameters(){
+        return mapOfParameters.values();
     }
     
     public Map<Integer, SPParameter> getMapOfParameters() {
@@ -168,7 +168,7 @@
 	}
 
     public SPParameter getParameter(int index){
-        return mapOfParameters.get(new Integer(index));
+        return mapOfParameters.get(index);
     }
 
     public int getNumberOfColumns(){
@@ -214,9 +214,9 @@
         copy.setGroup(getGroup().clone());
         copy.callableName = callableName;
         copy.calledWithReturn = calledWithReturn;
-        List<SPParameter> params = getParameters();
-        for(int i=0; i<params.size(); i++) {
-            copy.setParameter((SPParameter)params.get(i).clone());
+        Collection<SPParameter> params = getParameters();
+        for (SPParameter spParameter : params) {
+            copy.setParameter((SPParameter)spParameter.clone());
         }
         copy.resultSetParameterKey = resultSetParameterKey;
         this.copyMetadataState(copy);
@@ -350,23 +350,8 @@
         this.displayNamedParameters = displayNamedParameters;
     }
 
-    /** 
-     * Return the full parameter name for
-     * the indicated parameter of this stored procedure.
-     * @param param
-     * @return
-     * @since 4.3
-     */
-    public String getParamFullName(SPParameter param) {
-        String paramName = param.getName();
-        if(paramName.lastIndexOf(".") < 0) { //$NON-NLS-1$
-            paramName = this.getProcedureName() + "." + paramName; //$NON-NLS-1$
-        }
-        return paramName;
-    }
-    
     public List<SPParameter> getInputParameters() {
-    	List<SPParameter> parameters = getParameters();
+    	List<SPParameter> parameters = new ArrayList<SPParameter>(getParameters());
     	Iterator<SPParameter> params = parameters.iterator();
     	while (params.hasNext()) {
     		SPParameter param = params.next();

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/Array.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -25,6 +25,7 @@
 import java.util.List;
 
 import org.teiid.core.types.DataTypeManager;
+import org.teiid.core.util.Assertion;
 import org.teiid.core.util.EquivalenceUtil;
 import org.teiid.core.util.HashCodeUtil;
 import org.teiid.query.sql.LanguageObject;
@@ -33,18 +34,30 @@
 
 public class Array implements Expression {
 
-	private Class<?> baseType;
+	private Class<?> type;
 	private List<Expression> expressions;
+	private boolean implicit;
 	
+	public Array(List<Expression> expressions) {
+		this.expressions = expressions;
+	}
+	
 	public Array(Class<?> baseType, List<Expression> expresssions) {
-		this.baseType = baseType;
+		setComponentType(baseType);
 		this.expressions = expresssions;
 	}
 	
 	@Override
 	public Class<?> getType() {
-		return DataTypeManager.DefaultDataClasses.OBJECT;
+		return type;
 	}
+	
+	public void setType(Class<?> type) {
+		if (type != null) {
+			Assertion.assertTrue(type.isArray());
+		}
+		this.type = type;
+	}
 
 	@Override
 	public void acceptVisitor(LanguageVisitor visitor) {
@@ -53,15 +66,24 @@
 	
 	@Override
 	public Array clone() {
-		return new Array(baseType, LanguageObject.Util.deepClone(getExpressions(), Expression.class));
+		Array clone = new Array(type, LanguageObject.Util.deepClone(getExpressions(), Expression.class));
+		clone.implicit = implicit;
+		return clone;
 	}
 	
-	public Class<?> getBaseType() {
-		return baseType;
+	public Class<?> getComponentType() {
+		if (this.type != null) {
+			return this.type.getComponentType();
+		}
+		return null;
 	}
 	
-	public void setBaseType(Class<?> baseType) {
-		this.baseType = baseType;
+	public void setComponentType(Class<?> baseType) {
+		if (baseType != null) {
+			this.type = DataTypeManager.getArrayType(baseType);
+		} else {
+			this.type = null;
+		}
 	}
 	
 	public List<Expression> getExpressions() {
@@ -82,12 +104,24 @@
 	    	return false;
 	    }
 		Array other = (Array) obj;
-		return EquivalenceUtil.areEqual(baseType, other.baseType) && EquivalenceUtil.areEqual(expressions, other.expressions);
+		return EquivalenceUtil.areEqual(type, other.type) && EquivalenceUtil.areEqual(expressions, other.expressions);
 	}
 	
 	@Override
 	public String toString() {
 		return SQLStringVisitor.getSQLString(this);
 	}
+
+	public void setImplicit(boolean implicit) {
+		this.implicit = implicit;
+	}
 	
+	/**
+	 * If the array has been implicitly constructed, such as with vararg parameters
+	 * @return
+	 */
+	public boolean isImplicit() {
+		return implicit;
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ArrayValue.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -22,17 +22,29 @@
 
 package org.teiid.query.sql.symbol;
 
+import java.io.Serializable;
 import java.util.Arrays;
 
-public class ArrayValue implements Comparable<ArrayValue> {
+import org.teiid.query.sql.visitor.SQLStringVisitor;
+
+public class ArrayValue implements Comparable<ArrayValue>, Serializable {
+	private static final long serialVersionUID = 517794153664734815L;
 	private Object[] values;
 	
+	@SuppressWarnings("serial")
+	public final static class NullException extends RuntimeException {};
+	private final static NullException ex = new NullException();
+	
 	public ArrayValue(Object[] values) {
 		this.values = values;
 	}
 
 	@Override
 	public int compareTo(ArrayValue o) {
+		return compareTo(o, false);
+	}
+		
+	public int compareTo(ArrayValue o, boolean noNulls) {
 		int len1 = values.length;
 		int len2 = o.values.length;
 	    int lim = Math.min(len1, len2);
@@ -40,11 +52,17 @@
 	    	Object object1 = values[k];
 			Object object2 = o.values[k];
 			if (object1 == null) {
+				if (noNulls) {
+					throw ex;
+				}
 	    		if (object2 != null) {
 	    			return -1;
 	    		}
 	    		continue;
 	    	} else if (object2 == null) {
+	    		if (noNulls) {
+					throw ex;
+				}
 	    		return 1;
 	    	}
 			int comp = Constant.COMPARATOR.compare(object1, object2);
@@ -76,4 +94,9 @@
 		return values;
 	}
 	
+	@Override
+	public String toString() {
+		return SQLStringVisitor.getSQLString(new Constant(this));
+	}
+	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Constant.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/Constant.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/Constant.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -134,11 +134,15 @@
         if(type == null) {
             throw new IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0014")); //$NON-NLS-1$
         }
+        Class<?> originalType = type;
+        while (type.isArray()) {
+        	type = type.getComponentType();
+        }
         if(! DataTypeManager.getAllDataTypeClasses().contains(type)) {
             throw new IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0015", type.getName())); //$NON-NLS-1$
         }
-        assert value == null || type.isAssignableFrom(value.getClass()) : "Invalid value for specified type."; //$NON-NLS-1$
-        this.type = type;
+        assert value == null || originalType.isArray() || originalType.isAssignableFrom(value.getClass()) : "Invalid value for specified type."; //$NON-NLS-1$
+        this.type = originalType;
 	}
 
 	/**
@@ -150,10 +154,20 @@
 		this.value = DataTypeManager.convertToRuntimeType(value);
 		if (this.value == null) {
 			this.type = DataTypeManager.DefaultDataClasses.NULL;
-		} else if (DataTypeManager.getAllDataTypeClasses().contains(this.value.getClass())) {
+		} else { 
 			this.type = this.value.getClass();
-		} else {
-			this.type = DataTypeManager.DefaultDataClasses.OBJECT; 
+			Class<?> originalType = type;
+	        while (type.isArray()) {
+	        	type = type.getComponentType();
+	        }
+			if (DataTypeManager.getAllDataTypeClasses().contains(type)) {
+				//array of a runtime-type
+				this.type = originalType;
+			} else if (originalType.isArray()) {
+				this.type = DataTypeManager.getArrayType(DataTypeManager.DefaultDataClasses.OBJECT);
+			} else {
+				this.type = DataTypeManager.DefaultDataClasses.OBJECT;
+			}
 		}
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/Reference.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -41,6 +41,7 @@
 	}
 	
     private boolean positional;
+    private boolean optional;
 
     private int refIndex;
     private Class<?> type;
@@ -81,6 +82,7 @@
     		this.expression = ref.expression.clone();
     	}
     	this.constraint = ref.constraint;
+    	this.optional = ref.optional;
     }
 
     public int getIndex() {
@@ -186,5 +188,13 @@
     	assert this.expression != null && !this.positional;
 		this.expression = expression;
 	}
+
+	public boolean isOptional() {
+		return optional;
+	}
+	
+	public void setOptional(boolean optional) {
+		this.optional = optional;
+	}
     
 }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -1138,44 +1138,65 @@
 
     public void visit( Constant obj ) {
         Class<?> type = obj.getType();
-        String[] constantParts = null;
-        if (obj.isMultiValued()) {
+        boolean multiValued = obj.isMultiValued();
+	    Object value = obj.getValue();
+	    outputLiteral(type, multiValued, value);
+    }
+
+	private void outputLiteral(Class<?> type,
+			boolean multiValued, Object value) throws AssertionError {
+		String[] constantParts = null;
+	    if (multiValued) {
             constantParts = new String[] {"?"}; //$NON-NLS-1$
-        } else if (obj.isNull()) {
-            if (type.equals(DataTypeManager.DefaultDataClasses.BOOLEAN)) {
-                constantParts = new String[] {UNKNOWN};
-            } else {
-                constantParts = new String[] {"null"}; //$NON-NLS-1$
-            }
-        } else {
-            if (Number.class.isAssignableFrom(type)) {
-                constantParts = new String[] {obj.getValue().toString()};
-            } else if (type.equals(DataTypeManager.DefaultDataClasses.BOOLEAN)) {
-                constantParts = new String[] {obj.getValue().equals(Boolean.TRUE) ? TRUE : FALSE};
-            } else if (type.equals(DataTypeManager.DefaultDataClasses.TIMESTAMP)) {
-                constantParts = new String[] {"{ts'", obj.getValue().toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
-            } else if (type.equals(DataTypeManager.DefaultDataClasses.TIME)) {
-                constantParts = new String[] {"{t'", obj.getValue().toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
-            } else if (type.equals(DataTypeManager.DefaultDataClasses.DATE)) {
-                constantParts = new String[] {"{d'", obj.getValue().toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
-            } else if (type.equals(DataTypeManager.DefaultDataClasses.VARBINARY)) {
-            	constantParts = new String[] {"X'", obj.getValue().toString(), "'"}; //$NON-NLS-1$ //$NON-NLS-2$
-            }
-            if (constantParts == null) {
-            	if (DataTypeManager.isLOB(type)) {
-            		constantParts = new String[] {"?"}; //$NON-NLS-1$
-            	} else {
-	                String strValue = obj.getValue().toString();
-	                strValue = escapeStringValue(strValue, "'"); //$NON-NLS-1$
-	                constantParts = new String[] {"'", strValue, "'"}; //$NON-NLS-1$ //$NON-NLS-2$
-            	}
-            }
-        }
+        } else if (value == null) {
+		    if (type.equals(DataTypeManager.DefaultDataClasses.BOOLEAN)) {
+		        constantParts = new String[] {UNKNOWN};
+		    } else {
+		        constantParts = new String[] {"null"}; //$NON-NLS-1$
+		    }
+		} else {
+			if (value.getClass() == ArrayValue.class) {
+				ArrayValue av = (ArrayValue)value;
+				append(Tokens.LPAREN);
+				for (int i = 0; i < av.getValues().length; i++) {
+					if (i > 0) {
+						append(Tokens.COMMA);
+						append(SPACE);
+					}
+					Object value2 = av.getValues()[i];
+					outputLiteral(value2!=null?value2.getClass():av.getValues().getClass().getComponentType(), multiValued, value2);
+				}
+				append(Tokens.RPAREN);
+				return;
+			}
+			if (Number.class.isAssignableFrom(type)) {
+		        constantParts = new String[] {value.toString()};
+		    } else if (type.equals(DataTypeManager.DefaultDataClasses.BOOLEAN)) {
+		        constantParts = new String[] {value.equals(Boolean.TRUE) ? TRUE : FALSE};
+		    } else if (type.equals(DataTypeManager.DefaultDataClasses.TIMESTAMP)) {
+		        constantParts = new String[] {"{ts'", value.toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
+		    } else if (type.equals(DataTypeManager.DefaultDataClasses.TIME)) {
+		        constantParts = new String[] {"{t'", value.toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
+		    } else if (type.equals(DataTypeManager.DefaultDataClasses.DATE)) {
+		        constantParts = new String[] {"{d'", value.toString(), "'}"}; //$NON-NLS-1$ //$NON-NLS-2$
+		    } else if (type.equals(DataTypeManager.DefaultDataClasses.VARBINARY)) {
+		    	constantParts = new String[] {"X'", value.toString(), "'"}; //$NON-NLS-1$ //$NON-NLS-2$
+		    }
+		    if (constantParts == null) {
+		    	if (DataTypeManager.isLOB(type)) {
+		    		constantParts = new String[] {"?"}; //$NON-NLS-1$
+		    	} else {
+		            String strValue = value.toString();
+		            strValue = escapeStringValue(strValue, "'"); //$NON-NLS-1$
+		            constantParts = new String[] {"'", strValue, "'"}; //$NON-NLS-1$ //$NON-NLS-2$
+		    	}
+		    }
+		}
 
         for (String string : constantParts) {
             append(string);
         }
-    }
+	}
 
     /**
      * Take a string literal and escape it as necessary. By default, this converts ' to ''.
@@ -2111,9 +2132,13 @@
     
     @Override
     public void visit(Array array) {
-    	append(Tokens.LPAREN);
+    	if (!array.isImplicit()) {
+    		append(Tokens.LPAREN);
+    	}
     	registerNodes(array.getExpressions(), 0);
-    	append(Tokens.RPAREN);
+    	if (!array.isImplicit()) {
+    		append(Tokens.RPAREN);
+    	}
     }
 
     public static String escapeSinglePart( String part ) {

Modified: trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/tempdata/TempTableDataManager.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -286,12 +286,12 @@
 		QueryMetadataInterface metadata = context.getMetadata();
 		GlobalTableStore globalStore = context.getGlobalTableStore();
 		if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEW)) {
-			Object groupID = validateMatView(metadata, (String)((Constant)proc.getParameter(1).getExpression()).getValue());
+			Object groupID = validateMatView(metadata, (String)((Constant)proc.getParameter(2).getExpression()).getValue());
 			Object matTableId = globalStore.getGlobalTempTableMetadataId(groupID);
 			String matViewName = metadata.getFullName(groupID);
 			String matTableName = metadata.getFullName(matTableId);
 			LogManager.logDetail(LogConstants.CTX_MATVIEWS, "processing refreshmatview for", matViewName); //$NON-NLS-1$
-			boolean invalidate = Boolean.TRUE.equals(((Constant)proc.getParameter(2).getExpression()).getValue());
+			boolean invalidate = Boolean.TRUE.equals(((Constant)proc.getParameter(3).getExpression()).getValue());
 			boolean needsLoading = globalStore.needsLoading(matTableName, globalStore.getAddress(), true, true, invalidate);
 			if (!needsLoading) {
 				return CollectionTupleSource.createUpdateCountTupleSource(-1);
@@ -301,7 +301,7 @@
 			int rowCount = loadGlobalTable(context, matTable, matTableName, globalStore);
 			return CollectionTupleSource.createUpdateCountTupleSource(rowCount);
 		} else if (StringUtil.endsWithIgnoreCase(proc.getProcedureCallableName(), REFRESHMATVIEWROW)) {
-			Object groupID = validateMatView(metadata, (String)((Constant)proc.getParameter(1).getExpression()).getValue());
+			Object groupID = validateMatView(metadata, (String)((Constant)proc.getParameter(2).getExpression()).getValue());
 			Object pk = metadata.getPrimaryKey(groupID);
 			String matViewName = metadata.getFullName(groupID);
 			if (pk == null) {
@@ -320,7 +320,7 @@
 			if (!tempTable.isUpdatable()) {
 				 throw new QueryProcessingException(QueryPlugin.Event.TEIID30232, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30232, matViewName));
 			}
-			Constant key = (Constant)proc.getParameter(2).getExpression();
+			Constant key = (Constant)proc.getParameter(3).getExpression();
 			LogManager.logInfo(LogConstants.CTX_MATVIEWS, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30012, matViewName, key));
 			Object id = ids.iterator().next();
 			String targetTypeName = metadata.getElementType(id);

Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -367,13 +367,20 @@
 	            	handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.multisource_constant", param.getParameterSymbol()), param.getParameterSymbol()); //$NON-NLS-1$
 	            	continue;
 	            }
-                if (EvaluatableVisitor.isFullyEvaluatable(param.getExpression(), true)) {
+                if (!getMetadata().elementSupports(param.getMetadataID(), SupportConstants.Element.NULL) && EvaluatableVisitor.isFullyEvaluatable(param.getExpression(), true)) {
 	                try {
 	                    // If nextValue is an expression, evaluate it before checking for null
 	                    Object evaluatedValue = Evaluator.evaluate(param.getExpression());
-	                    if(evaluatedValue == null && ! getMetadata().elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+	                    if(evaluatedValue == null) {
 	                        handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0055", param.getParameterSymbol()), param.getParameterSymbol()); //$NON-NLS-1$
-	                    }
+	                    } else if (evaluatedValue instanceof ArrayValue && getMetadata().isVariadic(param.getMetadataID())) {
+	            			ArrayValue av = (ArrayValue)evaluatedValue;
+	            			for (Object o : av.getValues()) {
+	            				if (o == null) {
+	            					handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0055", param.getParameterSymbol()), param.getParameterSymbol()); //$NON-NLS-1$
+	            				}
+	            			}
+	            		}
 	                } catch(ExpressionEvaluationException e) {
 	                    //ignore for now, we don't have the context which could be the problem
 	                }

Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-30 17:48:02 UTC (rev 4382)
@@ -454,6 +454,7 @@
 |   <INCLUDING: "including">
 |   <EXCLUDING: "excluding">
 |   <XMLDECLARATION: "xmldeclaration">
+|   <VARIADIC: "variadic">
 
 }
 /*
@@ -561,7 +562,7 @@
      |<TO_BYTES>|<TIMESTAMPADD>|<TIMESTAMPDIFF>|<QUERYSTRING>|<NAMESPACE>|<RESULT>|<INDEX>|<ACCESSPATTERN>|<AUTO_INCREMENT>|<WELLFORMED>|<SQL_TSI_FRAC_SECOND>
      |<SQL_TSI_SECOND>|<SQL_TSI_MINUTE>|<SQL_TSI_HOUR>|<SQL_TSI_DAY>|<SQL_TSI_WEEK>|<SQL_TSI_MONTH>|<SQL_TSI_QUARTER>|<SQL_TSI_YEAR>|<TEXTTABLE>|<ARRAYTABLE>
      |<SELECTOR>|<SKIP_KEYWORD>|<WIDTH>|<PASSING>|<NAME>|<ENCODING>|<COLUMNS>|<DELIMITER>|<QUOTE>|<HEADER>|<NULLS>|<OBJECTTABLE>
-     |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>)
+     |<VERSION>|<INCLUDING>|<EXCLUDING>|<XMLDECLARATION>|<VARIADIC>)
     {
     	return getToken(0);
     }	
@@ -4609,11 +4610,13 @@
 	ProcedureParameter param = null;
 	String defaultValue = null;
 	boolean notNull = false;
+	boolean vararg = false;
 }
 {
-	[((<IN> {ppType = ProcedureParameter.Type.In ;})
+	[LOOKAHEAD(1) ((<IN> {ppType = ProcedureParameter.Type.In ;})
 	 |(<OUT> {ppType = ProcedureParameter.Type.Out;})
-	 |(<INOUT> {ppType = ProcedureParameter.Type.InOut;}))]
+	 |(<INOUT> {ppType = ProcedureParameter.Type.InOut;})
+	 |(<VARIADIC> {ppType = ProcedureParameter.Type.In ; vararg = true;}))]
 	name = id()
 	type = parseDataType()
 	[<NOT> <NULL> {notNull = true;}]
@@ -4632,6 +4635,9 @@
 			if (notNull) {
 				param.setNullType(Column.NullType.No_Nulls);
 			}
+			if (vararg) {
+				param.setVarArg(vararg);
+			}			
 		} catch (TranslatorException e){
 			throw new ParseException(e.getMessage());
 		}

Modified: trunk/engine/src/main/resources/org/teiid/metadata/SYSADMIN.sql
===================================================================
--- trunk/engine/src/main/resources/org/teiid/metadata/SYSADMIN.sql	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/resources/org/teiid/metadata/SYSADMIN.sql	2012-08-30 17:48:02 UTC (rev 4382)
@@ -21,10 +21,10 @@
 CREATE FOREIGN PROCEDURE logMsg(OUT logged boolean NOT NULL RESULT, IN level string NOT NULL DEFAULT 'DEBUG', IN context string NOT NULL DEFAULT 'org.teiid.PROCESSOR', IN msg object NOT NULL)
 OPTIONS (UPDATECOUNT 0)
 
-CREATE FOREIGN PROCEDURE refreshMatView(IN ViewName string NOT NULL, IN Invalidate boolean NOT NULL DEFAULT 'false', OUT RowsUpdated integer NOT NULL RESULT)
+CREATE FOREIGN PROCEDURE refreshMatView(OUT RowsUpdated integer NOT NULL RESULT, IN ViewName string NOT NULL, IN Invalidate boolean NOT NULL DEFAULT 'false')
 OPTIONS (UPDATECOUNT 0)
 
-CREATE FOREIGN PROCEDURE refreshMatViewRow(IN ViewName string NOT NULL, IN Key object NOT NULL, OUT RowsUpdated integer NOT NULL RESULT)
+CREATE FOREIGN PROCEDURE refreshMatViewRow(OUT RowsUpdated integer NOT NULL RESULT, IN ViewName string NOT NULL, IN Key object NOT NULL)
 OPTIONS (UPDATECOUNT 0)
 
 CREATE FOREIGN PROCEDURE setColumnStats(IN tableName string NOT NULL, IN columnName string NOT NULL, IN distinctCount integer, IN nullCount integer, IN max string, IN min string)

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-30 17:48:02 UTC (rev 4382)
@@ -649,7 +649,7 @@
 XMLSerialize.resolvingError=XMLSerialize is valid only for XML expressions: {0}
 TEIID30336=XMLSerialize: data exception - not an xml document
 TEIID30333=Error evaluating XMLQuery: {0}
-TEIID30145=Unable to convert procedural parameter of type {0} to expected type {1}
+TEIID30145=Unable to convert procedural parameter {0} of type {1} to expected type {2}
 TEIID30139=Procedure {0} does not have a return value.
 TEIID30144=OUT/RETURN parameter {0} with type {1} cannot be converted to {2}
 TEIID30100=Expected dynamic command sql to be of type STRING instead of type {0}.
@@ -943,7 +943,7 @@
 TEIID30098= Unable to resolve return element referred to by LOOKUP function: {0}
 TEIID30118=Cannot create temporary table "{0}". An object with the same name already exists.
 TEIID30121=Variable "{0}" is read only and cannot be assigned a value.
-TEIID30140= Incorrect number of parameters specified on the stored procedure {2} - expected {0} but got {1}
+TEIID30140= Incorrect number of parameters specified on the stored procedure {2} - expected between {0} and {1} but got {2}
 TEIID30146= No procedure plan exists for {0}.
 TEIID30183=Text parse error: Non-whitespace character found between the qualifier and the delimiter in text line {0} in {1}.
 TEIID30227=Table {0} is locked by pending transaction update.
@@ -1027,6 +1027,8 @@
 TEIID31109=Invalid language {0}.  Supported and allowed language names are {1}.
 TEIID31110=Invalid script {0}.  Scrpting engine reported: {1}
 TEIID31111=No such accessible property/method {0} on {1}.
+TEIID31112=Only the last parameter of {0} may be VARIADIC.
+TEIID31113={0} extra positional parameter(s) passed to {2}.
 
 SQLParser.proc_type_conflict=Result type {1} conflicts with return type {2} for procedure {0}
 SQLParser.param_out=Procedure {0} RESULT param {1} must be of type OUT.

Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestDDLStringVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -241,7 +241,15 @@
 	private void helpTest(String ddl, String expected) throws ParseException {
 		Schema s = TestDDLParser.helpParse(ddl, "model").getSchema();
 		String metadataDDL = DDLStringVisitor.getDDLString(s, null, null);
-		//System.out.println(metadataDDL);
 		assertEquals(expected, metadataDDL);
 	}	
+	
+	@Test
+	public void testSourceProcedureVariadic() throws Exception {
+		String ddl = "CREATE FOREIGN PROCEDURE myProc(OUT p1 boolean, VARIADIC p3 decimal) " +
+				"RETURNS (r1 varchar, r2 decimal);";
+		
+		String expected = "CREATE FOREIGN PROCEDURE myProc(OUT p1 boolean, VARIADIC p3 bigdecimal) RETURNS TABLE (r1 string, r2 bigdecimal)";
+		helpTest(ddl, expected);		
+	}	
 }

Modified: trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/metadata/TestMetadataValidator.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -64,6 +64,7 @@
 		
 		DDLMetadataRepository repo = new DDLMetadataRepository();
 		MetadataFactory mf = new MetadataFactory("myVDB",1, modelName, TestDDLParser.getDataTypes(), new Properties(), ddl);
+		mf.setBuiltinDataTypes(SystemMetadata.getInstance().getSystemStore().getDatatypes());
 		mf.getSchema().setPhysical(physical);
 		repo.loadMetadata(mf, null, null);
 		mf.mergeInto(store);	
@@ -312,4 +313,17 @@
 		ValidatorReport report = new MetadataValidator().validate(this.vdb, this.store);
 		assertFalse(printError(report), report.hasItems());
 	}	
+	
+	@Test public void testInvalidVarArgs() throws Exception {
+		// note here the unique here does not matter for non-existent reference columns, only primary key counted.
+		String ddl = "CREATE FOREIGN FUNCTION f1(VARIADIC e1 integer, e2 varchar) RETURNS varchar;";
+		
+		buildModel("pm1", true, this.vdb, this.store, ddl);
+		
+		buildTransformationMetadata();
+		
+		ValidatorReport report = new ValidatorReport();
+		report = new MetadataValidator().validate(this.vdb, this.store);
+		assertTrue(printError(report), report.hasItems());
+	}
 }

Modified: trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/processor/eval/TestExpressionEvaluator.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -27,6 +27,7 @@
 import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -47,19 +48,12 @@
 import org.teiid.query.processor.ProcessorDataManager;
 import org.teiid.query.resolver.TestFunctionResolving;
 import org.teiid.query.sql.lang.CollectionValueIterator;
+import org.teiid.query.sql.lang.CompareCriteria;
 import org.teiid.query.sql.lang.IsNullCriteria;
 import org.teiid.query.sql.lang.Query;
 import org.teiid.query.sql.lang.QueryCommand;
 import org.teiid.query.sql.lang.SubqueryContainer;
-import org.teiid.query.sql.symbol.CaseExpression;
-import org.teiid.query.sql.symbol.Constant;
-import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.Function;
-import org.teiid.query.sql.symbol.ScalarSubquery;
-import org.teiid.query.sql.symbol.SearchedCaseExpression;
-import org.teiid.query.sql.symbol.TestCaseExpression;
-import org.teiid.query.sql.symbol.TestSearchedCaseExpression;
+import org.teiid.query.sql.symbol.*;
 import org.teiid.query.sql.util.ValueIterator;
 import org.teiid.query.unittest.RealMetadataFactory;
 import org.teiid.query.util.CommandContext;
@@ -77,19 +71,14 @@
     }
 
     public Object helpEval(Expression expr, Expression[] elementList, Object[] valueList, ProcessorDataManager dataMgr, CommandContext context) throws ExpressionEvaluationException, BlockedException, TeiidComponentException {
-        Map elements = new HashMap();
+        Map<Expression, Integer> elements = new HashMap<Expression, Integer>();
         if (elementList != null) {
             for(int i=0; i<elementList.length; i++) {
-                elements.put(elementList[i], new Integer(i));
+                elements.put(elementList[i], i);
             }
         }
         
-        List tuple = new ArrayList();
-        if (valueList != null) {
-            for(int i=0; i<valueList.length; i++) {
-                tuple.add(valueList[i]);
-            }
-        }
+        List<Object> tuple = Arrays.asList(valueList);
         return new Evaluator(elements, dataMgr, context).evaluate(expr, tuple);
     }
     
@@ -488,4 +477,9 @@
     	assertEquals(Boolean.TRUE, Evaluator.evaluate(ex));
     }
     
+    @Test public void testArrayEquality() throws Exception {
+    	assertEquals(Boolean.TRUE, Evaluator.evaluate(new CompareCriteria(new Array(Arrays.asList((Expression)new Constant(1))), CompareCriteria.EQ, new Array(Arrays.asList((Expression)new Constant(1))))));
+    	assertNull(new Evaluator(null, null, null).evaluateTVL(new CompareCriteria(new Array(Arrays.asList((Expression)new Constant(1))), CompareCriteria.EQ, new Array(Arrays.asList((Expression)new Constant(null)))), null));
+    }
+    
 }

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	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -63,6 +63,7 @@
 import org.teiid.query.processor.xml.TestXMLPlanningEnhancements;
 import org.teiid.query.processor.xml.TestXMLProcessor;
 import org.teiid.query.resolver.QueryResolver;
+import org.teiid.query.resolver.TestProcedureResolving;
 import org.teiid.query.rewriter.QueryRewriter;
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.SPParameter;
@@ -2004,7 +2005,60 @@
     	Mockito.verify(ts, Mockito.times(0)).commit(tc);
     	Mockito.verify(ts).rollback(tc);
     }
+    
+    @Test public void testVarArgs() throws Exception {
+    	String ddl = "create foreign procedure proc (x integer, VARIADIC z integer); create virtual procedure vproc (x integer, VARIADIC z integer) returns integer as begin \"return\" = z[2] + array_length(z); call proc(x, z); end;";
+    	TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);    	
+        String sql = "call vproc(1, 2, 3)"; //$NON-NLS-1$
 
+        ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+        HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+        dataManager.addData("EXEC proc(1, 2, 3)", new List<?>[0]);
+        // Create expected results
+        List[] expected = new List[] { Arrays.asList(5) }; //$NON-NLS-1$
+        helpTestProcess(plan, expected, dataManager, tm);
+    }
+    
+    @Test public void testVarArgsVirtNotNull() throws Exception {
+    	String ddl = "create virtual procedure vproc (x integer, VARIADIC z integer NOT NULL) returns (y integer) as begin select array_length(z); end;";
+    	TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);
+    	
+        String sql = "call vproc(1, null, 3)"; //$NON-NLS-1$
+
+        try {
+        	getProcedurePlan(sql, tm);
+        	fail();
+        } catch (QueryValidatorException e) {
+        	
+        }
+    	
+        sql = "call vproc(1, (select cast(null as integer)), 3)"; //$NON-NLS-1$
+
+        ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+        HardcodedDataManager dataManager = new HardcodedDataManager();
+        try {
+        	helpTestProcess(plan, null, dataManager, tm);
+        	fail();
+        } catch (QueryValidatorException e) {
+        	
+        }
+    }
+    
+    @Test public void testVarArgsFunctionInVirt() throws Exception {
+    	String ddl = "create virtual procedure proc (VARIADIC z STRING) returns string as \"return\" = coalesce(null, null, z);";
+    	TransformationMetadata tm = TestProcedureResolving.createMetadata(ddl);    	
+        String sql = "call proc(1, 2, 3)"; //$NON-NLS-1$
+
+        ProcessorPlan plan = getProcedurePlan(sql, tm);
+
+        HardcodedDataManager dataManager = new HardcodedDataManager(tm);
+        // note that we're properly cast to string, even though we called with int
+        List[] expected = new List[] { Arrays.asList("1") }; //$NON-NLS-1$
+        helpTestProcess(plan, expected, dataManager, tm);
+    }
+
     private static final boolean DEBUG = false;
     
 }

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/CheckNoTempMetadataIDsVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/CheckNoTempMetadataIDsVisitor.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/CheckNoTempMetadataIDsVisitor.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -22,12 +22,16 @@
 
 package org.teiid.query.resolver;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
 
 import org.teiid.query.metadata.TempMetadataID;
-import org.teiid.query.sql.*;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
 import org.teiid.query.sql.navigator.DeepPreOrderNavigator;
-import org.teiid.query.sql.symbol.*;
+import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.Symbol;
 
 
 /**
@@ -37,16 +41,14 @@
  */
 public class CheckNoTempMetadataIDsVisitor extends LanguageVisitor {
 
-    private Collection symbolsWithTempMetadataIDs;
-    private Collection ignoreTheseSymbols;
+    private Collection<Symbol> symbolsWithTempMetadataIDs;
     
     /**
      * By default, this visitor deeply traverses all commands, and there are
      * no symbols to ignore
      */
 	public CheckNoTempMetadataIDsVisitor() { 
-        symbolsWithTempMetadataIDs = new ArrayList();    
-        this.ignoreTheseSymbols = Collections.EMPTY_LIST;
+        symbolsWithTempMetadataIDs = new ArrayList<Symbol>();    
     }
     
     /**
@@ -54,7 +56,7 @@
      * @return Collection of any unresolved Symbols; may
      * be empty but never null
      */
-    public Collection getSymbols(){
+    public Collection<Symbol> getSymbols(){
         return this.symbolsWithTempMetadataIDs;
     }
 
@@ -62,7 +64,7 @@
      * By default, this visitor deeply traverses all commands, and there are
      * no symbols to ignore
      */
-    public static final Collection checkSymbols(LanguageObject obj){
+    public static final Collection<Symbol> checkSymbols(LanguageObject obj){
         CheckNoTempMetadataIDsVisitor visitor = new CheckNoTempMetadataIDsVisitor();
         DeepPreOrderNavigator.doVisit(obj, visitor);
         return visitor.getSymbols();
@@ -71,13 +73,13 @@
     // visitor methods
     
     public void visit(ElementSymbol obj) {
-        if (obj.getMetadataID() instanceof TempMetadataID && !(this.ignoreTheseSymbols.contains(obj))){
+        if (obj.getMetadataID() instanceof TempMetadataID){
             this.symbolsWithTempMetadataIDs.add(obj);
         }
     }
 
     public void visit(GroupSymbol obj) {
-        if (obj.getMetadataID() instanceof TempMetadataID && !(this.ignoreTheseSymbols.contains(obj))){
+        if (obj.getMetadataID() instanceof TempMetadataID){
             this.symbolsWithTempMetadataIDs.add(obj);
         }
     }

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -24,6 +24,7 @@
 
 import static org.junit.Assert.*;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Map;
 
@@ -48,6 +49,7 @@
 import org.teiid.query.sql.lang.Command;
 import org.teiid.query.sql.lang.Insert;
 import org.teiid.query.sql.lang.ProcedureContainer;
+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;
@@ -55,12 +57,14 @@
 import org.teiid.query.sql.proc.CreateProcedureCommand;
 import org.teiid.query.sql.proc.LoopStatement;
 import org.teiid.query.sql.proc.TriggerAction;
+import org.teiid.query.sql.symbol.Array;
 import org.teiid.query.sql.symbol.Constant;
 import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.visitor.CommandCollectorVisitor;
 import org.teiid.query.sql.visitor.ElementCollectorVisitor;
 import org.teiid.query.unittest.RealMetadataFactory;
+import org.teiid.query.validator.ValidatorReport;
 
 @SuppressWarnings("nls")
 public class TestProcedureResolving {
@@ -1024,14 +1028,8 @@
     }
     
     @Test public void testOptionalParams() throws Exception {
-    	VDBMetaData vdb = new VDBMetaData();
-    	MetadataStore store = new MetadataStore();
     	String ddl = "create foreign procedure proc (x integer, y string);\n";
-    	TestMetadataValidator.buildModel("x", true, vdb, store, ddl);
-    	TransformationMetadata tm = new TransformationMetadata(vdb, new CompositeMetadataStore(Arrays.asList(store)), null, RealMetadataFactory.SFM.getSystemFunctions(), null);
-    	vdb.addAttchment(TransformationMetadata.class, tm);
-    	vdb.addAttchment(QueryMetadataInterface.class, tm);
-    	new MetadataValidator().validate(vdb, store);
+    	TransformationMetadata tm = createMetadata(ddl);
     	
         String sql = "call proc (1)"; //$NON-NLS-1$
         
@@ -1045,16 +1043,24 @@
 
         assertEquals(new Constant("a", DataTypeManager.DefaultDataClasses.STRING), sp.getParameter(2).getExpression());
     }
-    
-    @Test public void testOptionalParams1() throws Exception {
-    	VDBMetaData vdb = new VDBMetaData();
+
+	public static TransformationMetadata createMetadata(String ddl) throws Exception {
+		VDBMetaData vdb = new VDBMetaData();
     	MetadataStore store = new MetadataStore();
-    	String ddl = "create foreign procedure proc (x integer, y string NOT NULL, z integer);\n";
     	TestMetadataValidator.buildModel("x", true, vdb, store, ddl);
     	TransformationMetadata tm = new TransformationMetadata(vdb, new CompositeMetadataStore(Arrays.asList(store)), null, RealMetadataFactory.SFM.getSystemFunctions(), null);
     	vdb.addAttchment(TransformationMetadata.class, tm);
     	vdb.addAttchment(QueryMetadataInterface.class, tm);
-    	new MetadataValidator().validate(vdb, store);
+    	ValidatorReport report = new MetadataValidator().validate(vdb, store);
+    	if (report.hasItems()) {
+    		throw new RuntimeException(report.getFailureMessage());
+    	}
+		return tm;
+	}
+    
+    @Test public void testOptionalParams1() throws Exception {
+    	String ddl = "create foreign procedure proc (x integer, y string NOT NULL, z integer);\n";
+    	TransformationMetadata tm = createMetadata(ddl);
     	
         String sql = "call proc (1, 'a')"; //$NON-NLS-1$
 
@@ -1063,4 +1069,21 @@
         assertEquals(new Constant("a", DataTypeManager.DefaultDataClasses.STRING), sp.getParameter(2).getExpression());
     }
     
+    @Test public void testVarArgs() throws Exception {
+    	String ddl = "create foreign procedure proc (x integer, VARIADIC z integer) returns (x string);\n";
+    	TransformationMetadata tm = createMetadata(ddl);    	
+        String sql = "call proc (1, 2, 3)"; //$NON-NLS-1$
+
+        StoredProcedure sp = (StoredProcedure) TestResolver.helpResolve(sql, tm);
+        assertEquals("EXEC proc(1, 2, 3)", sp.toString());
+        assertEquals(new Constant(1), sp.getParameter(1).getExpression());
+        assertEquals(new Array(DataTypeManager.DefaultDataClasses.INTEGER, Arrays.asList((Expression)new Constant(2), new Constant(3))), sp.getParameter(2).getExpression());
+        assertEquals(SPParameter.RESULT_SET, sp.getParameter(3).getParameterType());
+        
+        sql = "call proc (1)"; //$NON-NLS-1$
+        sp = (StoredProcedure) TestResolver.helpResolve(sql, tm);
+        assertEquals("EXEC proc(1)", sp.toString());
+        assertEquals(new Array(DataTypeManager.DefaultDataClasses.INTEGER, new ArrayList<Expression>(0)), sp.getParameter(2).getExpression());
+    }
+    
 }

Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -129,7 +129,7 @@
 
         if (variableNames.length == 0){
             //There should be no TempMetadataIDs
-            Collection symbols = CheckNoTempMetadataIDsVisitor.checkSymbols(query);
+            Collection<Symbol> symbols = CheckNoTempMetadataIDsVisitor.checkSymbols(query);
             assertTrue("Expected no symbols with temp metadataIDs, but got " + symbols, symbols.isEmpty()); //$NON-NLS-1$
         }
         
@@ -315,7 +315,7 @@
 
         StoredProcedure proc = (StoredProcedure)helpResolve(sql);
         
-        List<SPParameter> params = proc.getParameters();
+        Collection<SPParameter> params = proc.getParameters();
 
         // Check remaining params against expected expressions
         int i = 0;
@@ -852,14 +852,14 @@
         StoredProcedure proc = (StoredProcedure) helpResolve("EXEC pm1.sq2('abc')"); //$NON-NLS-1$
         
         // Check number of resolved parameters
-        List<SPParameter> params = proc.getParameters();
+        Map<Integer, SPParameter> params = proc.getMapOfParameters();
         assertEquals("Did not get expected parameter count", 2, params.size()); //$NON-NLS-1$
         
         // Check resolved parameters
-        SPParameter param1 = params.get(1);
+        SPParameter param1 = params.get(2);
         helpCheckParameter(param1, ParameterInfo.RESULT_SET, 2, "pm1.sq2.ret", java.sql.ResultSet.class, null); //$NON-NLS-1$
 
-        SPParameter param2 = params.get(0);
+        SPParameter param2 = params.get(1);
         helpCheckParameter(param2, ParameterInfo.IN, 1, "pm1.sq2.in", DataTypeManager.DefaultDataClasses.STRING, new Constant("abc")); //$NON-NLS-1$ //$NON-NLS-2$
     }
     
@@ -876,14 +876,14 @@
 		StoredProcedure proc = (StoredProcedure) helpResolve("EXEC pm1.sq3a('abc', 123)"); //$NON-NLS-1$
 		
 		// Check number of resolved parameters
-		List<SPParameter> params = proc.getParameters();
+		Map<Integer, SPParameter> params = proc.getMapOfParameters();
 		assertEquals("Did not get expected parameter count", 3, params.size()); //$NON-NLS-1$
         
 		// Check resolved parameters
-		SPParameter param1 = params.get(0);
+		SPParameter param1 = params.get(1);
 		helpCheckParameter(param1, ParameterInfo.IN, 1, "pm1.sq3a.in", DataTypeManager.DefaultDataClasses.STRING, new Constant("abc")); //$NON-NLS-1$ //$NON-NLS-2$
 
-		SPParameter param2 = params.get(1);
+		SPParameter param2 = params.get(2);
 		helpCheckParameter(param2, ParameterInfo.IN, 2, "pm1.sq3a.in2", DataTypeManager.DefaultDataClasses.INTEGER, new Constant(new Integer(123))); //$NON-NLS-1$
 	}    
     
@@ -2049,9 +2049,7 @@
         while(iter.hasNext()) {
             SubqueryFromClause clause = (SubqueryFromClause) iter.next();
             StoredProcedure proc = (StoredProcedure) clause.getCommand();
-            List procParams = proc.getParameters();
-            for(int i=0; i<procParams.size(); i++) {
-                SPParameter param = (SPParameter) procParams.get(i);
+            for (SPParameter param : proc.getParameters()) {
                 if(param.getParameterType() == ParameterInfo.IN) {
                     if(params[0] == null) {
                         params[0] = param;
@@ -2115,7 +2113,7 @@
     }
 
     @Test public void testParameterError() throws Exception {
-        helpResolveException("EXEC pm1.sp2(1, 2)", metadata, "TEIID30140 Incorrect number of parameters specified on the stored procedure pm1.sp2 - expected 1 but got 2"); //$NON-NLS-1$ //$NON-NLS-2$
+        helpResolveException("EXEC pm1.sp2(1, 2)", metadata, "TEIID31113 1 extra positional parameter(s) passed to pm1.sp2."); //$NON-NLS-1$ //$NON-NLS-2$
     }
     
     @Test public void testUnionOfAliasedLiteralsGetsModified() {
@@ -2601,7 +2599,7 @@
 	@Test public void testCallableStatementTooManyParameters() throws Exception {
 		String sql = "{call pm4.spTest9(?, ?)}"; //$NON-NLS-1$
 		
-		TestResolver.helpResolveException(sql, RealMetadataFactory.exampleBQTCached(), "TEIID30140 Incorrect number of parameters specified on the stored procedure pm4.spTest9 - expected 1 but got 2"); //$NON-NLS-1$
+		TestResolver.helpResolveException(sql, RealMetadataFactory.exampleBQTCached(), "TEIID31113 1 extra positional parameter(s) passed to pm4.spTest9."); //$NON-NLS-1$
 	}	
 	    
     @Test public void testUpdateSetClauseReferenceType() {

Modified: trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/rewriter/TestQueryRewriter.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -26,6 +26,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -868,7 +869,7 @@
         // rewrite
         Command rewriteCommand = QueryRewriter.rewrite(command, metadata, null);
         
-        List<SPParameter> parameters = ((StoredProcedure)rewriteCommand).getParameters();
+        Collection<SPParameter> parameters = ((StoredProcedure)rewriteCommand).getParameters();
 
         for (SPParameter param : parameters) {
             if(param.getParameterType() == ParameterInfo.IN || param.getParameterType() == ParameterInfo.INOUT){

Modified: trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestArray.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -24,11 +24,20 @@
 
 import static org.junit.Assert.*;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
 import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
 
 import org.junit.Test;
+import org.teiid.client.BatchSerializer;
+import org.teiid.common.buffer.TupleBuffer;
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.core.util.UnitTestUtil;
+import org.teiid.query.sql.visitor.SQLStringVisitor;
 
 @SuppressWarnings("nls")
 public class TestArray {
@@ -43,6 +52,12 @@
 		UnitTestUtil.helpTestEquivalence(1, a1, a2);
 	}
 	
+	@Test public void testArrayValueToString() {
+		ArrayValue a1 = new ArrayValue(new Object[] {1, "x'2", 3});
+		
+		assertEquals("(1, 'x''2', 3)", SQLStringVisitor.getSQLString(new Constant(a1)));
+	}
+	
 	@Test public void testArrayClone() {
 		Array array = new Array(DataTypeManager.DefaultDataClasses.OBJECT, Arrays.asList((Expression)new ElementSymbol("e1")));
 		
@@ -52,4 +67,17 @@
 		assertNotSame(a1.getExpressions().get(0), array.getExpressions().get(0));
 	}
 	
+	@Test public void testArrayValueSerialization() throws Exception {
+		ArrayValue a1 = new ArrayValue(new Integer[] {1, 2, 3});
+		String[] types = TupleBuffer.getTypeNames(Arrays.asList(new Array(Integer.class, null)));
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		ObjectOutputStream oos = new ObjectOutputStream(baos);
+		BatchSerializer.writeBatch(oos, types, Collections.singletonList(Arrays.asList((a1))));
+		oos.close();
+		ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+		ObjectInputStream ois = new ObjectInputStream(bais);
+		List<List<Object>> batch = BatchSerializer.readBatch(ois, types);
+		assertEquals(a1, batch.get(0).get(0));
+	}
+	
 }

Modified: trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestConstant.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestConstant.java	2012-08-29 23:32:18 UTC (rev 4381)
+++ trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestConstant.java	2012-08-30 17:48:02 UTC (rev 4382)
@@ -171,5 +171,10 @@
 		
 		assertEquals(0, c.compare("a ", "a"));
 	}
+	
+	@Test public void testVarBinaryTyping() {
+		Constant c = new Constant(new byte[1]);
+		assertEquals(DataTypeManager.DefaultDataClasses.VARBINARY, c.getType());
+	}
     
 }



More information about the teiid-commits mailing list