[teiid-commits] teiid SVN: r4361 - in trunk: connectors/translator-olap/src/main/java/org/teiid/translator/olap and 21 other directories.

teiid-commits at lists.jboss.org teiid-commits at lists.jboss.org
Thu Aug 23 12:43:07 EDT 2012


Author: shawkins
Date: 2012-08-23 12:43:06 -0400 (Thu, 23 Aug 2012)
New Revision: 4361

Added:
   trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java
   trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java
Modified:
   trunk/api/src/main/java/org/teiid/language/SQLConstants.java
   trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
   trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.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/metadata/BasicQueryMetadata.java
   trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.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/TempMetadataAdapter.java
   trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java
   trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java
   trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
   trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java
   trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
   trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
   trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
   trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java
   trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
   trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
   trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
   trunk/engine/src/main/java/org/teiid/query/xquery/saxon/XQueryEvaluator.java
   trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
   trunk/engine/src/main/resources/org/teiid/query/i18n.properties
   trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
   trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java
   trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
   trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java
Log:
TEIID-2141 adding initial support for an object table and a few minor fixes

Modified: trunk/api/src/main/java/org/teiid/language/SQLConstants.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/api/src/main/java/org/teiid/language/SQLConstants.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -119,6 +119,7 @@
 		
 		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 interface Reserved {

Modified: trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java
===================================================================
--- trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/connectors/translator-olap/src/main/java/org/teiid/translator/olap/OlapQueryExecution.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -127,7 +127,7 @@
 			Cell cell = cellSet.getCell(colPos, rowPosition);
 			result[i++] = cell.getValue();
 		}	
-		ArrayList<Object[]> results = new ArrayList<Object[]>();
+		ArrayList<Object[]> results = new ArrayList<Object[]>(1);
 		results.add(result);
 		return results;
     }  

Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -373,7 +373,7 @@
 	}
 	
 	@Override
-	public QueryMetadataInterface getDesignTimeMetadata() {
+	protected QueryMetadataInterface createDesignTimeMetadata() {
 		return new MultiSourceMetadataWrapper(actualMetadata.getDesignTimeMetadata(), multiSourceModels);
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -526,5 +526,7 @@
     	TEIID31106, //duplicate param name
     	TEIID31107, //too many result params
     	TEIID31108, //datasource not available
+    	TEIID31109, //invalid scripting language
+    	TEIID31110, //invalid script
 	}
 }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -879,7 +879,7 @@
 	 * Evaluate the parameters and return the context item if it exists
 	 */
 	public Object evaluateParameters(List<DerivedColumn> cols, List<?> tuple,
-			HashMap<String, Object> parameters)
+			Map<String, Object> parameters)
 			throws ExpressionEvaluationException, BlockedException,
 			TeiidComponentException {
 		Object contextItem = null;

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadata.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -28,8 +28,11 @@
 import java.util.Properties;
 import java.util.Set;
 
+import javax.script.ScriptEngine;
+
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
@@ -519,5 +522,10 @@
 	public Set<String> getImportedModels() {
 		return Collections.emptySet();
 	}
-    
+	
+	@Override
+	public ScriptEngine getScriptEngine(String langauge) throws TeiidProcessingException {
+		return null;
+	}
+	
 }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -27,8 +27,11 @@
 import java.util.Properties;
 import java.util.Set;
 
+import javax.script.ScriptEngine;
+
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
@@ -37,6 +40,8 @@
 public class BasicQueryMetadataWrapper implements QueryMetadataInterface {
 	
 	protected QueryMetadataInterface actualMetadata;
+	protected QueryMetadataInterface designTimeMetadata;
+	protected boolean designTime;
 
 	public BasicQueryMetadataWrapper(QueryMetadataInterface actualMetadata) {
 		this.actualMetadata = actualMetadata;
@@ -355,6 +360,19 @@
 	
 	@Override
 	public QueryMetadataInterface getDesignTimeMetadata() {
+		if (designTime) {
+			return this;
+		}
+		if (designTimeMetadata == null) {
+    		designTimeMetadata = createDesignTimeMetadata();
+    		if (designTimeMetadata instanceof BasicQueryMetadataWrapper) {
+    			((BasicQueryMetadataWrapper)designTimeMetadata).designTime = true;
+    		}
+    	}
+		return designTimeMetadata;
+	}
+	
+	protected QueryMetadataInterface createDesignTimeMetadata() {
 		return actualMetadata.getDesignTimeMetadata();
 	}
 	
@@ -378,5 +396,10 @@
 	public Set<String> getImportedModels() {
 		return actualMetadata.getImportedModels();
 	}
-
+	
+	@Override
+	public ScriptEngine getScriptEngine(String langauge) throws TeiidProcessingException {
+		return actualMetadata.getScriptEngine(langauge);
+	}
+	
 }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/MetadataValidator.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -147,6 +147,8 @@
 	static class ResolveQueryPlans implements MetadataRule {
 		@Override
 		public void execute(VDBMetaData vdb, MetadataStore store, ValidatorReport report, MetadataValidator metadataValidator) {
+			QueryMetadataInterface metadata = vdb.getAttachment(QueryMetadataInterface.class);
+	    	metadata = new TempMetadataAdapter(metadata, new TempMetadataStore());
 			for (Schema schema:store.getSchemaList()) {
 				ModelMetaData model = vdb.getModel(schema.getName());
 
@@ -163,7 +165,7 @@
 							metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31079, t.getName(), model.getName()));
 						}
 						else {
-							metadataValidator.validate(vdb, model, t, report);
+							metadataValidator.validate(vdb, model, t, report, metadata);
 						}
 					}						
 				}
@@ -174,7 +176,7 @@
 							metadataValidator.log(report, model, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31081, p.getName(), model.getName()));
 						}
 						else {
-							metadataValidator.validate(vdb, model, p, report);
+							metadataValidator.validate(vdb, model, p, report, metadata);
 						}
 					}
 				}					
@@ -198,9 +200,7 @@
 		LogManager.log(messageLevel, LogConstants.CTX_QUERY_RESOLVER, msg);
 	}
 	
