[teiid-commits] teiid SVN: r2869 - in trunk: build/kits/jboss-container and 15 other directories.
teiid-commits at lists.jboss.org
teiid-commits at lists.jboss.org
Fri Jan 21 10:59:54 EST 2011
Author: shawkins
Date: 2011-01-21 10:59:53 -0500 (Fri, 21 Jan 2011)
New Revision: 2869
Modified:
trunk/COPYRIGHT.txt
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java
trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/processor/TestProcedureRelational.java
trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-946 adding support for inout/out/return parameters to have values assigned.
Modified: trunk/COPYRIGHT.txt
===================================================================
--- trunk/COPYRIGHT.txt 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/COPYRIGHT.txt 2011-01-21 15:59:53 UTC (rev 2869)
@@ -1,4 +1,4 @@
-Portions Copyright (C) 2008-2009 Red Hat, Inc.
+Portions Copyright (C) 2008-2011 Red Hat, Inc.
Portions Copyright (C) 2000-2007 MetaMatrix, Inc.
Portions Copyright (c) 2000, 2003, 2008 IBM Corporation and others.
Portions Copyright (c) 1997-2000 Sun Microsystems, Inc.
\ No newline at end of file
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2011-01-21 15:59:53 UTC (rev 2869)
@@ -26,21 +26,7 @@
</UL>
<H2><A NAME="Highlights"></A>Highlights</H2>
<UL>
- <LI><B>Subquery Optimization</B> - added rewrite to INNER JOIN for applicable WHERE clause subqueries. Also added cost based SEMI and ANTI-SEMI join handling for applicable non-pushed WHERE and HAVING subqueries.
- <LI><B>Updatable Views</B>
- <UL>
- <LI>Added support to perform simple pass-through and more complicated updates through views by default.
- <LI>Added support for "FOR EACH ROW" update procedure handling (similar to INSTEAD OF triggers in other DBMS's), which should be used instead of the deprecated TRANSLATE criteria approach.
- </UL>
- <LI><B>Temp table enhancements</B> - added support for the SERIAL datatype, which is a not null INTEGER that auto-increments, and the ability to specify a column as NOT NULL.
- <LI><B>UDF</B> - new API objects added to teiid-api to support user defined functions that are capable of pushdown to source.
- <LI><B>Unescape Function</B> - a new system function, unescape, was added to handle common \ escaping in strings including octal, hex/unicode, \b, \r, \n, \f, and \t.
- <LI><B>Predicate Optimization</B> - expanded optimizations for detecting always false conditions when using IS NULL, IN, or comparison predicates with literal values.
- <LI><B>Partition-wise Optimizations</B> - Views defined by partitioned unions (union alls where each branch has a projected literal or an IN predicate that makes its values mutually exclusive from the other branches) can
- be used in aggregation or joins and the optimizer will take advantage of the partitioning information. For example, when a partitioned union is joined against another partitioned union, the optimizer will reorganize the join of unions into a union of joins.
- <LI><B>Delegate Translator</B> - A new translator base class was added that is capable of delegating all the calls to another configured translator.
- <LI><B>JDBC Reauthentication</B> - Teiid connections (defined by the org.teiid.jdbc.TeiidConnection interface) now support the changeUser method to reauthenticate a given connection.
- <LI><B>Lob Caching</B> - Lobs are allowed to cache to disk as part of ResultSet caching. Distributed lob caching is not allowed.
+ <LI><B>Virtual procedure out params</B> - virtual procedures can now have RETURN/OUT/INOUT parameters to return values.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/procedures.xml 2011-01-21 15:59:53 UTC (rev 2869)
@@ -305,8 +305,9 @@
expected result set and parameters of the procedure.</para>
</section>
<section>
- <title>Procedure Input Parameters</title>
- <para>Virtual procedures can take zero or more input parameters. Each input has the following information that is used during runtime processing: </para>
+ <title>Procedure Parameters</title>
+ <para>Virtual procedures can take zero or more IN/INOUT parameters and may also have any number of OUT parameters and an optional RETURN parameter.
+ Each input has the following information that is used during runtime processing: </para>
<itemizedlist>
<listitem>
<para>Name - The name of the input parameter</para>
@@ -321,16 +322,20 @@
<para>Nullable - NO_NULLS, NULLABLE, NULLABLE_UNKNOWN; parameter is optional if nullable, and is not required to be listed when using named parameter syntax</para>
</listitem>
</itemizedlist>
- <para>You reference an input to a virtual procedure by using the fully-qualified name of the param (or less if unambiguous). For example, MySchema.MyProc.Param1.
+ <para>You reference a parameter in a virtual procedure by using the fully-qualified name of the param (or less if unambiguous). For example, MySchema.MyProc.Param1.
</para>
<example>
- <title>Example of Referencing an Input Parameter for 'GetBalance' Procedure</title>
+ <title>Example of Referencing an Input Parameter and Assigning an Out Parameter for 'GetBalance' Procedure</title>
<programlisting>
CREATE VIRTUAL PROCEDURE
BEGIN
+ MySchema.GetBalance.RetVal = UPPER(MySchema.GetBalance.AcctID);
SELECT Balance FROM MySchema.Accts WHERE MySchema.Accts.AccountID = MySchema.GetBalance.AcctID;
END</programlisting>
</example>
+ <para>If an INOUT parameter is not assigned any value in a procedure it will remain the value it was assigned for input.
+ Any OUT/RETURN parameter not assigned a value will remain the as the default NULL value.
+ The INOUT/OUT/RETURN output values are validated against the NOT NULL metadata of the parameter.</para>
</section>
<section>
<title>Example Virtual Procedures</title>
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -323,7 +323,7 @@
// Validate with visitor
ValidatorReport report = Validator.validate(command, metadata, visitor);
if (report.hasItems()) {
- ValidatorFailure firstFailure = (ValidatorFailure) report.getItems().iterator().next();
+ ValidatorFailure firstFailure = report.getItems().iterator().next();
throw new QueryValidatorException(firstFailure.getMessage());
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataAdapter.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -340,10 +340,15 @@
case SupportConstants.Element.NULL: {
if (id.isNotNull()) {
return false;
+ }
+ if (id.isTempTable()) {
+ return true;
}
break;
}
case SupportConstants.Element.AUTO_INCREMENT: return id.isAutoIncrement();
+ case SupportConstants.Element.UPDATE: return id.isTempTable() || id.isUpdatable();
+
}
// If this is a temp table column or real metadata is unknown, return hard-coded values
@@ -351,7 +356,6 @@
if(elementID == null || id.isTempTable()) {
switch(supportConstant) {
case SupportConstants.Element.NULL: return true;
- case SupportConstants.Element.UPDATE: return true;
case SupportConstants.Element.SIGNED: return true;
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/TempMetadataID.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -78,6 +78,7 @@
private Class<?> type; // type of this element, only for element
private boolean autoIncrement;
private boolean notNull;
+ private boolean updatable;
/**
* Constructor for group form of metadata ID.
@@ -273,6 +274,10 @@
public void setMetadataType(Type metadataType) {
this.metadataType = metadataType;
}
+
+ public Type getMetadataType() {
+ return metadataType;
+ }
public List<TempMetadataID> getPrimaryKey() {
return getTableData().primaryKey;
@@ -350,5 +355,13 @@
public void setNotNull(boolean notNull) {
this.notNull = notNull;
}
+
+ public void setUpdatable(boolean updatable) {
+ this.updatable = updatable;
+ }
+
+ public boolean isUpdatable() {
+ return updatable;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -23,6 +23,8 @@
package org.teiid.query.optimizer;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -50,6 +52,7 @@
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.ProcedureContainer;
import org.teiid.query.sql.lang.Query;
+import org.teiid.query.sql.lang.SPParameter;
import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.lang.TranslatableProcedureContainer;
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
@@ -129,6 +132,24 @@
LinkedHashMap<ElementSymbol, Expression> params = container.getProcedureParameters();
if (container instanceof StoredProcedure) {
plan.setRequiresTransaction(container.getUpdateCount() > 0);
+ StoredProcedure sp = (StoredProcedure)container;
+ if (sp.returnParameters()) {
+ List<ElementSymbol> outParams = new LinkedList<ElementSymbol>();
+ for (SPParameter param : sp.getParameters()) {
+ if (param.getParameterType() == SPParameter.RETURN_VALUE) {
+ outParams.add(param.getParameterSymbol());
+ }
+ }
+ for (SPParameter param : sp.getParameters()) {
+ if (param.getParameterType() == SPParameter.INOUT ||
+ param.getParameterType() == SPParameter.OUT) {
+ outParams.add(param.getParameterSymbol());
+ }
+ }
+ if (outParams.size() > 0) {
+ plan.setOutParams(outParams);
+ }
+ }
}
plan.setParams(params);
plan.setMetadata(metadata);
Modified: trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/processor/proc/ProcedurePlan.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -25,10 +25,10 @@
import static org.teiid.query.analysis.AnalysisRecord.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -36,6 +36,7 @@
import java.util.Set;
import java.util.Stack;
+import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.client.plan.PlanNode;
import org.teiid.common.buffer.BlockedException;
@@ -94,9 +95,10 @@
// Temp state for final results
private TupleSource finalTupleSource;
private int beginBatch = 1;
- private List batchRows;
+ private List<Object> batchRows;
private boolean lastBatch = false;
private LinkedHashMap<ElementSymbol, Expression> params;
+ private List<ElementSymbol> outParams;
private Map<ElementSymbol, Reference> implicitParams;
private QueryMetadataInterface metadata;
@@ -117,7 +119,7 @@
private TempTableStore tempTableStore;
- private LinkedList tempContext = new LinkedList();
+ private LinkedList<Set<String>> tempContext = new LinkedList<Set<String>>();
private SubqueryAwareEvaluator evaluator;
// Stack of programs, with current program on top
@@ -186,6 +188,11 @@
public void open() throws TeiidProcessingException, TeiidComponentException {
if (!this.evaluatedParams) {
+ if (this.outParams != null) {
+ for (ElementSymbol param : this.outParams) {
+ setParameterValue(param, getCurrentVariableContext(), null);
+ }
+ }
if (this.params != null) {
for (Map.Entry<ElementSymbol, Expression> entry : this.params.entrySet()) {
ElementSymbol param = entry.getKey();
@@ -195,9 +202,7 @@
Object value = this.evaluateExpression(expr);
//check constraint
- if (value == null && !metadata.elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
- throw new QueryValidatorException(QueryPlugin.Util.getString("ProcedurePlan.nonNullableParam", expr)); //$NON-NLS-1$
- }
+ checkNotNull(param, value);
setParameterValue(param, context, value);
}
}
@@ -214,6 +219,14 @@
this.evaluatedParams = true;
}
+ private void checkNotNull(ElementSymbol param, Object value)
+ throws TeiidComponentException, QueryMetadataException,
+ QueryValidatorException {
+ if (value == null && !metadata.elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+ throw new QueryValidatorException(QueryPlugin.Util.getString("ProcedurePlan.nonNullableParam", param)); //$NON-NLS-1$
+ }
+ }
+
protected void setParameterValue(ElementSymbol param,
VariableContext context, Object value) {
context.setValue(param, value);
@@ -245,11 +258,22 @@
// May throw BlockedException and exit here
List tuple = this.finalTupleSource.nextTuple();
if(tuple == null) {
+ if (outParams != null) {
+ VariableContext vc = getCurrentVariableContext();
+ List<Object> paramTuple = Arrays.asList(new Object[this.getOutputElements().size()]);
+ int i = this.getOutputElements().size() - this.outParams.size();
+ for (ElementSymbol param : outParams) {
+ Object value = vc.getValue(param);
+ checkNotNull(param, value);
+ paramTuple.set(i++, value);
+ }
+ addBatchRow(paramTuple, true);
+ }
terminateBatches();
done = true;
break;
}
- addBatchRow(tuple);
+ addBatchRow(tuple, false);
}
return pullBatch();
@@ -340,16 +364,24 @@
plan.setUpdateProcedure(this.isUpdateProcedure());
plan.setOutputElements(this.getOutputElements());
plan.setParams(params);
+ plan.setOutParams(outParams);
plan.setImplicitParams(implicitParams);
plan.setMetadata(metadata);
plan.requiresTransaction = requiresTransaction;
return plan;
}
- private void addBatchRow(List row) {
+ private void addBatchRow(List<?> row, boolean last) {
if(this.batchRows == null) {
- this.batchRows = new ArrayList(this.batchSize);
+ this.batchRows = new ArrayList<Object>(this.batchSize/4);
}
+ if (!last && this.outParams != null) {
+ List<Object> newRow = Arrays.asList(new Object[row.size() + this.outParams.size()]);
+ for (int i = 0; i < row.size(); i++) {
+ newRow.set(i, row.get(i));
+ }
+ row = newRow;
+ }
this.batchRows.add(row);
}
@@ -389,6 +421,10 @@
public void setMetadata( QueryMetadataInterface metadata ) {
this.metadata = metadata;
}
+
+ public void setOutParams(List<ElementSymbol> outParams) {
+ this.outParams = outParams;
+ }
public void setParams( LinkedHashMap<ElementSymbol, Expression> params ) {
this.params = params;
@@ -456,9 +492,9 @@
//process assignments
Assertion.assertTrue(this.currentState.currentRow != null);
for (Map.Entry<ElementSymbol, ElementSymbol> entry : procAssignments.entrySet()) {
- if (entry.getValue() == null) {
- continue;
- }
+ if (entry.getValue() == null || !metadata.elementSupports(entry.getValue().getMetadataID(), SupportConstants.Element.UPDATE)) {
+ continue;
+ }
int index = this.currentState.processor.getOutputElements().indexOf(entry.getKey());
getCurrentVariableContext().setValue(entry.getValue(), DataTypeManager.transformValue(this.currentState.currentRow.get(index), entry.getValue().getType()));
}
@@ -489,15 +525,15 @@
if (this.currentVarContext.getParentContext() != null) {
this.currentVarContext = this.currentVarContext.getParentContext();
}
- Set current = getTempContext();
+ Set<String> current = getTempContext();
- Set tempTables = getLocalTempTables();
+ Set<String> tempTables = getLocalTempTables();
tempTables.addAll(current);
if (program != originalProgram) {
- for (Iterator i = tempTables.iterator(); i.hasNext();) {
- this.tempTableStore.removeTempTableByName((String)i.next());
+ for (String table : tempTables) {
+ this.tempTableStore.removeTempTableByName(table);
}
}
this.tempContext.removeLast();
@@ -510,12 +546,12 @@
context.setParentContext(this.currentVarContext);
this.currentVarContext = context;
- Set current = getTempContext();
+ Set<String> current = getTempContext();
- Set tempTables = getLocalTempTables();
+ Set<String> tempTables = getLocalTempTables();
current.addAll(tempTables);
- this.tempContext.add(new HashSet());
+ this.tempContext.add(new HashSet<String>());
}
public void incrementProgramCounter() throws TeiidComponentException {
@@ -531,21 +567,21 @@
/**
* @return
*/
- private Set getLocalTempTables() {
- Set tempTables = this.tempTableStore.getAllTempTables();
+ private Set<String> getLocalTempTables() {
+ Set<String> tempTables = this.tempTableStore.getAllTempTables();
//determine what was created in this scope
for (int i = 0; i < tempContext.size() - 1; i++) {
- tempTables.removeAll((Set)tempContext.get(i));
+ tempTables.removeAll(tempContext.get(i));
}
return tempTables;
}
- public Set getTempContext() {
+ public Set<String> getTempContext() {
if (this.tempContext.isEmpty()) {
- tempContext.addLast(new HashSet());
+ tempContext.addLast(new HashSet<String>());
}
- return (Set)this.tempContext.getLast();
+ return this.tempContext.getLast();
}
public List getCurrentRow(String rsName) throws TeiidComponentException {
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/ProcedureContainerResolver.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -23,6 +23,7 @@
package org.teiid.query.resolver;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -53,6 +54,7 @@
import org.teiid.query.sql.proc.TriggerAction;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.GroupSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.validator.UpdateValidator;
import org.teiid.query.validator.UpdateValidator.UpdateInfo;
import org.teiid.query.validator.UpdateValidator.UpdateType;
@@ -119,10 +121,10 @@
List<ElementSymbol> viewElements = ResolverUtil.resolveElementsInGroup(ta.getView(), metadata);
if (procCommand instanceof Update || procCommand instanceof Insert) {
addChanging(tma.getMetadataStore(), externalGroups, viewElements);
- ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements);
+ ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.NEW, tma.getMetadataStore(), externalGroups, viewElements, false);
}
if (procCommand instanceof Update || procCommand instanceof Delete) {
- ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements);
+ ProcedureContainerResolver.addScalarGroup(SQLConstants.Reserved.OLD, tma.getMetadataStore(), externalGroups, viewElements, false);
}
QueryResolver.setChildMetadata(subCommand, tma.getMetadataStore().getData(), externalGroups);
QueryResolver.resolveCommand(subCommand, metadata);
@@ -192,8 +194,8 @@
inputElments.add(inputElement);
}
- addScalarGroup(ProcedureReservedWords.INPUT, discoveredMetadata, externalGroups, inputElments);
- addScalarGroup(ProcedureReservedWords.INPUTS, discoveredMetadata, externalGroups, inputElments);
+ addScalarGroup(ProcedureReservedWords.INPUT, discoveredMetadata, externalGroups, inputElments, false);
+ addScalarGroup(ProcedureReservedWords.INPUTS, discoveredMetadata, externalGroups, inputElments, false);
// Switch type to be boolean for all CHANGING variables
addChanging(discoveredMetadata, externalGroups, elements);
@@ -210,7 +212,7 @@
changingElements.add(changeElement);
}
- addScalarGroup(ProcedureReservedWords.CHANGING, discoveredMetadata, externalGroups, changingElements);
+ addScalarGroup(ProcedureReservedWords.CHANGING, discoveredMetadata, externalGroups, changingElements, false);
}
/**
@@ -313,13 +315,27 @@
procCommand.setUpdateInfo(ProcedureContainerResolver.getUpdateInfo(group, metadata, procCommand.getType()));
}
- public static GroupSymbol addScalarGroup(String name, TempMetadataStore metadata, GroupContext externalGroups, List symbols) {
+ public static GroupSymbol addScalarGroup(String name, TempMetadataStore metadata, GroupContext externalGroups, List<? extends SingleElementSymbol> symbols) {
+ return addScalarGroup(name, metadata, externalGroups, symbols, true);
+ }
+
+ public static GroupSymbol addScalarGroup(String name, TempMetadataStore metadata, GroupContext externalGroups, List<? extends SingleElementSymbol> symbols, boolean updatable) {
+ boolean[] updateArray = new boolean[symbols.size()];
+ if (updatable) {
+ Arrays.fill(updateArray, true);
+ }
+ return addScalarGroup(name, metadata, externalGroups, symbols, updateArray);
+ }
+
+ public static GroupSymbol addScalarGroup(String name, TempMetadataStore metadata, GroupContext externalGroups, List<? extends SingleElementSymbol> symbols, boolean[] updatable) {
GroupSymbol variables = new GroupSymbol(name);
externalGroups.addGroup(variables);
TempMetadataID tid = metadata.addTempGroup(name, symbols);
tid.setMetadataType(Type.SCALAR);
+ int i = 0;
for (TempMetadataID cid : tid.getElements()) {
cid.setMetadataType(Type.SCALAR);
+ cid.setUpdatable(updatable[i++]);
}
variables.setMetadataID(tid);
return variables;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/ExecResolver.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -235,15 +235,18 @@
GroupContext context = new GroupContext();
// Look through parameters to find input elements - these become child metadata
- List<ElementSymbol> tempElements = new ArrayList<ElementSymbol>();
+ List<ElementSymbol> tempElements = new ArrayList<ElementSymbol>(storedProcedureCommand.getParameters().size());
+ boolean[] updatable = new boolean[storedProcedureCommand.getParameters().size()];
+ int i = 0;
for (SPParameter param : storedProcedureCommand.getParameters()) {
- if(param.getParameterType() == ParameterInfo.IN || param.getParameterType() == ParameterInfo.INOUT) {
+ if(param.getParameterType() != ParameterInfo.RESULT_SET) {
ElementSymbol symbol = param.getParameterSymbol();
tempElements.add(symbol);
+ updatable[i++] = param.getParameterType() != ParameterInfo.IN;
}
}
- ProcedureContainerResolver.addScalarGroup(procName, discoveredMetadata, context, tempElements);
+ ProcedureContainerResolver.addScalarGroup(procName, discoveredMetadata, context, tempElements, updatable);
return context;
}
@@ -264,7 +267,7 @@
if(expr == null) {
continue;
}
- for (SubqueryContainer container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr)) {
+ for (SubqueryContainer<?> container : ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr)) {
QueryResolver.setChildMetadata(container.getCommand(), command);
QueryResolver.resolveCommand(container.getCommand(), metadata.getMetadata());
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/command/UpdateProcedureResolver.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -40,6 +40,7 @@
import org.teiid.logging.LogManager;
import org.teiid.query.QueryPlugin;
import org.teiid.query.metadata.QueryMetadataInterface;
+import org.teiid.query.metadata.SupportConstants;
import org.teiid.query.metadata.TempMetadataAdapter;
import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
@@ -181,7 +182,7 @@
externalGroups = new GroupContext(externalGroups, null);
//create a new variables group for this block
- GroupSymbol variables = ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, store, externalGroups, new LinkedList());
+ GroupSymbol variables = ProcedureContainerResolver.addScalarGroup(ProcedureReservedWords.VARIABLES, store, externalGroups, new LinkedList<SingleElementSymbol>());
for (Statement statement : block.getStatements()) {
resolveStatement(command, statement, externalGroups, variables, metadata);
@@ -218,11 +219,19 @@
continue;
}
switch (param.getParameterType()) {
- case ParameterInfo.INOUT:
case ParameterInfo.OUT:
case ParameterInfo.RETURN_VALUE:
+ if (param.getExpression() instanceof ElementSymbol && !metadata.elementSupports(((ElementSymbol)param.getExpression()).getMetadataID(), SupportConstants.Element.UPDATE)) {
+ throw new QueryResolverException(QueryPlugin.Util.getString("UpdateProcedureResolver.only_variables", param.getExpression())); //$NON-NLS-1$
+ }
sp.setCallableStatement(true);
break;
+ case ParameterInfo.INOUT:
+ if (param.getExpression() instanceof ElementSymbol && !metadata.elementSupports(((ElementSymbol)param.getExpression()).getMetadataID(), SupportConstants.Element.UPDATE)) {
+ continue;
+ }
+ sp.setCallableStatement(true);
+ break;
}
}
}
@@ -277,7 +286,7 @@
} else if (statement.getType() == Statement.TYPE_ASSIGNMENT) {
AssignmentStatement assStmt = (AssignmentStatement)statement;
ResolverVisitor.resolveLanguageObject(assStmt.getVariable(), null, externalGroups, metadata);
- if (statement.getType() == Statement.TYPE_ASSIGNMENT && !assStmt.getVariable().getGroupSymbol().getCanonicalName().equals(ProcedureReservedWords.VARIABLES)) {
+ if (!metadata.elementSupports(assStmt.getVariable().getMetadataID(), SupportConstants.Element.UPDATE)) {
throw new QueryResolverException(QueryPlugin.Util.getString("UpdateProcedureResolver.only_variables", assStmt.getVariable())); //$NON-NLS-1$
}
//don't allow variable assignments to be external
@@ -326,7 +335,7 @@
metadata = new TempMetadataAdapter(metadata.getMetadata(), store);
externalGroups = new GroupContext(externalGroups, null);
- ProcedureContainerResolver.addScalarGroup(groupName, store, externalGroups, symbols);
+ ProcedureContainerResolver.addScalarGroup(groupName, store, externalGroups, symbols, false);
resolveBlock(command, loopStmt.getBlock(), externalGroups, metadata);
break;
@@ -375,7 +384,9 @@
}
variable.setType(DataTypeManager.getDataTypeClass(typeName));
variable.setGroupSymbol(variables);
- variable.setMetadataID(new TempMetadataID(variable.getName(), variable.getType()));
+ TempMetadataID id = new TempMetadataID(variable.getName(), variable.getType());
+ id.setUpdatable(true);
+ variable.setMetadataID(id);
//TODO: this will cause the variables group to loose it's cache of resolved symbols
metadata.getMetadataStore().addElementToTempGroup(ProcedureReservedWords.VARIABLES, (ElementSymbol)variable.clone());
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -397,13 +397,10 @@
* @since 5.0
*/
public LinkedHashMap<ElementSymbol, Expression> getProcedureParameters() {
-
LinkedHashMap<ElementSymbol, Expression> map = new LinkedHashMap<ElementSymbol, Expression>();
- for (Iterator iter = this.getInputParameters().iterator(); iter.hasNext();) {
-
- SPParameter element = (SPParameter)iter.next();
+ for (SPParameter element : this.getInputParameters()) {
map.put(element.getParameterSymbol(), element.getExpression());
- } // for
+ } // for
return map;
}
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -442,10 +442,6 @@
public void visit(CreateUpdateProcedureCommand obj) {
if(!obj.isUpdateProcedure()){
- //Every virtual procedure should have at least one query.
- if(CommandCollectorVisitor.getCommands(obj).isEmpty()){
- handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.Procedure_should_have_query"), obj); //$NON-NLS-1$
- }
//check that the procedure does not contain references to itself
if (GroupCollectorVisitor.getGroups(obj,true).contains(obj.getVirtualGroup())) {
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-01-21 15:59:53 UTC (rev 2869)
@@ -668,7 +668,6 @@
SimpleQueryResolver.procedure_cache_not_usable=Procedure caching will not be used for {0} since the result set cache is disabled or the results/parameters cannot be cached.
SimpleQueryResolver.procedure_cache_not_used=Procedure caching will not be used for {0} due to the use of OPTION NOCACHE.
ValidationVisitor.groupby_subquery=Expressions used in a GROUP BY cannot be constant and must not contain subqueries: "{0}".
-ValidationVisitor.Procedure_should_have_query=Procedure must execute at least one command to define the procedure result set.
ValidationVisitor.Procedure_has_group_self_reference=Procedure cannot have a Group reference to itself.
ExpressionEvaluator.Expected_props_for_payload_function=Unable to evaluate {0}: expected Properties for command payload but got object of type {1}
ValidationVisitor.The_rowlimit_function_cannot_be_used_in_a_non-XML_command=The ''rowlimit'' and ''rowlimitexception'' functions cannot be used in a non-XML command
@@ -712,7 +711,7 @@
ValidationVisitor.xmlparse_type=XMLPARSE expects a STRING, CLOB, or BLOB value.
ValidationVisitor.invalid_encoding=Encoding {0} is not valid.
ValidationVisitor.subquery_insert=SELECT INTO should not be used in a subquery.
-UpdateProcedureResolver.only_variables=Element symbol "{0}" cannot be assigned a value. Only declared VARIABLES can be assigned values.
+UpdateProcedureResolver.only_variables=Variable "{0}" is read only and cannot be assigned a value.
MappingLoader.unknown_node_type=Unknown Node Type "{0}" being loaded by the XML mapping document.
MappingLoader.invalid_criteria_node=Invalid criteria node found; A criteria node must have criteria specified or it must be a default node.
WrongTypeChild=Wrong type of child node is being added.
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcedureRelational.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcedureRelational.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcedureRelational.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -585,7 +585,7 @@
TestProcessor.doProcess(plan, dataManager, expected, TestProcessor.createCommandContext());
fail("QueryPlannerException was expected."); //$NON-NLS-1$
} catch (QueryValidatorException e) {
- assertEquals("The procedure parameter is not nullable, but is set to null: pm1.vsp26.param2",e.getMessage()); //$NON-NLS-1$
+ assertEquals("The procedure parameter pm1.vsp26.param2 is not nullable, but is set to null.",e.getMessage()); //$NON-NLS-1$
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/test/java/org/teiid/query/processor/proc/TestProcedureProcessor.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -2697,5 +2697,41 @@
helpTestProcess(plan, expected, dataMgr, metadata);
}
+ @Test public void testReturnParamWithNoResultSetVirtual() throws Exception {
+ String sql = "EXEC TEIIDSP8(51)"; //$NON-NLS-1$
+ TransformationMetadata metadata = RealMetadataFactory.exampleBQTCached();
+ ProcessorPlan plan = getProcedurePlan(sql, metadata);
+
+ // Set up data
+ FakeDataManager dataMgr = new FakeDataManager();
+
+ // Create expected results
+ List[] expected = new List[] { Arrays.asList(51) }; //$NON-NLS-1$
+ helpTestProcess(plan, expected, dataMgr, metadata);
+ }
+
+ @Test(expected=QueryProcessingException.class) public void testParamsWithResultSetVirtualNotNull() throws Exception {
+ String sql = "{? = call TEIIDSP9(51)}"; //$NON-NLS-1$
+ TransformationMetadata metadata = RealMetadataFactory.exampleBQTCached();
+ ProcessorPlan plan = getProcedurePlan(sql, metadata);
+
+ FakeDataManager dataMgr = new FakeDataManager();
+
+ helpTestProcess(plan, null, dataMgr, metadata);
+ }
+
+ @Test public void testParamsWithResultSetVirtual() throws Exception {
+ String sql = "{? = call TEIIDSP9(1)}"; //$NON-NLS-1$
+ TransformationMetadata metadata = RealMetadataFactory.exampleBQTCached();
+ ProcessorPlan plan = getProcedurePlan(sql, metadata);
+
+ FakeDataManager dataMgr = new FakeDataManager();
+
+ List[] expected = new List[] { Arrays.asList("hello", null, null),
+ Arrays.asList(null, 1, 10) }; //$NON-NLS-1$
+
+ helpTestProcess(plan, expected, dataMgr, metadata);
+ }
+
private static final boolean DEBUG = false;
}
Modified: trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/test/java/org/teiid/query/resolver/TestProcedureResolving.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -1319,7 +1319,7 @@
String userUpdateStr = "UPDATE vm1.g1 SET e1='x'"; //$NON-NLS-1$
helpFailUpdateProcedure(procedure, userUpdateStr,
- FakeMetadataObject.Props.UPDATE_PROCEDURE, "Element symbol \"INPUTS.e1\" cannot be assigned a value. Only declared VARIABLES can be assigned values."); //$NON-NLS-1$
+ FakeMetadataObject.Props.UPDATE_PROCEDURE);
}
// validating CHANGING element assigned
@@ -1334,7 +1334,7 @@
String userUpdateStr = "UPDATE vm1.g1 SET e1='x'"; //$NON-NLS-1$
helpFailUpdateProcedure(procedure, userUpdateStr,
- FakeMetadataObject.Props.UPDATE_PROCEDURE, "Element symbol \"CHANGING.e1\" cannot be assigned a value. Only declared VARIABLES can be assigned values."); //$NON-NLS-1$
+ FakeMetadataObject.Props.UPDATE_PROCEDURE);
}
// variables cannot be used among insert elements
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/RealMetadataFactory.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -267,6 +267,20 @@
Procedure vsp7 = createVirtualProcedure("TEIIDSP7", mmspTest1, Arrays.asList(vsp7p1), vspqn7); //$NON-NLS-1$
vsp7.setResultSet(vsprs7);
+ ProcedureParameter vsp8p1 = createParameter("r", ParameterInfo.RETURN_VALUE, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
+ ProcedureParameter vsp8p2 = createParameter("p1", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
+ QueryNode vspqn8 = new QueryNode("TEIIDSP8", "CREATE VIRTUAL PROCEDURE BEGIN r = p1; END"); //$NON-NLS-1$ //$NON-NLS-2$
+ createVirtualProcedure("TEIIDSP8", mmspTest1, Arrays.asList(vsp8p1, vsp8p2), vspqn8); //$NON-NLS-1$
+
+ ColumnSet<Procedure> vsprs9 = createResultSet("TEIIDSP9.vsprs1", new String[] { "StringKey" }, new String[] { DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$
+ ProcedureParameter vsp9p1 = createParameter("r", ParameterInfo.RETURN_VALUE, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
+ vsp9p1.setNullType(NullType.No_Nulls);
+ ProcedureParameter vsp9p2 = createParameter("p1", ParameterInfo.IN, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
+ ProcedureParameter vsp9p3 = createParameter("p2", ParameterInfo.OUT, DataTypeManager.DefaultDataTypes.INTEGER); //$NON-NLS-1$
+ QueryNode vspqn9 = new QueryNode("TEIIDSP9", "CREATE VIRTUAL PROCEDURE BEGIN if (p1 = 1) begin\n r = 1; end\n p2 = 10; select 'hello'; END"); //$NON-NLS-1$ //$NON-NLS-2$
+ Procedure vsp9 = createVirtualProcedure("TEIIDSP9", mmspTest1, Arrays.asList(vsp9p1, vsp9p2, vsp9p3), vspqn9); //$NON-NLS-1$
+ vsp9.setResultSet(vsprs9);
+
// this is for the source added function
bqt1.addFunction(new FunctionMethod("reverse", "reverse", "misc", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
new FunctionParameter[] {new FunctionParameter("columnName", DataTypeManager.DefaultDataTypes.STRING, "")}, //$NON-NLS-1$ //$NON-NLS-2$
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-01-21 13:38:38 UTC (rev 2868)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-01-21 15:59:53 UTC (rev 2869)
@@ -1674,7 +1674,7 @@
// Validate
ValidatorReport report = Validator.validate(command, metadata);
// Validate
- assertEquals(1, report.getItems().size());
+ assertEquals(0, report.getItems().size());
}
@Test public void testDefect21389() throws Exception{
More information about the teiid-commits
mailing list