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);