-    private void validate(VDBMetaData vdb, ModelMetaData model, AbstractMetadataRecord record, ValidatorReport report) {
-    	QueryMetadataInterface metadata = vdb.getAttachment(QueryMetadataInterface.class);
-    	metadata = new TempMetadataAdapter(metadata, new TempMetadataStore()); //TODO: optimize this
+    private void validate(VDBMetaData vdb, ModelMetaData model, AbstractMetadataRecord record, ValidatorReport report, QueryMetadataInterface metadata) {
     	ValidatorReport resolverReport = null;
     	try {
     		if (record instanceof Procedure) {

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -27,8 +27,11 @@
 import java.util.Properties;
 import java.util.Set;
 
+import javax.script.ScriptEngine;
+
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
 import org.teiid.query.function.FunctionLibrary;
 import org.teiid.query.mapping.relational.QueryNode;
 import org.teiid.query.mapping.xml.MappingNode;
@@ -623,6 +626,14 @@
 
     FunctionLibrary getFunctionLibrary();
     
+    /**
+     * 
+     * @param langauge null is treated as the default of 'javascript'
+     * @return the ScriptEngine or null if the ScriptEngine is not available
+     * @throws TeiidProcessingException if the ScriptEngine is required
+     */
+    ScriptEngine getScriptEngine(String langauge) throws TeiidProcessingException;
+    
     Object getPrimaryKey(Object metadataID);
     
     boolean isMultiSource(Object modelId) throws QueryMetadataException, TeiidComponentException;

Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -95,9 +95,14 @@
     	if (isSession()) {
     		return this.actualMetadata.getDesignTimeMetadata();
     	}
-    	return new TempMetadataAdapter(this.actualMetadata.getDesignTimeMetadata(), tempStore, materializationTables, queryNodes);
+    	return super.getDesignTimeMetadata();
     }
     
+    @Override
+    protected QueryMetadataInterface createDesignTimeMetadata() {
+		return new TempMetadataAdapter(this.actualMetadata.getDesignTimeMetadata(), tempStore, materializationTables, queryNodes);
+    }
+    
     public TempMetadataStore getMetadataStore() {
         return this.tempStore;    
     }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TransformationMetadata.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -26,20 +26,17 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import java.util.*;
 
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
 import org.jboss.vfs.VirtualFile;
 import org.teiid.adminapi.impl.VDBMetaData;
 import org.teiid.api.exception.query.QueryMetadataException;
 import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.types.BlobImpl;
 import org.teiid.core.types.ClobImpl;
 import org.teiid.core.types.DataTypeManager;
@@ -68,6 +65,7 @@
 import org.teiid.query.mapping.xml.MappingDocument;
 import org.teiid.query.mapping.xml.MappingLoader;
 import org.teiid.query.mapping.xml.MappingNode;
+import org.teiid.query.sql.lang.ObjectTable;
 import org.teiid.query.sql.lang.SPParameter;
 
 
@@ -159,6 +157,8 @@
     private Map<String, Resource> vdbEntries;
     private FunctionLibrary functionLibrary;
     private VDBMetaData vdbMetaData;
+    private ScriptEngineManager scriptEngineManager;
+    private Set<String> importedModels;
     
     /*
      * TODO: move caching to jboss cache structure
@@ -174,6 +174,12 @@
     public TransformationMetadata(VDBMetaData vdbMetadata, final CompositeMetadataStore store, Map<String, Resource> vdbEntries, FunctionTree systemFunctions, Collection<FunctionTree> functionTrees) {
     	ArgCheck.isNotNull(store);
     	this.vdbMetaData = vdbMetadata;
+    	if (this.vdbMetaData !=null) {
+    		this.scriptEngineManager = vdbMetadata.getAttachment(ScriptEngineManager.class);
+    		this.importedModels = this.vdbMetaData.getImportedModels();
+    	} else {
+    		this.importedModels = Collections.emptySet();
+    	}
         this.store = store;
         if (vdbEntries == null) {
         	this.vdbEntries = Collections.emptyMap();
@@ -188,7 +194,6 @@
     }
     
     private TransformationMetadata(final CompositeMetadataStore store, FunctionLibrary functionLibrary) {
-    	ArgCheck.isNotNull(store);
         this.store = store;
     	this.vdbEntries = Collections.emptyMap();
         this.functionLibrary = functionLibrary;
@@ -1089,14 +1094,37 @@
 		tm.metadataCache = this.metadataCache;
 		tm.partialNameToFullNameCache = this.partialNameToFullNameCache;
 		tm.procedureCache = this.procedureCache; 
+		tm.scriptEngineManager = this.scriptEngineManager;
+		tm.importedModels = this.importedModels;
 		return tm;
 	}
 	
 	@Override
 	public Set<String> getImportedModels() {
-		if (this.vdbMetaData == null) {
-			return Collections.emptySet();
+		return this.importedModels;
+	}
+	
+	@Override
+	public ScriptEngine getScriptEngine(String language) throws TeiidProcessingException {
+		if (this.scriptEngineManager == null) {
+			this.scriptEngineManager = new ScriptEngineManager();
 		}
-		return this.vdbMetaData.getImportedModels();
+		if (language == null) {
+			language = ObjectTable.DEFAULT_LANGUAGE; 
+		}
+		/*
+		 * because of state caching in the engine, we'll return a new instance for each
+		 * usage.  we can pool if needed and add a returnEngine method 
+		 */
+		ScriptEngine engine = this.scriptEngineManager.getEngineByName(language);
+		if (engine == null) {
+			Set<String> names = new LinkedHashSet<String>();
+			for (ScriptEngineFactory factory : this.scriptEngineManager.getEngineFactories()) {
+				names.addAll(factory.getNames());
+			}
+			throw new TeiidProcessingException(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31109, language, names));
+		}
+		return engine;
 	}
+	
 }
\ No newline at end of file

Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -60,6 +60,7 @@
 import org.teiid.query.processor.relational.SortUtility.Mode;
 import org.teiid.query.resolver.util.ResolverUtil;
 import org.teiid.query.sql.lang.*;
+import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
 import org.teiid.query.sql.lang.SetQuery.Operation;
 import org.teiid.query.sql.lang.XMLTable.XMLColumn;
 import org.teiid.query.sql.symbol.ElementSymbol;
@@ -421,7 +422,7 @@
 					//we handle the projection filtering once here rather than repeating the
 					//path analysis on a per plan basis
 					updateGroupName(node, xt);
-					Map elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols());
+					Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(xt.getProjectedSymbols());
 			        List cols = (List) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
 					int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
 					ArrayList<XMLColumn> filteredColumns = new ArrayList<XMLColumn>(projectionIndexes.length);
@@ -434,6 +435,24 @@
 					processNode = xtn;
 					break;
 				}
