teiid SVN: r2896 - in trunk: documentation/reference/src/main/docbook/en-US and 10 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-02-01 16:22:45 -0500 (Tue, 01 Feb 2011)
New Revision: 2896
Added:
trunk/documentation/reference/src/main/docbook/en-US/content/multisource.xml
Modified:
trunk/build/kits/jboss-container/teiid-releasenotes.html
trunk/documentation/reference/src/main/docbook/en-US/Reference.xml
trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.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/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java
trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
Log:
TEIID-99 adding handling for multi-source procedures. also adding validation and fixing multisource updates when no source is selected.
Modified: trunk/build/kits/jboss-container/teiid-releasenotes.html
===================================================================
--- trunk/build/kits/jboss-container/teiid-releasenotes.html 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/build/kits/jboss-container/teiid-releasenotes.html 2011-02-01 21:22:45 UTC (rev 2896)
@@ -28,6 +28,7 @@
<UL>
<LI><B>Virtual procedure out params</B> - virtual procedures can now have RETURN/OUT/INOUT parameters to return values.
<LI><B>OLAP</B> - OLAP translator is now part of Teiid kit using OLAP4J
+ <LI><B>Multi-source procedures</B> - multi-source handling was expanded to cover stored procedure execution. See the Reference for more.
</UL>
<h2><a name="Compatibility">Compatibility Issues</a></h2>
@@ -35,6 +36,13 @@
<li>TRANSLATE/HAS CRITERIA has been deprecated. An alternative approach to update procedures will be introduced in a subsequent version.
<li>Support for named parameter syntax using param=value has been deprecated, since it is ambiguous with a comparison predicate boolean value expression. param<b>=></b>value should be used instead.
</ul>
+
+<h4>from 7.3</h4>
+<ul>
+ <li>The use of an IN procedure parameter with the name "source_name" in a multi-source model, will now be treated the parameter that controls which source
+ the procedure will execute against.
+</ul>
+
<h4>from 7.2</h4>
<ul>
<li>The default JDBC credentials are user/user - not admin/teiid
Modified: trunk/documentation/reference/src/main/docbook/en-US/Reference.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/Reference.xml 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/documentation/reference/src/main/docbook/en-US/Reference.xml 2011-02-01 21:22:45 UTC (rev 2896)
@@ -56,6 +56,7 @@
<xi:include href="content/transaction_support.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/dataroles.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/system_schema.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
+ <xi:include href="content/multisource.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/translators.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/federated_planning.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
<xi:include href="content/architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
Added: trunk/documentation/reference/src/main/docbook/en-US/content/multisource.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/multisource.xml (rev 0)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/multisource.xml 2011-02-01 21:22:45 UTC (rev 2896)
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+<!ENTITY % CustomDTD SYSTEM "../../../../../../docbook/custom.dtd">
+%CustomDTD;
+]>
+<chapter id="multisource">
+ <title>Multi-source models</title>
+ <para>Multi-source models can be used to quickly access data in multiple sources with homogeneous metadata.
+ Since all sources utilize the same physical metadata, this feature is most appropriate for accessing the same source type with multiple instances.
+ <para>A model is marked as supporting multi-source by setting the property supports-multi-source-bindings to true.
+ With supports-multi-source-bindings set to true, 1 or more uniquely named source elements can be added to the model.
+ See <xref linkend="dynamic_vdbs"/> for a full template of the vdb.xml.</para>
+ A physical table in a multi-source model is effectively treated as a view that is a
+ union all of the actual physical table from each of the configured sources. These tables tables are implicitly partitioned on a string pseudo-column "source_name".
+ The "source_name" column will be available to your use queries for a multi-source model regardless of whether it is explicitly part of the metadata.
+ The source_name column value for a particular row is the source name used to obtain that row.
+ More complex partitioning scenarios, such as heterogeneous sources or list partitioning will require the use of a <xref linkend="partitioned_union"/></para>
+ <para>In some scenarios, the source_name column can be manually added to the physical metadata in the Designer tool so that virtual layer logic can be multi-source aware.
+ It is important to understand that a column or IN procedure parameter named source_name will always be treated as the explicit form of the multi-source source_name column
+ and will no longer be treated as an actual physical column or procedure parameter.</para>
+ <section>
+ <title>Multi-source SELECTs</title>
+ <para>A multi-source SELECT may use the source_name column anywhere a column reference is allowed. As a final stage of planning, a source query will be generated against each source and each instance of the source_name column replaced by the appropriate value.
+ If the resulting query still needs executed, it is sent to the source. If the WHERE clause evaluates to always false, then the query is pruned from the result. All results are then unioned together and returned as the full result.
+ </para>
+ </section>
+ <section>
+ <title>Multi-source INSERTs</title>
+ <para>A multi-source INSERT may use the source_name column as an insert target column to specify which source should be targeted by the INSERT. Only a INSERT using the VALUES clause is supported and the source_name column value must be a literal.
+ If the source_name column is not part of the INSERT column, then the INSERT will be issued against every source. The sum of the update counts will be returned as the resultant update count.</para>
+ </section>
+ <section>
+ <title>Multi-source UPDATEs</title>
+ <para>A multi-source delete functions just like SELECT, however it is not possible to use the source_name column as a target column in the change set. Any other usage of the source_name column will be the appropriate value for each source.
+ If the WHERE clause evaluates to always false, then no update will be issued to the source. The sum of the update counts will be returned as the resultant update count.</para>
+ </section>
+ <section>
+ <title>Multi-source DELETEs</title>
+ <para>A multi-source delete functions just like SELECT. Any usage of the source_name column will be the appropriate value for each source.
+ If the WHERE clause evaluates to always false, then no delete will be issued to the source. The sum of the update counts will be returned as the resultant update count.</para>
+ </section>
+ <section>
+ <title>Multi-source Stored Procedures</title>
+ <para>A physical stored procedures requires the manual addition of a string source_name parameter to allow for specifying which source the procedure is executed on.
+ If the source_name parameter is not added or if named parameters are used and the source_name parameter is allowed to default to a null value, then the procedure will be executed on
+ each source and the results unioned together.</para>
+ <para>It is not possible to execute procedures that required to return IN/OUT, OUT, or RETURN parameters values on more than 1 source at a time.</para>
+ </section>
+ <section>
+ <title>Additional Concerns</title>
+ <para>When running under a transaction of in a mode that detects the need for a transation and multiple updates are performed, an attempt will be made to enlist each source in the same XA transaction.</para>
+ </section>
+</chapter>
\ No newline at end of file
Property changes on: trunk/documentation/reference/src/main/docbook/en-US/content/multisource.xml
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml
===================================================================
--- trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/documentation/reference/src/main/docbook/en-US/content/translators.xml 2011-02-01 21:22:45 UTC (rev 2896)
@@ -1149,6 +1149,7 @@
<source name="${source-name}" translator-name="${translator-name}"
connection-jndi-name="${deployed-jndi-name}">
+ ...
</model>
<!-- create translator instances that override default properties -->
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceElementReplacementVisitor.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -23,11 +23,6 @@
package org.teiid.dqp.internal.process.multisource;
import org.teiid.core.types.DataTypeManager;
-import org.teiid.query.rewriter.QueryRewriter;
-import org.teiid.query.sql.lang.From;
-import org.teiid.query.sql.lang.Insert;
-import org.teiid.query.sql.lang.Query;
-import org.teiid.query.sql.lang.Select;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
@@ -56,28 +51,4 @@
return expr;
}
- public void visit(Insert obj) {
- for (int i = 0; i < obj.getVariables().size(); i++) {
- Expression expr = (Expression)obj.getVariables().get(i);
- if(expr instanceof ElementSymbol) {
- ElementSymbol elem = (ElementSymbol) expr;
- Object metadataID = elem.getMetadataID();
- if(metadataID instanceof MultiSourceElement) {
- Constant source = (Constant)obj.getValues().get(i);
- obj.getVariables().remove(i);
- obj.getValues().remove(i);
- if (!source.getValue().equals(this.bindingName)) {
- Select select = new Select(obj.getVariables());
- From from = new From();
- from.addGroup(obj.getGroup());
- Query query = new Query();
- query.setSelect(select);
- query.setFrom(from);
- query.setCriteria(QueryRewriter.FALSE_CRITERIA);
- obj.setQueryExpression(query);
- }
- }
- }
- }
- }
}
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 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourceMetadataWrapper.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -337,8 +337,20 @@
}
@Override
- public boolean isMultiSourceElement(Object elementId) {
- return elementId instanceof MultiSourceElement;
+ public boolean isMultiSourceElement(Object elementId) throws QueryMetadataException, TeiidComponentException {
+ if (elementId instanceof MultiSourceElement) {
+ return true;
+ }
+ Object gid = getGroupIDForElementID(elementId);
+ if (isProcedure(gid)) {
+ Object modelID = this.getModelID(gid);
+ String modelName = this.getFullName(modelID);
+ if(multiSourceModels.contains(modelName)) {
+ String shortName = getShortElementName(getFullName(elementId));
+ return shortName.equalsIgnoreCase(MultiSourceElement.MULTI_SOURCE_ELEMENT_NAME);
+ }
+ }
+ return false;
}
}
Modified: trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/multisource/MultiSourcePlanToProcessConverter.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -23,11 +23,14 @@
package org.teiid.dqp.internal.process.multisource;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.adminapi.impl.VDBMetaData;
+import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.api.exception.query.QueryValidatorException;
import org.teiid.core.TeiidComponentException;
@@ -36,6 +39,7 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.dqp.internal.process.DQPWorkContext;
import org.teiid.language.SQLConstants.NonReserved;
+import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -53,10 +57,16 @@
import org.teiid.query.resolver.util.ResolverUtil;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.lang.Command;
+import org.teiid.query.sql.lang.Insert;
+import org.teiid.query.sql.lang.SPParameter;
+import org.teiid.query.sql.lang.StoredProcedure;
import org.teiid.query.sql.navigator.DeepPreOrderNavigator;
import org.teiid.query.sql.symbol.AggregateSymbol;
+import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.ExpressionSymbol;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.util.CommandContext;
@@ -120,6 +130,12 @@
ModelMetaData model = vdb.getModel(modelName);
List<AccessNode> accessNodes = new ArrayList<AccessNode>();
+ boolean hasOutParams = false;
+ if (accessNode.getCommand() instanceof StoredProcedure) {
+ StoredProcedure sp = (StoredProcedure)accessNode.getCommand();
+ hasOutParams = sp.returnParameters() && sp.getProjectedSymbols().size() > sp.getResultSetColumns().size();
+ }
+
for(String sourceName:model.getSourceNames()) {
// Create a new cloned version of the access node and set it's model name to be the bindingUUID
@@ -130,13 +146,12 @@
// Modify the command to pull the instance column and evaluate the criteria
Command command = (Command)instanceNode.getCommand().clone();
- // Replace all multi-source elements with the source name
- DeepPreOrderNavigator.doVisit(command, new MultiSourceElementReplacementVisitor(sourceName));
+ command = rewriteCommand(sourceName, command);
+
+ if (command == null) {
+ continue;
+ }
- if (!RelationalNodeUtil.shouldExecute(command, false)) {
- continue;
- }
-
// Rewrite the command now that criteria may have been simplified
try {
command = QueryRewriter.rewrite(command, metadata, null);
@@ -151,10 +166,21 @@
accessNodes.add(instanceNode);
}
+
+ if (hasOutParams && accessNodes.size() != 1) {
+ throw new QueryPlannerException(QueryPlugin.Util.getString("MultiSource.out_procedure", accessNode.getCommand())); //$NON-NLS-1$
+ }
switch(accessNodes.size()) {
case 0:
{
+ if (RelationalNodeUtil.isUpdate(accessNode.getCommand())) {
+ //should return a 0 update count
+ ProjectNode pnode = new ProjectNode(getID());
+ pnode.setElements(accessNode.getElements());
+ pnode.setSelectSymbols(Arrays.asList(new ExpressionSymbol("x", new Constant(0)))); //$NON-NLS-1$
+ return pnode;
+ }
// Replace existing access node with a NullNode
NullNode nullNode = new NullNode(getID());
nullNode.setElements(accessNode.getElements());
@@ -206,4 +232,50 @@
}
}
+ private Command rewriteCommand(String sourceName, Command command) throws ExpressionEvaluationException, TeiidComponentException {
+ if (command instanceof StoredProcedure) {
+ StoredProcedure obj = (StoredProcedure)command;
+ for (Iterator<SPParameter> params = obj.getMapOfParameters().values().iterator(); params.hasNext();) {
+ SPParameter param = params.next();
+ if (param.getParameterType() != SPParameter.IN) {
+ continue;
+ }
+ String shortName = SingleElementSymbol.getShortName(param.getName());
+ if(shortName.equalsIgnoreCase(MultiSourceElement.MULTI_SOURCE_ELEMENT_NAME)) {
+ Constant source = (Constant)param.getExpression();
+ params.remove();
+ if (param.isUsingDefault() && source.isNull()) {
+ continue;
+ }
+ if (!source.getValue().equals(sourceName)) {
+ return null;
+ }
+ }
+ }
+ } if (command instanceof Insert) {
+ Insert obj = (Insert)command;
+ for (int i = 0; i < obj.getVariables().size(); i++) {
+ ElementSymbol elem = obj.getVariables().get(i);
+ Object metadataID = elem.getMetadataID();
+ if(metadataID instanceof MultiSourceElement) {
+ Constant source = (Constant)obj.getValues().get(i);
+ obj.getVariables().remove(i);
+ obj.getValues().remove(i);
+ if (!source.getValue().equals(sourceName)) {
+ return null;
+ }
+ }
+ }
+ } else {
+ // Replace all multi-source elements with the source name
+ DeepPreOrderNavigator.doVisit(command, new MultiSourceElementReplacementVisitor(sourceName));
+ }
+
+ if (!RelationalNodeUtil.shouldExecute(command, false)) {
+ return null;
+ }
+
+ return command;
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/BasicQueryMetadataWrapper.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -380,7 +380,7 @@
}
@Override
- public boolean isMultiSourceElement(Object elementId) {
+ public boolean isMultiSourceElement(Object elementId) throws QueryMetadataException, TeiidComponentException {
return actualMetadata.isMultiSourceElement(elementId);
}
Modified: trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/query/metadata/QueryMetadataInterface.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -683,5 +683,5 @@
boolean isMultiSource(Object modelId) throws QueryMetadataException, TeiidComponentException;
- boolean isMultiSourceElement(Object elementId);
+ boolean isMultiSourceElement(Object elementId) throws QueryMetadataException, TeiidComponentException;
}
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-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/StoredProcedure.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -163,6 +163,10 @@
List<SPParameter> listOfParameters = new ArrayList<SPParameter>(mapOfParameters.values());
return listOfParameters;
}
+
+ public Map<Integer, SPParameter> getMapOfParameters() {
+ return mapOfParameters;
+ }
public SPParameter getParameter(int index){
return mapOfParameters.get(new Integer(index));
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -126,7 +126,6 @@
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
-import org.teiid.query.sql.visitor.CommandCollectorVisitor;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.sql.visitor.FunctionCollectorVisitor;
@@ -418,6 +417,31 @@
}
}
}
+
+ @Override
+ public void visit(StoredProcedure obj) {
+ for (SPParameter param : obj.getInputParameters()) {
+ try {
+ if (!(param.getExpression() instanceof Constant) && getMetadata().isMultiSourceElement(param.getMetadataID())) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.multisource_constant", param.getParameterSymbol()), param.getParameterSymbol()); //$NON-NLS-1$
+ continue;
+ }
+ if (EvaluatableVisitor.isFullyEvaluatable(param.getExpression(), true)) {
+ try {
+ // If nextValue is an expression, evaluate it before checking for null
+ Object evaluatedValue = Evaluator.evaluate(param.getExpression());
+ if(evaluatedValue == null && ! getMetadata().elementSupports(param.getMetadataID(), SupportConstants.Element.NULL)) {
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0055", param.getParameterSymbol()), param.getParameterSymbol()); //$NON-NLS-1$
+ }
+ } catch(ExpressionEvaluationException e) {
+ //ignore for now, we don't have the context which could be the problem
+ }
+ }
+ } catch (TeiidComponentException e) {
+ handleException(e);
+ }
+ }
+ }
private void validateAssignment(LanguageObject obj,
ElementSymbol variable) {
@@ -790,14 +814,12 @@
}
// Get elements in the group.
- Collection insertElmnts = new LinkedList(ResolverUtil.resolveElementsInGroup(insertGroup, getMetadata()));
+ Collection<ElementSymbol> insertElmnts = new LinkedList<ElementSymbol>(ResolverUtil.resolveElementsInGroup(insertGroup, getMetadata()));
// remove all elements specified in insert to get the ignored elements
insertElmnts.removeAll(vars);
- Iterator ignoreIter = insertElmnts.iterator();
- while(ignoreIter.hasNext()) {
- ElementSymbol nextElmnt = (ElementSymbol) ignoreIter.next();
+ for (ElementSymbol nextElmnt : insertElmnts) {
if(!getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.DEFAULT_VALUE) &&
!getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.NULL) &&
!getMetadata().elementSupports(nextElmnt.getMetadataID(), SupportConstants.Element.AUTO_INCREMENT) &&
@@ -812,12 +834,17 @@
Expression nextValue = (Expression) valIter.next();
ElementSymbol nextVar = (ElementSymbol) varIter.next();
+ if (!(nextValue instanceof Constant) && getMetadata().isMultiSourceElement(nextVar.getMetadataID())) {
+ handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.multisource_constant", nextVar), nextVar); //$NON-NLS-1$
+ continue;
+ }
+
if (EvaluatableVisitor.isFullyEvaluatable(nextValue, true)) {
try {
// If nextValue is an expression, evaluate it before checking for null
Object evaluatedValue = Evaluator.evaluate(nextValue);
if(evaluatedValue == null && ! getMetadata().elementSupports(nextVar.getMetadataID(), SupportConstants.Element.NULL)) {
- handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0055", SQLStringVisitor.getSQLString(nextVar)), nextVar); //$NON-NLS-1$
+ handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0055", nextVar), nextVar); //$NON-NLS-1$
}
} catch(ExpressionEvaluationException e) {
//ignore for now, we don't have the context which could be the problem
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-02-01 21:22:45 UTC (rev 2896)
@@ -197,6 +197,7 @@
ValidationVisitor.nonUpdatable = The specified change set {0} against an inherently updatable view does not map to a key preserving group.
ValidationVisitor.insert_qe_partition = Inserts with query expressions cannot be performed against a partitioned UNION view {0}.
ValidationVisitor.insert_no_partition = Could not determine INSERT target for a partitioned UNION view {0} with values {1}.
+ValidationVisitor.multisource_constant = The multisource column or parameter {0} requires a literal value.
ERR.015.012.0029 = INSERT, UPDATE, and DELETE not allowed on XML documents
ERR.015.012.0030 = Commands used in stored procedure language not allowed on XML documents
ERR.015.012.0031 = Queries against XML documents can not have a GROUP By clause
@@ -891,4 +892,6 @@
RelationalPlanner.nonpushdown_command=Source UPDATE or DELETE command "{0}" contains non-pushdown constructs and no compensating action can be taken as the table lacks a unique key or the source does not support equality predicates.
-Translate.error=Cannot translate criteria "{0}", it is not matched by selector "{1}"
\ No newline at end of file
+Translate.error=Cannot translate criteria "{0}", it is not matched by selector "{1}"
+
+MultiSource.out_procedure=The multisource plan must execute a procedure returning parameter values exactly 1: {0}
\ No newline at end of file
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourceElementReplacementVisitor.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -122,22 +122,4 @@
"SELECT a FROM MultiModel.Phys WHERE 'x' = (SELECT b FROM MultiModel.Phys WHERE 'x' IN ('x'))"); //$NON-NLS-1$
}
- public void testInsertMatching() throws Exception {
- helpTest("INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'x')", //$NON-NLS-1$
- getMetadata(),
- "INSERT INTO MultiModel.Phys (a) VALUES ('a')"); //$NON-NLS-1$
- }
-
- public void testInsertNotMatching() throws Exception {
- helpTest("INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'y')", //$NON-NLS-1$
- getMetadata(),
- "INSERT INTO MultiModel.Phys (a) SELECT a FROM MultiModel.Phys WHERE 1 = 0"); //$NON-NLS-1$
- }
-
- public void testInsertAll() throws Exception {
- helpTest("INSERT INTO MultiModel.Phys(a) VALUES('a')", //$NON-NLS-1$
- getMetadata(),
- "INSERT INTO MultiModel.Phys (a) VALUES ('a')"); //$NON-NLS-1$
- }
-
}
Modified: trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -26,7 +26,6 @@
import java.util.Arrays;
import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
@@ -57,8 +56,6 @@
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.util.CommandContext;
-
-
/**
* It's important here that the MultiSourceCapabilityFinder is used since some capabilities
* will never be pushed to the source
@@ -76,10 +73,9 @@
public TupleSource registerRequest(CommandContext context, Command command, String modelName, String connectorBindingId, int nodeID) throws org.teiid.core.TeiidComponentException {
assertNotNull(connectorBindingId);
- Collection elements = ElementCollectorVisitor.getElements(command, true, true);
+ Collection<ElementSymbol> elements = ElementCollectorVisitor.getElements(command, true, true);
- for (Iterator i = elements.iterator(); i.hasNext();) {
- ElementSymbol symbol = (ElementSymbol)i.next();
+ for (ElementSymbol symbol : elements) {
if (symbol.getMetadataID() instanceof MultiSourceElement) {
fail("Query Contains a MultiSourceElement -- MultiSource expansion did not happen"); //$NON-NLS-1$
}
@@ -261,5 +257,64 @@
dataMgr.addData("UPDATE MultiModel.Phys SET a = '1' WHERE b = 'z'", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
}
+
+ @Test public void testInsertMatching() throws Exception {
+ final QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
+ final String userSql = "INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'a')"; //$NON-NLS-1$
+ final String multiModel = "MultiModel"; //$NON-NLS-1$
+ final int sources = 3;
+ final List[] expected = new List[] { Arrays.asList(1)};
+ final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
+ dataMgr.setMustRegisterCommands(true);
+ dataMgr.addData("INSERT INTO MultiModel.Phys (a) VALUES ('a')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
+ }
+
+ @Test public void testInsertNotMatching() throws Exception {
+ final QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
+ final String userSql = "INSERT INTO MultiModel.Phys(a, SOURCE_NAME) VALUES ('a', 'x')"; //$NON-NLS-1$
+ final String multiModel = "MultiModel"; //$NON-NLS-1$
+ final int sources = 3;
+ final List[] expected = new List[] { Arrays.asList(0)};
+ final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
+ dataMgr.setMustRegisterCommands(true);
+ helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
+ }
+
+ @Test public void testInsertAll() throws Exception {
+ final QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
+ final String userSql = "INSERT INTO MultiModel.Phys(a) VALUES ('a')"; //$NON-NLS-1$
+ final String multiModel = "MultiModel"; //$NON-NLS-1$
+ final int sources = 3;
+ final List[] expected = new List[] { Arrays.asList(3)};
+ final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
+ dataMgr.setMustRegisterCommands(true);
+ dataMgr.addData("INSERT INTO MultiModel.Phys (a) VALUES ('a')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
+ }
+
+ @Test public void testProcedure() throws Exception {
+ final QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
+ final String userSql = "exec MultiModel.proc('b', 'a')"; //$NON-NLS-1$
+ final String multiModel = "MultiModel"; //$NON-NLS-1$
+ final int sources = 3;
+ final List[] expected = new List[] { Arrays.asList(1)};
+ final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
+ dataMgr.setMustRegisterCommands(true);
+ dataMgr.addData("EXEC MultiModel.proc('b')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
+ }
+
+ @Test public void testProcedureAll() throws Exception {
+ final QueryMetadataInterface metadata = FakeMetadataFactory.exampleMultiBinding();
+ final String userSql = "exec MultiModel.proc(\"in\"=>'b')"; //$NON-NLS-1$
+ final String multiModel = "MultiModel"; //$NON-NLS-1$
+ final int sources = 3;
+ final List[] expected = new List[] { Arrays.asList(1), Arrays.asList(1), Arrays.asList(1)};
+ final MultiSourceDataManager dataMgr = new MultiSourceDataManager();
+ dataMgr.setMustRegisterCommands(true);
+ dataMgr.addData("EXEC MultiModel.proc('b')", new List[] {Arrays.asList(1)}); //$NON-NLS-1$
+ helpTestMultiSourcePlan(metadata, userSql, multiModel, sources, dataMgr, expected, FakeMetadataFactory.exampleMultiBindingVDB());
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -69,7 +69,6 @@
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.FakeFunctionMetadataSource;
import org.teiid.query.optimizer.QueryOptimizer;
-import org.teiid.query.optimizer.TestAggregatePushdown;
import org.teiid.query.optimizer.TestOptimizer;
import org.teiid.query.optimizer.TestRuleRaiseNull;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
@@ -97,7 +96,6 @@
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
-import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.query.unittest.TimestampUtil;
import org.teiid.query.util.CommandContext;
import org.teiid.query.validator.Validator;
Modified: trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/test/java/org/teiid/query/unittest/FakeMetadataFactory.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -2321,6 +2321,15 @@
QueryNode sq2n1 = new QueryNode("pm1.sq1", "CREATE VIRTUAL PROCEDURE BEGIN\n" //$NON-NLS-1$ //$NON-NLS-2$
+ "execute string 'SELECT a, b FROM MultiModel.Phys where SOURCE_NAME = Virt.sq1.in'; END"); //$NON-NLS-1$
FakeMetadataObject sq1 = FakeMetadataFactory.createVirtualProcedure("Virt.sq1", virtModel, Arrays.asList(new FakeMetadataObject[] { rs2p1, rs2p2 }), sq2n1); //$NON-NLS-1$
+
+ FakeMetadataObject rs3 = FakeMetadataFactory.createResultSet("MultiModel.rs1", virtModel, new String[] { "a", "b" }, new String[] { DataTypeManager.DefaultDataTypes.STRING, DataTypeManager.DefaultDataTypes.STRING }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ FakeMetadataObject rs3p1 = FakeMetadataFactory.createParameter("ret", 1, ParameterInfo.RESULT_SET, DataTypeManager.DefaultDataTypes.OBJECT, rs3); //$NON-NLS-1$
+ FakeMetadataObject rs3p2 = FakeMetadataFactory.createParameter("in", 2, ParameterInfo.IN, DataTypeManager.DefaultDataTypes.STRING, null); //$NON-NLS-1$
+ FakeMetadataObject rs3p3 = FakeMetadataFactory.createParameter("source_name", 3, ParameterInfo.IN, DataTypeManager.DefaultDataTypes.STRING, null); //$NON-NLS-1$
+ rs3p3.putProperty(FakeMetadataObject.Props.NULL, Boolean.TRUE);
+ FakeMetadataObject sq2 = FakeMetadataFactory.createStoredProcedure("MultiModel.proc", physModel, Arrays.asList(new FakeMetadataObject[] { rs3p1, rs3p2, rs3p3 }), "MultiModel.proc");
+ rs3p2.putProperty(FakeMetadataObject.Props.GROUP, sq2);
+ rs3p3.putProperty(FakeMetadataObject.Props.GROUP, sq2);
FakeMetadataStore store = new FakeMetadataStore();
store.addObject(virtModel);
@@ -2332,6 +2341,8 @@
store.addObject(rs2);
store.addObject(sq1);
+ store.addObject(rs3);
+ store.addObject(sq2);
return new FakeMetadataFacade(store);
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-02-01 17:34:53 UTC (rev 2895)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-02-01 21:22:45 UTC (rev 2896)
@@ -2029,5 +2029,11 @@
@Test public void testTextAggHeader() throws Exception {
helpValidate("select textagg(for e1 || 1 HEADER) from pm1.g1", new String[] {"TEXTAGG(FOR (e1 || 1) HEADER)"}, FakeMetadataFactory.example1Cached()); //$NON-NLS-1$
}
+
+ @Test public void testMultiSourceProcValue() throws Exception {
+ Set<String> models = new HashSet<String>();
+ models.add("MultiModel");
+ helpValidate("exec MultiModel.proc('a', (select 1))", new String[] {"MultiModel.proc.source_name"}, new MultiSourceMetadataWrapper(FakeMetadataFactory.exampleMultiBinding(), models)); //$NON-NLS-1$
+ }
}
14 years, 10 months
teiid SVN: r2895 - in branches/7.1.x/engine/src: test/java/org/teiid/query/optimizer and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-02-01 12:34:53 -0500 (Tue, 01 Feb 2011)
New Revision: 2895
Modified:
branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
Log:
TEIID-1458 fix to ensure aggregates that need computed after a join and are cardinality dependent return the proper value
Modified: branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-02-01 15:31:51 UTC (rev 2894)
+++ branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-02-01 17:34:53 UTC (rev 2895)
@@ -444,8 +444,11 @@
CapabilitiesFinder capFinder) throws TeiidComponentException,
QueryMetadataException, QueryPlannerException {
- Map<PlanNode, List<AggregateSymbol>> aggregateMap = createNodeMapping(groupNode, allAggregates);
- Map<PlanNode, List<SingleElementSymbol>> groupingMap = createNodeMapping(groupNode, groupingExpressions);
+ Map<PlanNode, List<AggregateSymbol>> aggregateMap = createNodeMapping(groupNode, allAggregates, true);
+ if (aggregateMap == null) {
+ return;
+ }
+ Map<PlanNode, List<SingleElementSymbol>> groupingMap = createNodeMapping(groupNode, groupingExpressions, false);
Set<PlanNode> possibleTargetNodes = new HashSet<PlanNode>(aggregateMap.keySet());
possibleTargetNodes.addAll(groupingMap.keySet());
@@ -621,26 +624,25 @@
}
private <T extends SingleElementSymbol> Map<PlanNode, List<T>> createNodeMapping(PlanNode groupNode,
- Collection<T> expressions) {
+ Collection<T> expressions, boolean aggs) {
Map<PlanNode, List<T>> result = new HashMap<PlanNode, List<T>>();
if (expressions == null) {
return result;
}
for (T aggregateSymbol : expressions) {
- if (aggregateSymbol instanceof AggregateSymbol) {
- AggregateSymbol partitionAgg = (AggregateSymbol)aggregateSymbol;
- if (partitionAgg.isDistinct()) {
- continue; //currently we cann't consider distinct aggs
- }
- }
-
+ if (aggs && ((AggregateSymbol)aggregateSymbol).getExpression() == null) {
+ return null; //count(*) is not yet handled. a general approach would be count(*) => count(r.col) * count(l.col), but the logic here assumes a simpler initial mapping
+ }
Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(aggregateSymbol);
if (groups.isEmpty()) {
- continue;
+ continue;
}
PlanNode originatingNode = FrameUtil.findOriginatingNode(groupNode, groups);
if (originatingNode == null) {
- continue;
+ if (aggs) {
+ return null; //should never happen
+ }
+ continue;
}
PlanNode parentAccess = NodeEditor.findParent(originatingNode, NodeConstants.Types.ACCESS, NodeConstants.Types.GROUP);
@@ -653,8 +655,18 @@
}
if (originatingNode.getParent() == groupNode) {
+ //anything logically applied after the join and is
+ //dependent upon the cardinality prevents us from optimizing.
+ if (aggs && RuleRemoveOptionalJoins.isCardinalityDependent((AggregateSymbol)aggregateSymbol)) {
+ return null;
+ }
continue;
}
+
+ if (aggs && ((AggregateSymbol)aggregateSymbol).isDistinct()) {
+ //TODO: support distinct
+ continue;
+ }
List<T> symbols = result.get(originatingNode);
if (symbols == null) {
Modified: branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-01 15:31:51 UTC (rev 2894)
+++ branches/7.1.x/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-01 17:34:53 UTC (rev 2895)
@@ -274,18 +274,29 @@
static boolean areAggregatesCardinalityDependent(Set<AggregateSymbol> aggs) {
for (AggregateSymbol aggregateSymbol : aggs) {
- switch (aggregateSymbol.getAggregateFunction()) {
- case COUNT:
- case AVG:
- case STDDEV_POP:
- case STDDEV_SAMP:
- case VAR_POP:
- case VAR_SAMP:
+ if (isCardinalityDependent(aggregateSymbol)) {
return true;
}
}
return false;
}
+
+ static boolean isCardinalityDependent(AggregateSymbol aggregateSymbol) {
+ if (aggregateSymbol.isDistinct()) {
+ return false;
+ }
+ switch (aggregateSymbol.getAggregateFunction()) {
+ case COUNT:
+ case AVG:
+ case STDDEV_POP:
+ case STDDEV_SAMP:
+ case VAR_POP:
+ case VAR_SAMP:
+ case SUM:
+ return true;
+ }
+ return false;
+ }
public String toString() {
return "RuleRemoveOptionalJoins"; //$NON-NLS-1$
Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-02-01 15:31:51 UTC (rev 2894)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-02-01 17:34:53 UTC (rev 2895)
@@ -104,7 +104,7 @@
capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
capFinder.addCapabilities("BQT2", caps); //$NON-NLS-1$
- String sql = "SELECT a12.intkey, MAX(a12.stringkey), SUM(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
+ String sql = "SELECT a12.intkey, MAX(a12.stringkey), MIN(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null, capFinder,
new String[] {"SELECT g_0.stringkey, g_0.intkey, g_0.intnum FROM bqt2.smalla AS g_0 GROUP BY g_0.stringkey, g_0.intkey, g_0.intnum", "SELECT g_0.stringkey, g_0.intnum FROM bqt1.smalla AS g_0"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
@@ -126,6 +126,37 @@
});
}
+ @Test public void testAggregateOfJoinExpression1() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.QUERY_FROM_GROUP_ALIAS, true);
+ caps.setCapabilitySupport(Capability.QUERY_ORDERBY, false);
+ caps.setFunctionSupport("convert", true); //$NON-NLS-1$
+ capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
+ capFinder.addCapabilities("BQT2", caps); //$NON-NLS-1$
+
+ String sql = "SELECT a12.intkey, MAX(a12.stringkey), SUM(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null, capFinder,
+ new String[] {"SELECT g_0.stringkey, g_0.intkey, g_0.intnum FROM bqt2.smalla AS g_0", "SELECT g_0.stringkey, g_0.intnum FROM bqt1.smalla AS g_0"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ }
+
/**
* Note that even though this grouping is join invariant, we still do not remove the top level group by
* since we are not checking the uniqueness of the x side join expressions
@@ -205,7 +236,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
metadata,
null, getAggregatesFinder(),
- new String[] {"SELECT DISTINCT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, SUM(g_0.o_amount) AS c_2 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, SUM(g_0.o_amount) AS c_2 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING );
TestOptimizer.checkNodeTypes(plan, new int[] {
@@ -235,7 +266,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
metadata,
null, getAggregatesFinder(),
- new String[] {"SELECT DISTINCT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, MAX(g_0.o_amount) AS c_2, SUM(g_0.o_amount) AS c_3 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, MAX(g_0.o_amount) AS c_2, SUM(g_0.o_amount) AS c_3 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING );
TestOptimizer.checkNodeTypes(plan, new int[] {
@@ -377,8 +408,7 @@
}
/**
- * Test to ensure count(*) isn't mistakenly pushed to either side, but that
- * grouping can still be.
+ * Test to ensure count(*) isn't mistakenly pushed to either side
*/
@Test public void testCase5724() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
@@ -392,7 +422,7 @@
"select count(*), a.intnum from bqt1.smalla as a, bqt2.smallb as b where a.intkey = b.intkey group by a.intnum", //$NON-NLS-1$
metadata, null, capFinder,
new String[] {
- "SELECT a.intkey, a.intnum FROM bqt1.smalla AS a group by a.intkey, a.intnum", "SELECT b.intkey FROM bqt2.smallb AS b"}, //$NON-NLS-1$ //$NON-NLS-2$
+ "SELECT a.intkey, a.intnum FROM bqt1.smalla AS a", "SELECT b.intkey FROM bqt2.smallb AS b"}, //$NON-NLS-1$ //$NON-NLS-2$
true);
TestOptimizer.checkNodeTypes(plan, new int[] {
Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 15:31:51 UTC (rev 2894)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 17:34:53 UTC (rev 2895)
@@ -69,6 +69,7 @@
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.FakeFunctionMetadataSource;
import org.teiid.query.optimizer.QueryOptimizer;
+import org.teiid.query.optimizer.TestAggregatePushdown;
import org.teiid.query.optimizer.TestOptimizer;
import org.teiid.query.optimizer.TestRuleRaiseNull;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
@@ -96,6 +97,7 @@
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
+import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.query.unittest.TimestampUtil;
import org.teiid.query.util.CommandContext;
import org.teiid.query.validator.Validator;
Modified: branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
===================================================================
--- branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-02-01 15:31:51 UTC (rev 2894)
+++ branches/7.1.x/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-02-01 17:34:53 UTC (rev 2895)
@@ -390,8 +390,8 @@
List<String> expectedQueries = new ArrayList<String>(6);
for (int i = 0; i < 3; i++) {
- expectedQueries.add("SELECT DISTINCT g_0.id AS c_0, g_0.first AS c_1, g_0.last AS c_2 FROM CustomerMaster.Customers AS g_0 WHERE g_0.first = 'Miles' ORDER BY c_0"); //$NON-NLS-1$
- expectedQueries.add("SELECT DISTINCT g_0.id AS c_0, g_0.amount AS c_1 FROM Europe.CustAccts AS g_0 WHERE g_0.id = 100 ORDER BY c_0"); //$NON-NLS-1$
+ expectedQueries.add("SELECT g_0.id AS c_0, g_0.first AS c_1, g_0.last AS c_2 FROM CustomerMaster.Customers AS g_0 WHERE g_0.first = 'Miles' ORDER BY c_0"); //$NON-NLS-1$
+ expectedQueries.add("SELECT g_0.id AS c_0, g_0.amount AS c_1 FROM Europe.CustAccts AS g_0 WHERE g_0.id = 100 ORDER BY c_0"); //$NON-NLS-1$
}
assertEquals(expectedQueries, dataManager.getQueries());
14 years, 10 months
teiid SVN: r2894 - in trunk/engine/src: test/java/org/teiid/query/optimizer and 1 other directories.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-02-01 10:31:51 -0500 (Tue, 01 Feb 2011)
New Revision: 2894
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
Log:
TEIID-1458 fix to ensure aggregates that need computed after a join and are cardinality dependent return the proper value
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-02-01 15:26:05 UTC (rev 2893)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-02-01 15:31:51 UTC (rev 2894)
@@ -530,8 +530,11 @@
CapabilitiesFinder capFinder) throws TeiidComponentException,
QueryMetadataException, QueryPlannerException {
- Map<PlanNode, List<AggregateSymbol>> aggregateMap = createNodeMapping(groupNode, allAggregates);
- Map<PlanNode, List<SingleElementSymbol>> groupingMap = createNodeMapping(groupNode, groupingExpressions);
+ Map<PlanNode, List<AggregateSymbol>> aggregateMap = createNodeMapping(groupNode, allAggregates, true);
+ if (aggregateMap == null) {
+ return;
+ }
+ Map<PlanNode, List<SingleElementSymbol>> groupingMap = createNodeMapping(groupNode, groupingExpressions, false);
Set<PlanNode> possibleTargetNodes = new HashSet<PlanNode>(aggregateMap.keySet());
possibleTargetNodes.addAll(groupingMap.keySet());
@@ -707,26 +710,25 @@
}
private <T extends SingleElementSymbol> Map<PlanNode, List<T>> createNodeMapping(PlanNode groupNode,
- Collection<T> expressions) {
+ Collection<T> expressions, boolean aggs) {
Map<PlanNode, List<T>> result = new HashMap<PlanNode, List<T>>();
if (expressions == null) {
return result;
}
for (T aggregateSymbol : expressions) {
- if (aggregateSymbol instanceof AggregateSymbol) {
- AggregateSymbol partitionAgg = (AggregateSymbol)aggregateSymbol;
- if (partitionAgg.isDistinct()) {
- continue; //currently we cann't consider distinct aggs
- }
- }
-
+ if (aggs && ((AggregateSymbol)aggregateSymbol).getExpression() == null) {
+ return null; //count(*) is not yet handled. a general approach would be count(*) => count(r.col) * count(l.col), but the logic here assumes a simpler initial mapping
+ }
Set<GroupSymbol> groups = GroupsUsedByElementsVisitor.getGroups(aggregateSymbol);
if (groups.isEmpty()) {
- continue;
+ continue;
}
PlanNode originatingNode = FrameUtil.findOriginatingNode(groupNode, groups);
if (originatingNode == null) {
- continue;
+ if (aggs) {
+ return null; //should never happen
+ }
+ continue;
}
PlanNode parentAccess = NodeEditor.findParent(originatingNode, NodeConstants.Types.ACCESS, NodeConstants.Types.GROUP);
@@ -739,8 +741,18 @@
}
if (originatingNode.getParent() == groupNode) {
+ //anything logically applied after the join and is
+ //dependent upon the cardinality prevents us from optimizing.
+ if (aggs && RuleRemoveOptionalJoins.isCardinalityDependent((AggregateSymbol)aggregateSymbol)) {
+ return null;
+ }
continue;
}
+
+ if (aggs && ((AggregateSymbol)aggregateSymbol).isDistinct()) {
+ //TODO: support distinct
+ continue;
+ }
List<T> symbols = result.get(originatingNode);
if (symbols == null) {
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-01 15:26:05 UTC (rev 2893)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRemoveOptionalJoins.java 2011-02-01 15:31:51 UTC (rev 2894)
@@ -274,18 +274,29 @@
static boolean areAggregatesCardinalityDependent(Set<AggregateSymbol> aggs) {
for (AggregateSymbol aggregateSymbol : aggs) {
- switch (aggregateSymbol.getAggregateFunction()) {
- case COUNT:
- case AVG:
- case STDDEV_POP:
- case STDDEV_SAMP:
- case VAR_POP:
- case VAR_SAMP:
+ if (isCardinalityDependent(aggregateSymbol)) {
return true;
}
}
return false;
}
+
+ static boolean isCardinalityDependent(AggregateSymbol aggregateSymbol) {
+ if (aggregateSymbol.isDistinct()) {
+ return false;
+ }
+ switch (aggregateSymbol.getAggregateFunction()) {
+ case COUNT:
+ case AVG:
+ case STDDEV_POP:
+ case STDDEV_SAMP:
+ case VAR_POP:
+ case VAR_SAMP:
+ case SUM:
+ return true;
+ }
+ return false;
+ }
public String toString() {
return "RuleRemoveOptionalJoins"; //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-02-01 15:26:05 UTC (rev 2893)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-02-01 15:31:51 UTC (rev 2894)
@@ -104,7 +104,7 @@
capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
capFinder.addCapabilities("BQT2", caps); //$NON-NLS-1$
- String sql = "SELECT a12.intkey, MAX(a12.stringkey), SUM(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
+ String sql = "SELECT a12.intkey, MAX(a12.stringkey), MIN(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null, capFinder,
new String[] {"SELECT g_0.stringkey, g_0.intkey, g_0.intnum FROM bqt2.smalla AS g_0 GROUP BY g_0.stringkey, g_0.intkey, g_0.intnum", "SELECT g_0.stringkey, g_0.intnum FROM bqt1.smalla AS g_0"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
@@ -126,6 +126,37 @@
});
}
+ @Test public void testAggregateOfJoinExpression1() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.QUERY_FROM_GROUP_ALIAS, true);
+ caps.setCapabilitySupport(Capability.QUERY_ORDERBY, false);
+ caps.setFunctionSupport("convert", true); //$NON-NLS-1$
+ capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
+ capFinder.addCapabilities("BQT2", caps); //$NON-NLS-1$
+
+ String sql = "SELECT a12.intkey, MAX(a12.stringkey), SUM(a11.intnum+a12.intnum) FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey GROUP BY a12.intkey"; //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql, FakeMetadataFactory.exampleBQTCached(), null, capFinder,
+ new String[] {"SELECT g_0.stringkey, g_0.intkey, g_0.intnum FROM bqt2.smalla AS g_0", "SELECT g_0.stringkey, g_0.intnum FROM bqt1.smalla AS g_0"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ }
+
/**
* Note that even though this grouping is join invariant, we still do not remove the top level group by
* since we are not checking the uniqueness of the x side join expressions
@@ -205,7 +236,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
metadata,
null, getAggregatesFinder(),
- new String[] {"SELECT DISTINCT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, SUM(g_0.o_amount) AS c_2 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, SUM(g_0.o_amount) AS c_2 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING );
TestOptimizer.checkNodeTypes(plan, new int[] {
@@ -235,7 +266,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
metadata,
null, getAggregatesFinder(),
- new String[] {"SELECT DISTINCT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, MAX(g_0.o_amount) AS c_2, SUM(g_0.o_amount) AS c_3 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.p_productid AS c_0 FROM m2.product AS g_0 WHERE g_0.p_divid = 100 ORDER BY c_0", "SELECT g_0.o_productid AS c_0, g_0.o_dealerid AS c_1, MAX(g_0.o_amount) AS c_2, SUM(g_0.o_amount) AS c_3 FROM m1.\"order\" AS g_0, m1.dealer AS g_1 WHERE (g_0.o_dealerid = g_1.d_dealerid) AND (g_1.d_state = 'CA') AND (g_0.o_productid IN (<dependent values>)) GROUP BY g_0.o_productid, g_0.o_dealerid ORDER BY c_0"}, //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING );
TestOptimizer.checkNodeTypes(plan, new int[] {
@@ -377,8 +408,7 @@
}
/**
- * Test to ensure count(*) isn't mistakenly pushed to either side, but that
- * grouping can still be.
+ * Test to ensure count(*) isn't mistakenly pushed to either side
*/
@Test public void testCase5724() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
@@ -392,7 +422,7 @@
"select count(*), a.intnum from bqt1.smalla as a, bqt2.smallb as b where a.intkey = b.intkey group by a.intnum", //$NON-NLS-1$
metadata, null, capFinder,
new String[] {
- "SELECT a.intkey, a.intnum FROM bqt1.smalla AS a group by a.intkey, a.intnum", "SELECT b.intkey FROM bqt2.smallb AS b"}, //$NON-NLS-1$ //$NON-NLS-2$
+ "SELECT a.intkey, a.intnum FROM bqt1.smalla AS a", "SELECT b.intkey FROM bqt2.smallb AS b"}, //$NON-NLS-1$ //$NON-NLS-2$
true);
TestOptimizer.checkNodeTypes(plan, new int[] {
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 15:26:05 UTC (rev 2893)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-02-01 15:31:51 UTC (rev 2894)
@@ -69,6 +69,7 @@
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.FakeFunctionMetadataSource;
import org.teiid.query.optimizer.QueryOptimizer;
+import org.teiid.query.optimizer.TestAggregatePushdown;
import org.teiid.query.optimizer.TestOptimizer;
import org.teiid.query.optimizer.TestRuleRaiseNull;
import org.teiid.query.optimizer.TestOptimizer.ComparisonMode;
@@ -96,6 +97,7 @@
import org.teiid.query.unittest.FakeMetadataFactory;
import org.teiid.query.unittest.FakeMetadataObject;
import org.teiid.query.unittest.FakeMetadataStore;
+import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.query.unittest.TimestampUtil;
import org.teiid.query.util.CommandContext;
import org.teiid.query.validator.Validator;
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-02-01 15:26:05 UTC (rev 2893)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-02-01 15:31:51 UTC (rev 2894)
@@ -390,8 +390,8 @@
List<String> expectedQueries = new ArrayList<String>(6);
for (int i = 0; i < 3; i++) {
- expectedQueries.add("SELECT DISTINCT g_0.id AS c_0, g_0.first AS c_1, g_0.last AS c_2 FROM CustomerMaster.Customers AS g_0 WHERE g_0.first = 'Miles' ORDER BY c_0"); //$NON-NLS-1$
- expectedQueries.add("SELECT DISTINCT g_0.id AS c_0, g_0.amount AS c_1 FROM Europe.CustAccts AS g_0 WHERE g_0.id = 100 ORDER BY c_0"); //$NON-NLS-1$
+ expectedQueries.add("SELECT g_0.id AS c_0, g_0.first AS c_1, g_0.last AS c_2 FROM CustomerMaster.Customers AS g_0 WHERE g_0.first = 'Miles' ORDER BY c_0"); //$NON-NLS-1$
+ expectedQueries.add("SELECT g_0.id AS c_0, g_0.amount AS c_1 FROM Europe.CustAccts AS g_0 WHERE g_0.id = 100 ORDER BY c_0"); //$NON-NLS-1$
}
assertEquals(expectedQueries, dataManager.getQueries());
14 years, 10 months
teiid SVN: r2893 - branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process.
by teiid-commits@lists.jboss.org
Author: rareddy
Date: 2011-02-01 10:26:05 -0500 (Tue, 01 Feb 2011)
New Revision: 2893
Modified:
branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
Log:
TEIID-1439: Making the matview cache as expiring cache. This will eliminate the ClassCastException and also correctly configure the mat view cache.
Modified: branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java
===================================================================
--- branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2011-02-01 14:59:38 UTC (rev 2892)
+++ branches/7.1.x/engine/src/main/java/org/teiid/dqp/internal/process/DQPCore.java 2011-02-01 15:26:05 UTC (rev 2893)
@@ -705,7 +705,7 @@
this.processWorkerPool = new ThreadReuseExecutor(DQPConfiguration.PROCESS_PLAN_QUEUE_NAME, config.getMaxThreads());
if (cacheFactory.isReplicated()) {
- matTables = new SessionAwareCache<CachedResults>(this.cacheFactory, SessionAwareCache.Type.RESULTSET, new CacheConfiguration(Policy.LRU, -1, -1, "MaterilizationTables")); //$NON-NLS-1$
+ matTables = new SessionAwareCache<CachedResults>(this.cacheFactory, SessionAwareCache.Type.RESULTSET, new CacheConfiguration(Policy.EXPIRATION, -1, -1, "MaterilizationTables")); //$NON-NLS-1$
matTables.setBufferManager(this.bufferManager);
}
14 years, 10 months
teiid SVN: r2892 - in branches/7.1.x/client/src: test/java/org/teiid/jdbc and 1 other directory.
by teiid-commits@lists.jboss.org
Author: shawkins
Date: 2011-02-01 09:59:38 -0500 (Tue, 01 Feb 2011)
New Revision: 2892
Modified:
branches/7.1.x/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
branches/7.1.x/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java
Log:
TEIID-1456 adding a check for exceptions to resultsetimpl
Modified: branches/7.1.x/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java
===================================================================
--- branches/7.1.x/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2011-01-31 21:12:16 UTC (rev 2891)
+++ branches/7.1.x/client/src/main/java/org/teiid/jdbc/ResultSetImpl.java 2011-02-01 14:59:38 UTC (rev 2892)
@@ -48,6 +48,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.logging.Level;
import java.util.logging.Logger;
import org.teiid.client.ResultsMessage;
@@ -146,6 +147,9 @@
rmetadata = new FilteredResultsMetadata(rmetadata, resultColumns);
}
this.fetchSize = statement.getFetchSize();
+ if (logger.isLoggable(Level.FINER)) {
+ logger.finer("Creating ResultSet requestID: " + requestID + " beginRow: " + resultsMsg.getFirstRow() + " resultsColumns: " + resultColumns + " parameters: " + parameters); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
}
public void setMaxFieldSize(int maxFieldSize) {
@@ -356,7 +360,7 @@
}
public Batch requestBatch(int beginRow) throws SQLException{
- logger.fine("CursorResultsImpl.requestBatch] thread name: " + Thread.currentThread().getName() + " requestID: " + requestID + " beginRow: " + beginRow ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ logger.finer("requestBatch requestID: " + requestID + " beginRow: " + beginRow ); //$NON-NLS-1$ //$NON-NLS-2$
checkClosed();
try {
ResultsFuture<ResultsMessage> results = statement.getDQP().processCursorRequest(requestID, beginRow, fetchSize);
@@ -365,6 +369,11 @@
timeoutSeconds = Integer.MAX_VALUE;
}
ResultsMessage currentResultMsg = results.get(timeoutSeconds, TimeUnit.SECONDS);
+
+ if (currentResultMsg.getException() != null) {
+ throw TeiidSQLException.create(currentResultMsg.getException());
+ }
+
this.accumulateWarnings(currentResultMsg);
return getCurrentBatch(currentResultMsg);
} catch (TeiidProcessingException e) {
Modified: branches/7.1.x/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java
===================================================================
--- branches/7.1.x/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java 2011-01-31 21:12:16 UTC (rev 2891)
+++ branches/7.1.x/client/src/test/java/org/teiid/jdbc/TestAllResultsImpl.java 2011-02-01 14:59:38 UTC (rev 2892)
@@ -41,6 +41,7 @@
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
+import org.mockito.Mockito;
import org.teiid.client.DQP;
import org.teiid.client.RequestMessage;
import org.teiid.client.ResultsMessage;
@@ -696,6 +697,19 @@
assertTrue(rs.previous());
}
}
+
+ @Test(expected=TeiidSQLException.class) public void testResultsMessageException() throws Exception {
+ ResultsMessage resultsMsg = exampleMessage(exampleResults1(1), new String[] { "IntNum" }, new String[] { JDBCSQLTypeInfo.INTEGER }); //$NON-NLS-1$
+ resultsMsg.setFinalRow(-1);
+ ResultsMessage next = new ResultsMessage();
+ next.setException(new Throwable());
+ ResultsFuture<ResultsMessage> rf = new ResultsFuture<ResultsMessage>();
+ rf.getResultsReceiver().receiveResults(next);
+ Mockito.stub(statement.getDQP().processCursorRequest(0, 2, 0)).toReturn(rf);
+ ResultSetImpl cs = new ResultSetImpl(resultsMsg, statement, null, 2);
+ cs.next();
+ cs.next();
+ }
static ResultSetImpl helpTestBatching(StatementImpl statement, int fetchSize, int batchLength,
int totalLength) throws InterruptedException, ExecutionException,
14 years, 10 months