+				if (source instanceof ObjectTable) {
+					ObjectTable ot = (ObjectTable)source;
+					ObjectTableNode otn = new ObjectTableNode(getID());
+					//we handle the projection filtering once here rather than repeating the
+					//path analysis on a per plan basis
+					updateGroupName(node, ot);
+					Map<Expression, Integer> elementMap = RelationalNode.createLookupMap(ot.getProjectedSymbols());
+			        List<Expression> cols = (List<Expression>) node.getProperty(NodeConstants.Info.OUTPUT_COLS);
+					int[] projectionIndexes = RelationalNode.getProjectionIndexes(elementMap, cols);
+					ArrayList<ObjectColumn> filteredColumns = new ArrayList<ObjectColumn>(projectionIndexes.length);
+					for (int col : projectionIndexes) {
+						filteredColumns.add(ot.getColumns().get(col));
+					}
+					otn.setProjectedColumns(filteredColumns);
+					otn.setTable(ot);
+					processNode = otn;
+					break;
+				}
 				if (source instanceof TextTable) {
 					TextTableNode ttn = new TextTableNode(getID());
 					TextTable tt = (TextTable)source;

Added: trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java	                        (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.processor.relational;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.common.buffer.BlockedException;
+import org.teiid.common.buffer.TupleBatch;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.QueryPlugin;
+import org.teiid.query.eval.Evaluator;
+import org.teiid.query.function.FunctionDescriptor;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.lang.ObjectTable;
+import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
+
+/**
+ * Handles object table processing.
+ */
+public class ObjectTableNode extends SubqueryAwareRelationalNode {
+
+	private static final String TEIID_ROW_COUNT = "teiid_rowcount"; //$NON-NLS-1$
+	private static final String TEIID_ROW = "teiid_row"; //$NON-NLS-1$
+	private static final String TEIID_CONTEXT = "teiid_context"; //$NON-NLS-1$
+	
+	private ObjectTable table;
+	private List<ObjectColumn> projectedColumns;
+	
+	//processing state
+	private int rowCount = 0;
+	private Object item;
+	private Iterator<?> result;
+	private SimpleScriptContext scriptContext;
+	
+	public ObjectTableNode(int nodeID) {
+		super(nodeID);
+	}
+	
+	@Override
+	public void open() throws TeiidComponentException, TeiidProcessingException {
+		super.open();
+		if (table.getScriptEngine() == null) {
+			table.setScriptEngine(getContext().getMetadata().getScriptEngine(table.getScriptingLanguage()));
+		}
+		scriptContext = new SimpleScriptContext();
+		this.scriptContext.setAttribute(TEIID_CONTEXT, this.getContext(), ScriptContext.ENGINE_SCOPE);
+	}
+	
+	@Override
+	public synchronized void closeDirect() {
+		super.closeDirect();
+		reset();
+	}
+	
+	@Override
+	public void reset() {
+		super.reset();
+		item = null;
+		result = null;
+		rowCount = 0;
+		this.scriptContext = null;
+	}
+	
+	public void setTable(ObjectTable table) {
+		this.table = table;
+	}
+	
+	public void setProjectedColumns(List<ObjectColumn> projectedColumns) {
+		this.projectedColumns = projectedColumns;
+	}
+	
+	@Override
+	public ObjectTableNode clone() {
+		ObjectTableNode clone = new ObjectTableNode(getID());
+		this.copyTo(clone);
+		clone.setTable(table);
+		clone.setProjectedColumns(projectedColumns);
+		return clone;
+	}
+
+	@Override
+	protected synchronized TupleBatch nextBatchDirect() throws BlockedException,
+			TeiidComponentException, TeiidProcessingException {
+		
+		evaluate();
+		
+		while (!isBatchFull() && result.hasNext()) {
+			if (item == null) {
+				item = result.next();
+				if (item == null) {
+					continue;
+				}
+				rowCount++;
+			}
+			addBatchRow(processRow());
+		}
+		if (!result.hasNext()) {
+			terminateBatches();
+		}
+		return pullBatch();
+	}
+
+	private void evaluate() throws TeiidComponentException,
+			ExpressionEvaluationException, BlockedException,
+			TeiidProcessingException {
+		if (result != null) {
+			return;
+		}
+		setReferenceValues(this.table);
+		Evaluator eval = getEvaluator(Collections.emptyMap());
+		Object context = eval.evaluateParameters(this.table.getPassing(), null, scriptContext.getBindings(ScriptContext.ENGINE_SCOPE));
+		assert context == null;
+
+		Object value = evalScript(this.table.getCompiledScript(), this.table.getRowScript());
+		if (value instanceof Iterable<?>) {
+			result = ((Iterable<?>)value).iterator();
+		} else if (value instanceof Iterator<?>) {
+			result = (Iterator<?>)value;
+		} else {
+			result = Arrays.asList(value).iterator();
+		}
+	}
+
+	private Object evalScript(CompiledScript compiledScript, String script) throws TeiidProcessingException {
+		try {
+			if (compiledScript != null) {
+				return compiledScript.eval(this.scriptContext);
+			}
+			return this.table.getScriptEngine().eval(script, this.scriptContext);
+		} catch (ScriptException e) {
+			throw new TeiidProcessingException(QueryPlugin.Event.TEIID31110, e, QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31110, script, e.getMessage()));
+		}
+	}
+
+	private List<?> processRow() throws ExpressionEvaluationException,
+			TeiidComponentException, TeiidProcessingException {
+		List<Object> tuple = new ArrayList<Object>(projectedColumns.size());
+		this.scriptContext.setAttribute(TEIID_ROW, this.item, ScriptContext.ENGINE_SCOPE);
+		this.scriptContext.setAttribute(TEIID_ROW_COUNT, this.rowCount, ScriptContext.ENGINE_SCOPE);
+		for (ObjectColumn proColumn : projectedColumns) {
+			Object value = evalScript(proColumn.getCompiledScript(), proColumn.getPath());
+			if (value == null) {
+				if (proColumn.getDefaultExpression() != null) {
+					tuple.add(getEvaluator(Collections.emptyMap()).evaluate(proColumn.getDefaultExpression(), null));
+				} else {
+					tuple.add(null);
+				}
+				continue;
+			}
+			value = FunctionDescriptor.importValue(value, proColumn.getSymbol().getType());
+			tuple.add(value);
+		}
+		item = null;
+		return tuple;
+	}
+
+	@Override
+	protected Collection<? extends LanguageObject> getObjects() {
+		return this.table.getPassing();
+	}
+
+}
\ No newline at end of file


Property changes on: trunk/engine/src/main/java/org/teiid/query/processor/relational/ObjectTableNode.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/RelationalPlan.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -125,6 +125,7 @@
         return this.outputCols;
     }
 
+    @Override
     public void open()
         throws TeiidComponentException, TeiidProcessingException {
     	if (with != null) {

Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/processor/relational/XMLTableNode.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -321,7 +321,7 @@
 				Calendar cal = cv.getCalendar();
 				Date d = cal.getTime();
 				cal.setTimeZone(getContext().getServerTimeZone());
-				return TimestampWithTimezone.createTimestamp(d, TimeZone.getTimeZone("GMT"), cal);
+				return TimestampWithTimezone.createTimestamp(d, TimeZone.getTimeZone("GMT"), cal); //$NON-NLS-1$
 			}
 		}
 		return Value.convertToJava(value);

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/SimpleQueryResolver.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -328,6 +328,26 @@
 			}
         }
         
+        @Override
+        public void visit(ObjectTable obj) {
+        	LinkedHashSet<GroupSymbol> saved = preTableFunctionReference(obj);
+        	visitNodes(obj.getPassing());
+			postTableFunctionReference(obj, saved);
+			try {
+	    		ResolverUtil.setDesiredType(obj.getPassing(), obj, DataTypeManager.DefaultDataClasses.OBJECT);
+				for (ObjectTable.ObjectColumn column : obj.getColumns()) {
+					if (column.getDefaultExpression() == null) {
+						continue;
+					}
+					visitNode(column.getDefaultExpression());
+					Expression ex = ResolverUtil.convertExpression(column.getDefaultExpression(), DataTypeManager.getDataTypeName(column.getSymbol().getType()), metadata);
+					column.setDefaultExpression(ex);
+				}
+			} catch (TeiidException e) {
+				 throw new TeiidRuntimeException(e);
+			}
+        }
+        
         /**
 		 * @param tfr  
 		 */

Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -252,13 +252,14 @@
 
         return conversion;
     }
+
+    public static void setDesiredType(List<DerivedColumn> passing, LanguageObject obj) throws QueryResolverException {
+    	setDesiredType(passing, obj, DataTypeManager.DefaultDataClasses.XML);
+    }
     
-    public static void setDesiredType(List<DerivedColumn> passing, LanguageObject obj) throws QueryResolverException {
+    public static void setDesiredType(List<DerivedColumn> passing, LanguageObject obj, Class<?> type) throws QueryResolverException {
 		for (DerivedColumn dc : passing) {
-			if (dc.getAlias() == null) {
-		    	ResolverUtil.setDesiredType(dc.getExpression(), DataTypeManager.DefaultDataClasses.XML, obj);
-		    	break;
-			}
+	    	ResolverUtil.setDesiredType(dc.getExpression(), type, obj);
 		}
 	}
 

Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -703,9 +703,9 @@
         	TextTable tt = (TextTable)clause;
         	tt.setFile(rewriteExpressionDirect(tt.getFile()));
         } else if (clause instanceof XMLTable) {
-        	XMLTable xt = (XMLTable)clause;
-        	xt.rewriteDefaultColumn();
         	rewriteExpressions(clause);
+        } else if (clause instanceof ObjectTable) {
+        	rewriteExpressions(clause);
         } else if (clause instanceof ArrayTable) {
         	ArrayTable at = (ArrayTable)clause;
         	at.setArrayValue(rewriteExpressionDirect(at.getArrayValue()));

Modified: trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -144,4 +144,5 @@
 	public void visit(WindowSpecification windowSpecification) {}
 
 	public void visit(Array array) {}
+	public void visit(ObjectTable objectTable) {}
 }

Added: trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java	                        (rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership.  Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.sql.lang;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+
+import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.symbol.DerivedColumn;
+import org.teiid.query.sql.symbol.Expression;
+
+public class ObjectTable extends TableFunctionReference {
+	
+	public static final String DEFAULT_LANGUAGE = "javascript"; //$NON-NLS-1$
+	
+	public static class ObjectColumn extends ProjectedColumn {
+		private String path;
+		private Expression defaultExpression;
+		private CompiledScript compiledScript;
+		
+		public ObjectColumn(String name, String type, String path, Expression defaultExpression) {
+			super(name, type);
+			this.path = path;
+			this.defaultExpression = defaultExpression;
+		}
+		
+		protected ObjectColumn() {
+			
+		}
+		
+		public Expression getDefaultExpression() {
+			return defaultExpression;
+		}
+		
+		public void setDefaultExpression(Expression defaultExpression) {
+			this.defaultExpression = defaultExpression;
+		}
+		
+		public String getPath() {
+			return path;
+		}
+		
+		public void setPath(String path) {
+			this.path = path;
+		}
+		
+		public CompiledScript getCompiledScript() {
+			return compiledScript;
+		}
+		
+		public void setCompiledScript(CompiledScript compiledScript) {
+			this.compiledScript = compiledScript;
+		}
+		
+		@Override
+		public boolean equals(Object obj) {
+			if (obj == this) {
+				return true;
+			}
+			if (!super.equals(obj) || !(obj instanceof ObjectColumn)) {
+				return false;
+			}
+			ObjectColumn other = (ObjectColumn)obj;
+			return EquivalenceUtil.areEqual(this.path, other.path)
+				&& EquivalenceUtil.areEqual(this.defaultExpression, other.defaultExpression);
+		}
+		
+		@Override
+		public ObjectColumn clone() {
+			ObjectColumn clone = new ObjectColumn();
+			super.copyTo(clone);
+			clone.path = this.path;
+			if (this.defaultExpression != null) {
+				clone.defaultExpression = (Expression)this.defaultExpression.clone();
+			}
+			clone.compiledScript = this.compiledScript;
+			return clone;
+		}
+	}
+	
+    private List<ObjectColumn> columns = new ArrayList<ObjectColumn>();
+    private String rowScript;
+    private List<DerivedColumn> passing = new ArrayList<DerivedColumn>();
+    private String scriptingLanguage;
+    
+    private CompiledScript compiledScript;
+    private ScriptEngine scriptEngine;
+    
+    public CompiledScript getCompiledScript() {
+		return compiledScript;
+	}
+    
+    public void setCompiledScript(CompiledScript compiledScript) {
+		this.compiledScript = compiledScript;
+	}
+    
+    public String getScriptingLanguage() {
+		return scriptingLanguage;
+	}
+    
+    public void setScriptingLanguage(String scriptingLanguage) {
+		this.scriptingLanguage = scriptingLanguage;
+	}
+    
+    public List<DerivedColumn> getPassing() {
+		return passing;
+	}
+    
+    public void setPassing(List<DerivedColumn> passing) {
+		this.passing = passing;
+	}
+    
+    public String getRowScript() {
+		return rowScript;
+	}
+    
+    public void setRowScript(String query) {
+		this.rowScript = query;
+	}
+    
+    public List<ObjectColumn> getColumns() {
+		return columns;
+	}
+    
+    public void setColumns(List<ObjectColumn> columns) {
+		this.columns = columns;
+	}
+    
+	@Override
+	public void acceptVisitor(LanguageVisitor visitor) {
+		visitor.visit(this);
+	}
+
+	@Override
+	protected ObjectTable cloneDirect() {
+		ObjectTable clone = new ObjectTable();
+		this.copy(clone);
+		for (ObjectColumn column : columns) {
+			clone.getColumns().add(column.clone());
+		}
+		if (this.passing != null) {
+			for (DerivedColumn col : this.passing) {
+				clone.passing.add(col.clone());
+			}
+		}
+		clone.rowScript = this.rowScript;
+		clone.compiledScript = this.compiledScript;
+		return clone;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (obj == this) {
+			return true;
+		}
+		if (!super.equals(obj) || !(obj instanceof ObjectTable)) {
+			return false;
+		}
+		ObjectTable other = (ObjectTable)obj;
+		return this.columns.equals(other.columns) 
+			&& this.rowScript.equals(other.rowScript)
+			&& this.passing.equals(other.passing);
+	}
+
+	public ScriptEngine getScriptEngine() {
+		return scriptEngine;
+	}
+	
+	public void setScriptEngine(ScriptEngine scriptEngine) {
+		this.scriptEngine = scriptEngine;
+	}
+	
+}


Property changes on: trunk/engine/src/main/java/org/teiid/query/sql/lang/ObjectTable.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/XMLTable.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -1,7 +1,6 @@
 package org.teiid.query.sql.lang;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import net.sf.saxon.sxpath.XPathExpression;
@@ -11,7 +10,6 @@
 import org.teiid.core.util.EquivalenceUtil;
 import org.teiid.query.sql.LanguageVisitor;
 import org.teiid.query.sql.symbol.DerivedColumn;
-import org.teiid.query.sql.symbol.ElementSymbol;
 import org.teiid.query.sql.symbol.Expression;
 import org.teiid.query.sql.symbol.XMLNamespaces;
 import org.teiid.query.xquery.saxon.SaxonXQueryExpression;
@@ -104,7 +102,7 @@
     private XMLNamespaces namespaces;
     private String xquery;
     private List<DerivedColumn> passing = new ArrayList<DerivedColumn>();
-    private XMLColumn defaultColumn;
+    private boolean usingDefaultColumn;
     
     private SaxonXQueryExpression xqueryExpression;
     
@@ -113,11 +111,7 @@
 	}
     
     public void compileXqueryExpression() throws TeiidProcessingException {
-    	List<XMLColumn> cols = this.columns;
-    	if (cols.isEmpty()) {
-    		cols = Arrays.asList(defaultColumn);
-    	}
-    	this.xqueryExpression = new SaxonXQueryExpression(xquery, namespaces, passing, cols);
+    	this.xqueryExpression = new SaxonXQueryExpression(xquery, namespaces, passing, this.columns);
     }
     
     public SaxonXQueryExpression getXQueryExpression() {
@@ -141,9 +135,17 @@
 	}
     
     public void setColumns(List<XMLColumn> columns) {
+    	if (columns.isEmpty()) {
+    		usingDefaultColumn = true;
+        	columns.add(new XMLColumn("OBJECT_VALUE", DataTypeManager.DefaultDataTypes.XML, ".", null)); //$NON-NLS-1$ //$NON-NLS-2$
+    	}
 		this.columns = columns;
 	}
     
+    public boolean isUsingDefaultColumn() {
+		return usingDefaultColumn;
+	}
+    
     public XMLNamespaces getNamespaces() {
 		return namespaces;
 	}
@@ -152,17 +154,6 @@
 		this.namespaces = namespaces;
 	}
     
-    @Override
-    public List<ElementSymbol> getProjectedSymbols() {
-    	if (!columns.isEmpty()) {
-        	return super.getProjectedSymbols();
-    	}
-    	if (defaultColumn == null) {
-    		defaultColumn = new XMLColumn("OBJECT_VALUE", DataTypeManager.DefaultDataTypes.XML, ".", null); //$NON-NLS-1$ //$NON-NLS-2$
-    	}
-    	return Arrays.asList(defaultColumn.getSymbol());
-    }
-    
 	@Override
 	public void acceptVisitor(LanguageVisitor visitor) {
 		visitor.visit(this);
@@ -175,9 +166,6 @@
 		for (XMLColumn column : columns) {
 			clone.getColumns().add(column.clone());
 		}
-		if (defaultColumn != null) {
-			clone.defaultColumn = this.defaultColumn;
-		}
 		if (this.namespaces != null) {
 			clone.namespaces = this.namespaces.clone();
 		}
@@ -190,6 +178,7 @@
 		if (this.xqueryExpression != null) {
 			clone.xqueryExpression = this.xqueryExpression.clone();
 		}
+		clone.usingDefaultColumn = usingDefaultColumn;
 		return clone;
 	}
 
@@ -208,11 +197,4 @@
 			&& this.passing.equals(other.passing);
 	}
 
-	public void rewriteDefaultColumn() {
-		if (this.columns.isEmpty() && defaultColumn != null) {
-			this.columns.add(defaultColumn);
-			defaultColumn = null;
-		}
-	}
-	
 }

Modified: trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -503,6 +503,17 @@
     }
     
     @Override
+    public void visit(ObjectTable obj) {
+    	preVisitVisitor(obj);
+    	visitNodes(obj.getPassing());
+    	for (ObjectTable.ObjectColumn column : obj.getColumns()) {
+			visitNode(column.getDefaultExpression());
+		}
+        visitNode(obj.getGroupSymbol());
+        postVisitVisitor(obj);
+    }
+    
+    @Override
     public void visit(XMLQuery obj) {
     	preVisitVisitor(obj);
     	visitNode(obj.getNamespaces());

Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -34,6 +34,7 @@
 import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.LanguageVisitor;
 import org.teiid.query.sql.lang.*;
+import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
 import org.teiid.query.sql.lang.XMLTable.XMLColumn;
 import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
 import org.teiid.query.sql.navigator.PreOrderNavigator;
@@ -111,6 +112,16 @@
     }
     
     @Override
+    public void visit(ObjectTable obj) {
+    	for (ObjectColumn col : obj.getColumns()) {
+    		Expression exp = col.getDefaultExpression();
+    		if (exp != null) {
+    			col.setDefaultExpression(replaceExpression(exp));
+    		}
+		}
+    }
+    
+    @Override
     public void visit(XMLSerialize obj) {
     	obj.setExpression(replaceExpression(obj.getExpression()));
     }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -41,6 +41,7 @@
 import org.teiid.query.sql.LanguageVisitor;
 import org.teiid.query.sql.lang.*;
 import org.teiid.query.sql.lang.ExistsCriteria.SubqueryHint;
+import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
 import org.teiid.query.sql.lang.TableFunctionReference.ProjectedColumn;
 import org.teiid.query.sql.lang.TextTable.TextColumn;
 import org.teiid.query.sql.lang.XMLTable.XMLColumn;
@@ -1778,7 +1779,7 @@
             append(SPACE);
             registerNodes(obj.getPassing(), 0);
         }
-        if (!obj.getColumns().isEmpty()) {
+        if (!obj.getColumns().isEmpty() && !obj.isUsingDefaultColumn()) {
             append(SPACE);
             append(NonReserved.COLUMNS);
             for (Iterator<XMLColumn> cols = obj.getColumns().iterator(); cols.hasNext();) {
@@ -1818,6 +1819,50 @@
     }
 
     @Override
+    public void visit( ObjectTable obj ) {
+        addHintComment(obj);
+        append("OBJECTTABLE("); //$NON-NLS-1$
+        if (obj.getScriptingLanguage() != null) {
+        	append(LANGUAGE);
+            append(SPACE);
+            visitNode(new Constant(obj.getScriptingLanguage()));
+            append(SPACE);
+        }
+        visitNode(new Constant(obj.getRowScript()));
+        if (!obj.getPassing().isEmpty()) {
+            append(SPACE);
+            append(NonReserved.PASSING);
+            append(SPACE);
+            registerNodes(obj.getPassing(), 0);
+        }
+        append(SPACE);
+        append(NonReserved.COLUMNS);
+        for (Iterator<ObjectColumn> cols = obj.getColumns().iterator(); cols.hasNext();) {
+        	ObjectColumn col = cols.next();
+            append(SPACE);
+            outputDisplayName(col.getName());
+            append(SPACE);
+            append(col.getType());
+            append(SPACE);
+            visitNode(new Constant(col.getPath()));
+            if (col.getDefaultExpression() != null) {
+                append(SPACE);
+                append(DEFAULT);
+                append(SPACE);
+                visitNode(col.getDefaultExpression());
+            }
+            if (cols.hasNext()) {
+                append(","); //$NON-NLS-1$
+            }
+        }
+        append(")");//$NON-NLS-1$
+        append(SPACE);
+        append(AS);
+        append(SPACE);
+        outputDisplayName(obj.getName());
+    }
+    
+    @Override
     public void visit( XMLQuery obj ) {
         append("XMLQUERY("); //$NON-NLS-1$
         if (obj.getNamespaces() != null) {

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -31,7 +31,12 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 
+import javax.script.Compilable;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+
 import net.sf.saxon.om.Name11Checker;
 import net.sf.saxon.om.QNameException;
 import net.sf.saxon.trans.XPathException;
@@ -44,6 +49,7 @@
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.types.DataTypeManager;
 import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.language.SQLConstants;
 import org.teiid.metadata.AggregateAttributes;
 import org.teiid.query.QueryPlugin;
 import org.teiid.query.eval.Evaluator;
@@ -57,6 +63,7 @@
 import org.teiid.query.resolver.util.ResolverUtil;
 import org.teiid.query.sql.LanguageObject;
 import org.teiid.query.sql.lang.*;
+import org.teiid.query.sql.lang.ObjectTable.ObjectColumn;
 import org.teiid.query.sql.lang.SetQuery.Operation;
 import org.teiid.query.sql.lang.XMLTable.XMLColumn;
 import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
@@ -1191,6 +1198,45 @@
     }
     
     @Override
+    public void visit(ObjectTable obj) {
+    	List<DerivedColumn> passing = obj.getPassing();
+    	TreeSet<String> names = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
+    	for (DerivedColumn dc : passing) {
+    		if (dc.getAlias() == null) {
+				handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.context_item_not_allowed"), obj); //$NON-NLS-1$
+        	} else if (!names.add(dc.getAlias())) {
+    			handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.duplicate_passing", dc.getAlias()), obj); //$NON-NLS-1$
+        	}
+		}
+    	Compilable scriptCompiler = null;
+    	try {
+			ScriptEngine engine = this.getMetadata().getScriptEngine(obj.getScriptingLanguage());
+			obj.setScriptEngine(engine);
+			if (engine instanceof Compilable) {
+				scriptCompiler = (Compilable)engine;
+				engine.put(ScriptEngine.FILENAME, SQLConstants.NonReserved.OBJECTTABLE);
+				obj.setCompiledScript(scriptCompiler.compile(obj.getRowScript()));
+			}
+		} catch (TeiidProcessingException e) {
+			handleValidationError(e.getMessage(), obj);
+		} catch (ScriptException e) {
+			handleValidationError(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31110, obj.getRowScript(), e.getMessage()), obj); //$NON-NLS
+		}
+    	for (ObjectColumn xc : obj.getColumns()) {
+    		if (scriptCompiler != null) {
+    			try {
+					xc.setCompiledScript(scriptCompiler.compile(xc.getPath()));
+				} catch (ScriptException e) {
+					handleValidationError(QueryPlugin.Util.gs(QueryPlugin.Event.TEIID31110, xc.getPath(), e.getMessage()), obj); //$NON-NLS
+				}
+    		}
+			if (xc.getDefaultExpression() != null && !EvaluatableVisitor.isFullyEvaluatable(xc.getDefaultExpression(), false)) {
+				handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.invalid_default", xc.getDefaultExpression()), obj); //$NON-NLS-1$
+			}
+		}
+    }
+    
+    @Override
     public void visit(XMLQuery obj) {
     	validatePassing(obj, obj.getXQueryExpression(), obj.getPassing());
     }
@@ -1198,7 +1244,7 @@
 	private void validatePassing(LanguageObject obj, SaxonXQueryExpression xqe, List<DerivedColumn> passing) {
 		boolean context = false;
     	boolean hadError = false;
-    	HashSet<String> names = new HashSet<String>();
+    	TreeSet<String> names = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
     	for (DerivedColumn dc : passing) {
     		if (dc.getAlias() == null) {
     			Class<?> type = dc.getExpression().getType();
@@ -1212,7 +1258,7 @@
     			context = true;
         	} else { 
         		validateXMLContentTypes(dc.getExpression(), obj);
-        		if (!names.add(dc.getAlias().toUpperCase())) {
+        		if (!names.add(dc.getAlias())) {
         			handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.duplicate_passing", dc.getAlias()), obj); //$NON-NLS-1$
         		}
         	}

Modified: trunk/engine/src/main/java/org/teiid/query/xquery/saxon/XQueryEvaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/xquery/saxon/XQueryEvaluator.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/java/org/teiid/query/xquery/saxon/XQueryEvaluator.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -41,6 +41,7 @@
 import net.sf.saxon.om.NodeInfo;
 import net.sf.saxon.query.DynamicQueryContext;
 import net.sf.saxon.trans.XPathException;
+import net.sf.saxon.value.HexBinaryValue;
 import nu.xom.Builder;
 import nu.xom.DocType;
 import nu.xom.Element;
@@ -53,6 +54,7 @@
 import org.teiid.core.TeiidComponentException;
 import org.teiid.core.TeiidProcessingException;
 import org.teiid.core.TeiidRuntimeException;
+import org.teiid.core.types.BinaryType;
 import org.teiid.logging.LogConstants;
 import org.teiid.logging.LogManager;
 import org.teiid.logging.MessageLevel;
@@ -90,6 +92,8 @@
 		            	value = wrapStax((Source)value, xquery.getConfig());
 		            } else if (value instanceof java.util.Date) {
 		            	value = XMLSystemFunctions.convertToAtomicValue(value);
+		            } else if (value instanceof BinaryType) {
+		            	value = new HexBinaryValue(((BinaryType)value).getBytesDirect());
 		            }
 		            dynamicContext.setParameter(entry.getKey(), value);                
 		        }

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj	2012-08-23 16:43:06 UTC (rev 4361)
@@ -449,6 +449,7 @@
 |   <QUOTE: "quote">
 |   <HEADER: "header">
 |   <NULLS: "nulls">
+|   <OBJECTTABLE: "objecttable">
 
 }
 /*
@@ -551,7 +552,7 @@
 {
 }
 {
-    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<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>)
+    (<INSTEAD>|<VIEW>|<ENABLED>|<DISABLED>|<KEY>|<SERIAL>|<TEXTAGG>|<COUNT>|<ROW_NUMBER>|<RANK>|<DENSE_RANK>|<SUM>|<AVG>|<MIN>|<MAX>|<EVERY>|<STDDEV_POP>|<STDDEV_SAMP>|<VAR_SAMP>|<VAR_POP>|<DOCUMENT>|<CONTENT>|<TRIM>|<EMPTY>|<ORDINALITY>|<PATH>|<FIRST>|<LAST>|<NEXT>|<SUBSTRING>|<EXTRACT>|<TO_CHARS>|<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>)
     {
     	return getToken(0);
     }	
@@ -2294,6 +2295,8 @@
 	    |
 	    clause = xmlTable(info)
 	    |
+	    LOOKAHEAD(2) clause = objectTable(info)
+	    |
 	    clause = unaryFromClause(info)
 		|
 		LOOKAHEAD(subqueryFromClause(info)) clause = subqueryFromClause(info) 
@@ -2555,6 +2558,89 @@
 }
 
 /*
+name=object table
+description=Returns table results by processing a script.
+example={code:sql}OBJECTTABLE('z' PASSING val AS z COLUMNS col OBJECT 'teiid_row') AS X{code}
+*/
+ObjectTable objectTable(ParseInfo info) :
+{
+	String rowScript = null;
+	String lang = null;
+	DerivedColumn passing = null;
+	ArrayList<DerivedColumn> passingValues = new ArrayList<DerivedColumn>();
+	ObjectTable.ObjectColumn column = null;
+	ArrayList<ObjectTable.ObjectColumn> columns = new ArrayList<ObjectTable.ObjectColumn>();
+	String aliasID = null;
+}
+{
+ 	<OBJECTTABLE> <LPAREN> 
+ 	[<LANGUAGE> lang = stringVal()]
+ 	rowScript = stringVal()
+ 	[ 
+ 	  <PASSING>
+ 	  passing = derivedColumn(info)
+ 	  {
+ 	  	passingValues.add(passing);
+ 	  	passing.setPropagateName(false);
+ 	  }
+ 	  (<COMMA>
+ 	    passing = derivedColumn(info)
+ 	    {
+ 	  	  passingValues.add(passing);
+ 	  	  passing.setPropagateName(false);
+ 	    }
+ 	  )*
+ 	]
+    <COLUMNS>
+    column = objectColumn(info)
+    {
+      columns.add(column);
+    }
+    (<COMMA>
+      column = objectColumn(info)
+      {
+        columns.add(column);
+      }
+    )*
+ 	<RPAREN>
+ 	[<AS>] aliasID=id()
+ 	{
+ 		ObjectTable result = new ObjectTable();
+ 		result.setScriptingLanguage(lang);
+ 		result.setRowScript(rowScript);
+ 		result.setPassing(passingValues);
+ 		result.setColumns(columns);
+ 		result.setName(validateAlias(aliasID));
+ 		return result;
+ 	}
+}
+
+/*
+name=object table column
+description=object table column.
+example={code:sql}y integer 'teiid_rowcount'{code}
+*/
+ObjectTable.ObjectColumn objectColumn(ParseInfo info):
+{
+	String name = null;
+	ParsedDataType datatype = null;
+	String path = null;
+	Expression defaultExpr = null;
+}
+{
+	name = id()
+    datatype = parseDataType()
+	path = stringVal()    
+    [
+   	  <DEFAULT_KEYWORD> defaultExpr = expression(info)
+	]
+	{
+	  return new ObjectTable.ObjectColumn(name, datatype.type, path, defaultExpr);
+	}
+}
+
+
+/*
 name=xml table
 description=Returns table results by processing an XQuery.
 example={code:sql}XMLTABLE('/a/b' PASSING doc COLUMNS col XML PATH '.') AS X{code}

Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties	2012-08-23 16:43:06 UTC (rev 4361)
@@ -719,9 +719,10 @@
 ValidationVisitor.xml_invalid_qname=The qname "{0}" is invalid.
 ValidationVisitor.context_item_type=XMLTABLE or XMLQUERY PASSING context item must be an XML value.
 ValidationVisitor.passing_requires_name=XMLTABLE or XMLQUERY PASSING clause can only contain at most 1 unnamed item.
-ValidationVisitor.duplicate_passing=XMLTABLE or XMLQUERY PASSING clause duplicate item name "{0}".
+ValidationVisitor.duplicate_passing=XMLTABLE, XMLQUERY, or OBJECTTABLE PASSING clause duplicate item name "{0}".
+ValidationVisitor.ValidationVisitor.context_item_not_allowed=OBJECTTABLE does not support passing unnamed items.
 ValidationVisitor.one_ordinal=Only one FOR ORDINALITY column is allowed for an XMLTABLE.
-ValidationVisitor.invalid_default=XMLTABLE DEFAULT expression is invalid: "{0}"
+ValidationVisitor.invalid_default=XMLTABLE or OBJECTTABLE DEFAULT expression is invalid: "{0}"
 ValidationVisitor.context_required=The XQuery requires a context item, but none exists in the PASSING clause.
 ValidationVisitor.xmlparse_type=XMLPARSE expects a STRING, CLOB, or BLOB value.
 ValidationVisitor.invalid_encoding=Encoding {0} is not valid.
@@ -1022,6 +1023,8 @@
 TEIID31105=Returing warning to client: {0}
 TEIID31106=Duplicate parameter {1} defined on {0}
 TEIID31107=Procedure {0} can only have 1 RESULT/return value
+TEIID31109=Invalid language {0}.  Supported language names are {1}.
+TEIID31109=Invalid script {0}.  Scrpting engine reported: {1}.
 
 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/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -5068,6 +5068,11 @@
         helpTest(sql, "SELECT * FROM XMLTABLE(XMLNAMESPACES(NO DEFAULT), '/' COLUMNS x FOR ORDINALITY, y date DEFAULT {d'2000-01-01'} PATH '@date') AS x", query);
     }
     
+    @Test public void testObjectTable() throws Exception {
+    	Query actualCommand = (Query)QueryParser.getQueryParser().parseCommand("SELECT * from objecttable(LANGUAGE 'foo' 'x' columns y date 'row.date' default {d'2000-01-01'}) as x", new ParseInfo());
+		assertEquals("SELECT * FROM OBJECTTABLE(LANGUAGE 'foo' 'x' COLUMNS y date 'row.date' DEFAULT {d'2000-01-01'}) AS x", actualCommand.toString());
+    }
+    
     @Test public void testXmlSerialize() throws Exception {
     	XMLSerialize f = new XMLSerialize();
     	f.setDocument(true);

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-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestResolver.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -169,27 +169,11 @@
 
         CheckSymbolsAreResolvedVisitor vis = new CheckSymbolsAreResolvedVisitor();
         DeepPreOrderNavigator.doVisit(command, vis);
-        Collection unresolvedSymbols = vis.getUnresolvedSymbols();
+        Collection<LanguageObject> unresolvedSymbols = vis.getUnresolvedSymbols();
         assertTrue("Found unresolved symbols: " + unresolvedSymbols, unresolvedSymbols.isEmpty()); //$NON-NLS-1$
         return command; 
 	}		
 
-	/**
-	 * Expect a QueryResolverException (not any other kind of Throwable)
-	 */
-	private void helpResolveFails(Command command) {
-		// resolve
-		QueryResolverException exception = null;
-		try {
-			QueryResolver.resolveCommand(command, metadata);
-		} catch(QueryResolverException e) {
-			exception = e;
-		} catch(TeiidException e) {
-			fail("Exception during resolution (" + e.getClass().getName() + "): " + e.getMessage()); //$NON-NLS-1$ //$NON-NLS-2$
-		}
-		assertNotNull("Expected a QueryResolverException but got none.", exception); //$NON-NLS-1$
-	}
-
     private Criteria helpResolveCriteria(String sql) { 
         Criteria criteria = null;
         
@@ -211,7 +195,7 @@
 
         CheckSymbolsAreResolvedVisitor vis = new CheckSymbolsAreResolvedVisitor();
         DeepPreOrderNavigator.doVisit(criteria, vis);
-        Collection unresolvedSymbols = vis.getUnresolvedSymbols();
+        Collection<LanguageObject> unresolvedSymbols = vis.getUnresolvedSymbols();
         assertTrue("Found unresolved symbols: " + unresolvedSymbols, unresolvedSymbols.isEmpty()); //$NON-NLS-1$
         return criteria;
     }
@@ -229,7 +213,7 @@
         CheckSymbolsAreResolvedVisitor vis = new CheckSymbolsAreResolvedVisitor();
         DeepPreOrderNavigator.doVisit(command, vis);
 
-        Collection unresolvedSymbols = vis.getUnresolvedSymbols();
+        Collection<LanguageObject> unresolvedSymbols = vis.getUnresolvedSymbols();
         assertTrue("Found unresolved symbols: " + unresolvedSymbols, unresolvedSymbols.isEmpty()); //$NON-NLS-1$
         return command;
     }
@@ -331,27 +315,22 @@
 
         StoredProcedure proc = (StoredProcedure)helpResolve(sql);
         
-        List params = proc.getParameters();
+        List<SPParameter> params = proc.getParameters();
 
-        // Remove all but IN and IN/OUT params
-        Iterator paramIter = params.iterator();
-        while (paramIter.hasNext()) {
-            final SPParameter param = (SPParameter)paramIter.next();
-            if (param.getParameterType() != ParameterInfo.IN && param.getParameterType() != ParameterInfo.INOUT) {
-                paramIter.remove();
-            }
-        }
-
         // Check remaining params against expected expressions
-        assertEquals(expectedParameterExpressions.length, params.size());
-        for (int i=0; i<expectedParameterExpressions.length; i++) {
-            SPParameter param = (SPParameter)params.get(i);
+        int i = 0;
+        for (SPParameter param : params) {
+        	if (param.getParameterType() != SPParameter.IN && param.getParameterType() != SPParameter.INOUT) {
+        		continue;
+        	}
             if (expectedParameterExpressions[i] == null) {
                 assertNull(param.getExpression());
             } else {
                 assertEquals(expectedParameterExpressions[i], param.getExpression());
             }
+            i++;
         }
+        assertEquals(expectedParameterExpressions.length, i);
         
         return proc;
     }
@@ -932,13 +911,13 @@
         Query resolvedQuery = (Query) helpResolve("select * from (EXEC pm1.sq2('abc')) as x"); //$NON-NLS-1$
         helpCheckFrom(resolvedQuery, new String[] { "x" }); //$NON-NLS-1$
         
-        List elements = (List) ElementCollectorVisitor.getElements(resolvedQuery.getSelect(), false);
+        List<ElementSymbol> elements = (List<ElementSymbol>) ElementCollectorVisitor.getElements(resolvedQuery.getSelect(), false);
         
-        ElementSymbol elem1 = (ElementSymbol)elements.get(0);
+        ElementSymbol elem1 = elements.get(0);
         assertEquals("Did not get expected element", "x.e1", elem1.getName() ); //$NON-NLS-1$ //$NON-NLS-2$
         assertEquals("Did not get expected type", DataTypeManager.DefaultDataClasses.STRING, elem1.getType()); //$NON-NLS-1$
 
-        ElementSymbol elem2 = (ElementSymbol)elements.get(1);
+        ElementSymbol elem2 = elements.get(1);
         assertEquals("Did not get expected element", "x.e2", elem2.getName() ); //$NON-NLS-1$ //$NON-NLS-2$
         assertEquals("Did not get expected type", DataTypeManager.DefaultDataClasses.INTEGER, elem2.getType()); //$NON-NLS-1$
     }
@@ -2355,7 +2334,7 @@
         String update1 = "update pm1.g1 set e1 =1"; //$NON-NLS-1$
         String update2 = "update pm2.g1 set e1 =1"; //$NON-NLS-1$
         
-        List commands = new ArrayList();
+        List<Command> commands = new ArrayList<Command>();
         commands.add(QueryParser.getQueryParser().parseCommand(update1));
         commands.add(QueryParser.getQueryParser().parseCommand(update2));
         BatchedUpdateCommand command = new BatchedUpdateCommand(commands);
@@ -2438,11 +2417,11 @@
          
         StoredProcedure proc = (StoredProcedure)helpResolve(query); 
         
-        List projected = proc.getProjectedSymbols();
+        List<Expression> projected = proc.getProjectedSymbols();
         
         assertEquals(2, projected.size());
         
-        for (Iterator i = projected.iterator(); i.hasNext();) {
+        for (Iterator<Expression> i = projected.iterator(); i.hasNext();) {
             ElementSymbol symbol = (ElementSymbol)i.next();
             assertNotNull(symbol.getGroupSymbol());
         }
@@ -2923,6 +2902,10 @@
     	helpResolve("select * from xmltable('/a' passing ?) as x");
     }
     
+    @Test public void testObjectTableWithParam() {
+    	helpResolve("select * from objecttable('x + 1' passing ? as x columns obj OBJECT '') as y");
+    }
+    
     @Test public void testXmlQueryWithParam() {
     	Query q = (Query)helpResolve("select xmlquery('/a' passing ?)");
     	XMLQuery ex = (XMLQuery) SymbolMap.getExpression(q.getSelect().getSymbols().get(0));

Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -1576,6 +1576,22 @@
     @Test public void testXMLTableContextRequired() {
     	helpValidate("select * from xmltable('/a/b' passing convert('<a/>', xml) as a columns x for ordinality, c integer path '.') as x", new String[] {"XMLTABLE('/a/b' PASSING convert('<a/>', xml) AS a COLUMNS x FOR ORDINALITY, c integer PATH '.') AS x"}, RealMetadataFactory.example1Cached());
     }
+    
+    @Test public void testObjectTablePassing() {
+    	helpValidate("select * from objecttable('x' passing 'a' columns c integer 'row') as x", new String[] {"OBJECTTABLE('x' PASSING 'a' COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
+    }
+    
+    @Test public void testObjectTablePassingSameName() {
+    	helpValidate("select * from objecttable('x' passing 'a' AS X, 'b' AS x columns c integer 'row') as x", new String[] {"OBJECTTABLE('x' PASSING 'a' AS X, 'b' AS x COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
+    }
+    
+    @Test public void testObjectTableLanguage() {
+    	helpValidate("select * from objecttable(language 'foo!' 'x' columns c integer 'row') as x", new String[] {"OBJECTTABLE(LANGUAGE 'foo!' 'x' COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
+    }
+    
+    @Test public void testObjectTableScript() {
+    	helpValidate("select * from objecttable('this is not valid' columns c integer 'row') as x", new String[] {"OBJECTTABLE('this is not valid' COLUMNS c integer 'row') AS x"}, RealMetadataFactory.example1Cached());
+    }
 
     @Test public void testXMLQueryPassingContextType() {
     	helpValidate("select xmlquery('/' passing 2)", new String[] {"XMLQUERY('/' PASSING 2)"}, RealMetadataFactory.example1Cached());

Modified: trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java
===================================================================
--- trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java	2012-08-23 15:03:42 UTC (rev 4360)
+++ trunk/jboss-integration/src/main/java/org/teiid/jboss/VDBDeployer.java	2012-08-23 16:43:06 UTC (rev 4361)
@@ -29,6 +29,8 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
+import javax.script.ScriptEngineManager;
+
 import org.jboss.as.controller.ModelController;
 import org.jboss.as.naming.deployment.ContextNames;
 import org.jboss.as.server.Services;
@@ -38,7 +40,16 @@
 import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.modules.Module;
-import org.jboss.msc.service.*;
+import org.jboss.modules.ModuleClassLoader;
+import org.jboss.msc.service.AbstractServiceListener;
+import org.jboss.msc.service.Service;
+import org.jboss.msc.service.ServiceBuilder;
+import org.jboss.msc.service.ServiceController;
+import org.jboss.msc.service.ServiceName;
+import org.jboss.msc.service.ServiceTarget;
+import org.jboss.msc.service.StartContext;
+import org.jboss.msc.service.StartException;
+import org.jboss.msc.service.StopContext;
 import org.jboss.msc.service.ServiceBuilder.DependencyType;
 import org.jboss.msc.service.ServiceController.Mode;
 import org.jboss.msc.service.ServiceController.State;
@@ -121,7 +132,9 @@
 		}
 		
 		// add VDB module's classloader as an attachment
-		deployment.addAttchment(ClassLoader.class, deploymentUnit.getAttachment(Attachments.MODULE).getClassLoader());
+		ModuleClassLoader classLoader = deploymentUnit.getAttachment(Attachments.MODULE).getClassLoader();
+		deployment.addAttchment(ClassLoader.class, classLoader);
+		deployment.addAttchment(ScriptEngineManager.class, new ScriptEngineManager(classLoader));
 		
 		// check if this is a VDB with index files, if there are then build the TransformationMetadata
 		UDFMetaData udf = deploymentUnit.removeAttachment(TeiidAttachments.UDF_METADATA);



More information about the teiid-commits mailing list