Author: shawkins
Date: 2011-07-19 23:27:02 -0400 (Tue, 19 Jul 2011)
New Revision: 3317
Added:
trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
Removed:
trunk/engine/src/main/java/org/teiid/core/id/IntegerID.java
trunk/engine/src/main/java/org/teiid/core/id/IntegerIDFactory.java
trunk/engine/src/main/java/org/teiid/core/id/InvalidIDException.java
trunk/engine/src/main/java/org/teiid/core/id/LongID.java
trunk/engine/src/main/java/org/teiid/core/id/LongIDFactory.java
trunk/engine/src/main/java/org/teiid/core/id/ObjectID.java
trunk/engine/src/main/java/org/teiid/core/id/ObjectIDFactory.java
trunk/engine/src/main/java/org/teiid/core/id/ParsedObjectID.java
trunk/engine/src/main/java/org/teiid/core/id/StringID.java
trunk/engine/src/main/java/org/teiid/core/id/StringIDFactory.java
trunk/engine/src/main/java/org/teiid/core/id/UUIDFactory.java
trunk/engine/src/test/java/org/teiid/core/id/
Modified:
trunk/api/src/main/java/org/teiid/language/AggregateFunction.java
trunk/api/src/main/java/org/teiid/language/visitor/HierarchyVisitor.java
trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
trunk/engine/src/main/java/org/teiid/core/id/IDGenerator.java
trunk/engine/src/main/java/org/teiid/core/id/UUID.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java
trunk/engine/src/main/java/org/teiid/query/optimizer/BatchedUpdatePlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlaceAccess.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseNull.java
trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/lang/GroupBy.java
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/AliasSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ElementSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/ExpressionSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ElementCollectorVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/GroupsUsedByElementsVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestInlineView.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java
trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
trunk/engine/src/test/java/org/teiid/query/optimizer/xml/TestXMLPlanner.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestSearchedCaseExpression.java
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java
trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java
Log:
TEIID-1676 TEIID-1667 changing base aggregate planning to use an symbolic planning form.
beginnings of window function support. fix for cardinality dependent aggregate
decomposition
Modified: trunk/api/src/main/java/org/teiid/language/AggregateFunction.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/AggregateFunction.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/api/src/main/java/org/teiid/language/AggregateFunction.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -43,6 +43,7 @@
private String aggName;
private boolean isDistinct;
private Class<?> type;
+ private Expression condition;
public AggregateFunction(String aggName, boolean isDistinct, Expression exp,
Class<?> type) {
this.expression = exp;
@@ -118,5 +119,17 @@
public void setType(Class<?> type) {
this.type = type;
}
+
+ /**
+ *
+ * @return the filter clause condition
+ */
+ public Expression getCondition() {
+ return condition;
+ }
+
+ public void setCondition(Expression condition) {
+ this.condition = condition;
+ }
}
Modified: trunk/api/src/main/java/org/teiid/language/visitor/HierarchyVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/HierarchyVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/api/src/main/java/org/teiid/language/visitor/HierarchyVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -79,6 +79,7 @@
public void visit(AggregateFunction obj) {
visitNode(obj.getExpression());
+ visitNode(obj.getCondition());
}
public void visit(BatchedUpdates obj) {
Modified: trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java
===================================================================
--- trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/api/src/main/java/org/teiid/language/visitor/SQLStringVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -60,6 +60,7 @@
import org.teiid.language.Not;
import org.teiid.language.OrderBy;
import org.teiid.language.QueryExpression;
+import org.teiid.language.SQLConstants;
import org.teiid.language.ScalarSubquery;
import org.teiid.language.SearchedCase;
import org.teiid.language.SearchedWhenClause;
@@ -174,11 +175,22 @@
}
if (obj.getExpression() == null) {
- buffer.append(Tokens.ALL_COLS);
+ if (SQLConstants.NonReserved.COUNT.equalsIgnoreCase(obj.getName())) {
+ buffer.append(Tokens.ALL_COLS);
+ }
} else {
append(obj.getExpression());
}
buffer.append(Tokens.RPAREN);
+ if (obj.getCondition() != null) {
+ buffer.append(Tokens.SPACE);
+ buffer.append(FILTER);
+ buffer.append(Tokens.LPAREN);
+ buffer.append(WHERE);
+ buffer.append(Tokens.SPACE);
+ append(obj.getCondition());
+ buffer.append(Tokens.RPAREN);
+ }
}
public void visit(Comparison obj) {
Modified: trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java
===================================================================
--- trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/api/src/main/java/org/teiid/translator/ExecutionFactory.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -860,5 +860,31 @@
public boolean supportsCommonTableExpressions() {
return false;
}
+
+ /**
+ * @return true if Advanced OLAP operations are supporting
+ * including the aggregate function filter clause.
+ * @since 7.5
+ */
+ public boolean supportsAdvancedOlapOperations() {
+ return false;
+ }
+
+ /**
+ * @return true if Elementary OLAP operations are supporting
+ * including window functions
+ * @since 7.5
+ */
+ public boolean supportsElementaryOlapOperations() {
+ return false;
+ }
+
+ /**
+ * @return true if array_agg is supported
+ * @since 7.5
+ */
+ public boolean supportsArrayAgg() {
+ return false;
+ }
}
Modified: trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml
===================================================================
---
trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/documentation/reference/src/main/docbook/en-US/content/sql_support.xml 2011-07-20
03:27:02 UTC (rev 3317)
@@ -264,13 +264,22 @@
</para>
</listitem>
<listitem>
- <para>Aggregate functions may only be used in the HAVING or SELECT
clauses and may not be nested within another aggregate function.
+ <para>Aggregate functions cannot be used in FROM, GROUP BY, or WHERE
clauses without an intervening query expression.
</para>
</listitem>
<listitem>
+ <para>Aggregate functions cannot be nested within another aggregate
function without an intervening query expression.
+ </para>
+ </listitem>
+ <listitem>
<para>Aggregate functions may be nested inside other functions.
</para>
</listitem>
+ <listitem>
+ <para>Any aggregate function may take an optional FILTER clasue of the
form <synopsis label="Usage">FILTER ( WHERE condition )</synopsis>.
The condition may be any boolean value expression that does not contain a subquery or a
correlated variable.
+ The filter will logically be evaluated for each row prior to the grouping
operation. If false the aggregate function will not accumulate a value for the given row.
+ </para>
+ </listitem>
</itemizedlist>
<para>
For more information on aggregates, see the sections on GROUP BY or HAVING.
Modified: trunk/engine/src/main/java/org/teiid/core/id/IDGenerator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/IDGenerator.java 2011-07-19 13:41:13 UTC
(rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/IDGenerator.java 2011-07-20 03:27:02 UTC
(rev 3317)
@@ -22,306 +22,17 @@
package org.teiid.core.id;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import org.teiid.core.CorePlugin;
-
-
/**
* IDGenerator
*/
public class IDGenerator {
- private static final IDGenerator INSTANCE = new IDGenerator();
-
- /**
- * Obtain the shared instance of this class.
- * @return the statically shared instance of this class.
- */
- public static IDGenerator getInstance() {
- return INSTANCE;
- }
-
- /** ObjectIDFactory instances keyed by protocol */
- private final Map factories;
- private final Set protocols;
+ private int id;
+
+ public int nextInt() {
+ return id++;
+ }
- private ObjectIDFactory defaultFactory;
-
- public IDGenerator() {
- this.factories = new HashMap();
- this.protocols = new HashSet();
-
- // Initialize default factory ...
- final ObjectIDFactory newDefaultFactory = new UUIDFactory();
- addFactory( newDefaultFactory );
- if ( !this.hasDefaultFactory() ) {
- this.setDefaultFactory(newDefaultFactory);
- }
- }
-
- /**
- * Method that creates and adds to this generator all the built-in factories, and if
there is no default
- * factory, set the default factory to the {@link UUIDFactory}.
- * This method may be called multiple times without side effect.
- */
- public void addBuiltInFactories() {
- // Add the UUID factory as the default ...
- final ObjectIDFactory newDefaultFactory = new UUIDFactory();
- addFactory( newDefaultFactory );
- if ( !this.hasDefaultFactory() ) {
- this.setDefaultFactory(newDefaultFactory);
- }
- addFactory( new IntegerIDFactory() );
- addFactory( new LongIDFactory() );
- addFactory( new StringIDFactory() );
- }
-
- /**
- * Supply to this generator a new factory for a type of {@link ObjectID}.
- * This method has no effect if the factory is null, or if this generator already
knows
- * about the factory.
- * @param factory the new factory
- */
- public void addFactory( final ObjectIDFactory factory ) {
- if ( factory == null ) {
- return;
- }
- final String protocol = factory.getProtocol();
-
- // See if the factory is already known ...
- if ( !this.factories.containsKey(protocol) ) {
- this.factories.put(protocol,factory);
- }
- this.protocols.add(protocol);
- }
-
- /**
- * Remove a factory from this generator.
- * This method has no effect if the supplied protocol doesn't match the protocol
of any descriptor
- * known to this generator.
- * @param protocol the protocol for which the factory is to be removed
- * @return whether a factory was found and removed for the supplied protocol
- */
- public boolean removeFactory(String protocol) {
- if ( protocol == null ) {
- return false;
- }
- final Object previous = this.factories.remove(protocol);
- if ( previous != null ) {
- this.protocols.remove(protocol);
- return true;
- }
- return false;
- }
-
- /**
- * Method to obtain the collection of {@link ObjectIDFactory} instances that each
describe
- * one of the types of {@link ObjectID}s that are available to this generator.
- * @return the collection of {@link ObjectIDFactory} instances.
- */
- public Collection getFactories() {
- // Currently, we get the collection of values from the 'factories' map.
This is okay,
- // because although not terribly efficient, this method is not intended to be
called very
- // frequently
- return factories.values();
- }
-
- /**
- * Method to obtain the collection of {@link ObjectIDFactory} instances that each
describe
- * one of the types of {@link ObjectID}s that are available to this generator.
- * @return the collection of {@link ObjectIDFactory} instances.
- */
- public ObjectIDFactory getFactory( final String protocol ) {
- return (ObjectIDFactory) this.factories.get(protocol);
- }
-
- /**
- * Method to obtain the set of {@link java.lang.String String} protocols. This is a
utility that merely obtains the
- * protocols from the factories.
- * @return the Set of String protocols; never null
- */
- public Set getProtocols() {
- return factories.keySet();
- }
-
- /**
- * Return whether there is a factory that is used by default for the {@link
#create()} method is invoked.
- * @return true if there is a default factory, or false otherwise
- */
- public boolean hasDefaultFactory() {
- return defaultFactory != null;
- }
-
- /**
- * Get the factory that is used by default for the {@link #create()} method is
invoked.
- * @return the default factory, or null if there is no default factory
- */
- public ObjectIDFactory getDefaultFactory() {
- return defaultFactory;
- }
-
- /**
- * Set the factory that should be used by default for the {@link #create()} method is
invoked.
- * @param factory the factory that should be used by default; may be null if no
default is to be allowed.
- */
- public void setDefaultFactory(final ObjectIDFactory factory) {
- defaultFactory = factory;
- }
-
- /**
- * Set the factory that should be used by default for the {@link #create()} method is
invoked.
- * @param protocol the protocol for factory that should be used by default; may be
null if no default
- * is to be allowed.
- */
- public void setDefaultFactory(final String protocol) {
- final ObjectIDFactory factory = getFactory(protocol); // null if protocol
doesn't match
- defaultFactory = factory;
- }
-
- /**
- * Create a new {@link ObjectID} using the default factory
- * @return the new ObjectID
- */
- public ObjectID create() {
- if ( this.defaultFactory != null ) {
- return this.defaultFactory.create();
- }
- // Invalid protocol
- throw new
IllegalArgumentException(CorePlugin.Util.getString("IDGenerator.No_default_id_factory_has_been_defined"));
//$NON-NLS-1$
- }
-
- /**
- * Create a new {@link ObjectID} for the type specified by the protocol
- * @param protocol the protocol of the type of {@link ObjectID} to be created; may
not be null
- * @return the new ObjectID
- */
- public ObjectID create( final String protocol ) {
- if (protocol == null) {
- final String msg =
CorePlugin.Util.getString("IDGenerator.The_protocol_may_not_be_null");
//$NON-NLS-1$
- throw new IllegalArgumentException(msg);
- }
- // Get the factory ...
- final ObjectIDFactory factory = (ObjectIDFactory) this.factories.get(protocol);
- if ( factory != null ) {
- // Create the new ObjectID ...
- return factory.create();
- }
- // Invalid protocol
- throw new
IllegalArgumentException(CorePlugin.Util.getString("IDGenerator.The_specified_ObjectID_protocol___8",protocol));
//$NON-NLS-1$
- }
-
- /**
- * Convenience method for obtaining the stringified form of an ObjectID.
- * @param id
- * @return
- */
- public String toString( final ObjectID id ) {
- return id.toString();
- }
-
- /**
- * Convenience method for obtaining the stringified form of an ObjectID.
- * @param id
- * @return
- */
- public String toString( final ObjectID id, final char delim ) {
- return id.toString(delim);
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param id the stringified id of the form <code>protocol:value</code>,
where
- * <code>protocol</code> defines the protocol of the ID, and
<code>value</code
- * contains the global identifier value; may never be null
- * @return the ObjectID instance for the stringified ID
- * @throws InvalidIDException if the specified string does not contain a valid
ObjectID
- * or if the protocol is unknown
- */
- public ObjectID stringToObject(String id) throws InvalidIDException {
- if (id == null) {
- final String msg =
CorePlugin.Util.getString("IDGenerator.The_stringified_ID_may_not_be_null");
//$NON-NLS-1$
- throw new IllegalArgumentException(msg);
- }
-
- // Parse the string
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(id,this.protocols);
-
- // Find the appropriate factory and parse the id ...
- final ObjectIDFactory factory = (ObjectIDFactory)
this.factories.get(parsedID.getProtocol());
- ObjectID result = null;
- if ( factory != null ) {
- result = factory.stringWithoutProtocolToObject(parsedID.getRemainder());
- }
- if ( result == null ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("IDGenerator.The_stringified_ObjectID_has_an_unknown_protocol___16")
+ parsedID.getProtocol()); //$NON-NLS-1$
- }
- return result;
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param id the stringified id of the form <code>protocol:value</code>,
where
- * <code>protocol</code> defines the protocol of the ID, and
<code>value</code
- * contains the global identifier value; may never be null
- * @return the ObjectID instance for the stringified ID
- * @throws InvalidIDException if the specified string does not contain a valid
ObjectID
- * or if the protocol is unknown
- */
- public ObjectID stringToObject(String id, String protocol) throws InvalidIDException
{
- if (id == null) {
- final String msg =
CorePlugin.Util.getString("IDGenerator.The_stringified_ID_may_not_be_null");
//$NON-NLS-1$
- throw new IllegalArgumentException(msg);
- }
-
- // Parse the string
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(id,protocol);
-
- // Find the appropriate factory and parse the id ...
- final ObjectIDFactory factory = (ObjectIDFactory)
this.factories.get(parsedID.getProtocol());
- ObjectID result = null;
- if ( factory != null ) {
- result = factory.stringWithoutProtocolToObject(parsedID.getRemainder());
- }
- if ( result == null ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("IDGenerator.The_stringified_ObjectID_has_an_unknown_protocol___16")
+ parsedID.getProtocol()); //$NON-NLS-1$
- }
- return result;
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param id the stringified id of the form <code>protocol:value</code>,
where
- * <code>protocol</code> defines the protocol of the ID, and
<code>value</code
- * contains the global identifier value; may never be null
- * @return the ObjectID instance for the stringified ID
- * @throws InvalidIDException if the specified string does not contain a valid
ObjectID
- * or if the protocol is unknown
- */
- public ObjectID stringToObject(String id, char delim) throws InvalidIDException {
- if (id == null) {
- final String msg =
CorePlugin.Util.getString("IDGenerator.The_stringified_ID_may_not_be_null");
//$NON-NLS-1$
- throw new IllegalArgumentException(msg);
- }
-
- // Parse the string
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(id,delim);
-
- // Find the appropriate factory and parse the id ...
- final ObjectIDFactory factory = (ObjectIDFactory)
this.factories.get(parsedID.getProtocol());
- ObjectID result = null;
- if ( factory != null ) {
- result = factory.stringWithoutProtocolToObject(parsedID.getRemainder());
- }
- if ( result == null ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("IDGenerator.The_stringified_ObjectID_has_an_unknown_protocol___16")
+ parsedID.getProtocol()); //$NON-NLS-1$
- }
- return result;
- }
-
}
Deleted: trunk/engine/src/main/java/org/teiid/core/id/IntegerID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/IntegerID.java 2011-07-19 13:41:13 UTC
(rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/IntegerID.java 2011-07-20 03:27:02 UTC
(rev 3317)
@@ -1,125 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import java.io.Serializable;
-
-import org.teiid.core.util.Assertion;
-
-
-public class IntegerID implements ObjectID, Serializable {
-
- public static final String PROTOCOL = "mmint"; //$NON-NLS-1$
- private int id;
-
- protected IntegerID(int id) {
- this.id = id;
- }
- /**
- * Get hash code for object
- * @return Hash code
- */
- public int hashCode() {
- return this.id;
- }
-
- /**
- /**
- * Returns true if the specified object is semantically equal to this instance.
- * Note: this method is consistent with <code>compareTo()</code>.
- * <p>
- * @param obj the object that this instance is to be compared to.
- * @return whether the object is equal to this object.
- */
- public boolean equals(Object obj) {
- // Check if instances are identical ...
- if ( this == obj ) {
- return true;
- }
-
- // Check if object can be compared to this one
- // (this includes checking for null ) ...
- //if ( this.getClass().isInstance(obj) ) {
- if ( obj instanceof IntegerID ) {
- IntegerID that = (IntegerID) obj;
- return ( this.id == that.id );
- }
-
- // Otherwise not comparable ...
- return false;
- }
- /**
- * Compares this object to another. If the specified object is not an instance of
- * the LongID class, then this method throws a
- * ClassCastException (as instances are comparable only to instances of the same
- * class).
- * Note: this method <i>is</i> consistent with
<code>equals()</code>, meaning
- * that <code>(compare(x, y)==0) == (x.equals(y))</code>.
- * <p>
- * @param obj the object that this instance is to be compared to; may not be null.
- * @return a negative integer, zero, or a positive integer as this object
- * is less than, equal to, or greater than the specified object, respectively.
- * @throws ClassCastException if the specified object's type prevents it
- * from being compared to this instance.
- */
- public int compareTo(Object obj) {
- IntegerID that = (IntegerID) obj; // May throw ClassCastException
- Assertion.isNotNull(obj);
-
- long diff = this.id - that.id;
- if ( diff < 0 ) {
- return -1;
- }
- if ( diff > 0 ) {
- return 1;
- }
- return 0;
- }
-
- /**
- * Returns a string representing the current state of the object.
- * @return the string representation of this instance.
- */
- public String toString(){
- return PROTOCOL + ObjectID.DELIMITER + this.id;
- }
- /**
- * @see org.teiid.core.id.ObjectID#toString(char)
- */
- public String toString(char delim) {
- return PROTOCOL + delim + this.id;
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return PROTOCOL;
- }
-
- public int getValue() {
- return this.id;
- }
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/IntegerIDFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/IntegerIDFactory.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/IntegerIDFactory.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -1,116 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import java.io.Serializable;
-
-import org.teiid.core.CorePlugin;
-
-public class IntegerIDFactory implements ObjectIDFactory, Serializable {
- private int lastID = 0;
- public IntegerIDFactory() {
- }
-
- /**
- * Return the description for the type of ObjectID described by this object.
- * @return the description
- */
- public String getDescription() {
- return CorePlugin.Util.getString("IntegerIDFactory.Description");
//$NON-NLS-1$
- }
-
- protected int getNextValue() {
- return ++lastID;
- }
-
- /**
- * Create a new ObjectID instance using this protocol.
- * @return the new instance
- */
- public ObjectID create(){
- return new IntegerID( getNextValue() );
- }
- /**
- * Return whether the specified ObjectID instance is valid. Only ObjectID instances
- * that are for this protocol will be passed in.
- * <p>
- * This implementation only checks whether the ObjectID is an instance of a LongID.
- * @param id the ID that is to be validated, and which is never null
- * @return true if the instance is valid for this protocol, or false if
- * it is not valid.
- */
- public boolean validate(ObjectID id) {
- if ( id instanceof IntegerID ) {
- return true;
- }
- return false;
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id (the result of {@link ObjectID#toString()}),
- * and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringToObject(String value) throws InvalidIDException {
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(value,IntegerID.PROTOCOL);
- try {
- return new IntegerID( Integer.parseInt(parsedID.getRemainder()) );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("IntegerIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * This method is called by the {@link IDGenerator#stringToObject(String)} method,
which
- * must process the protocol to determine the correct parser to use. As such, it
guarantees
- * that the parser that receives this call can assume that the protocol was equal to
the
- * protocol returned by the parser's {@link ObjectIDDescriptor#getProtocol()}.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringWithoutProtocolToObject(String value) throws InvalidIDException
{
- try {
- return new IntegerID( Integer.parseInt(value) );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("IntegerIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return IntegerID.PROTOCOL;
- }
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/InvalidIDException.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/InvalidIDException.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/InvalidIDException.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -1,70 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import org.teiid.core.CorePlugin;
-import org.teiid.core.TeiidException;
-
-/**
- * Exception which occurs if an error occurs within the server that is not
- * business-related. For instance, if a service or bean is not available
- * or communication fails.
- */
-public class InvalidIDException extends TeiidException {
- private static final String INVALID_ID_MESSAGE =
CorePlugin.Util.getString("InvalidIDException.Invalid_ID_1"); //$NON-NLS-1$
-
- /**
- * No-Arg Constructor
- */
- public InvalidIDException( ) {
- super( );
- }
-
-
- /**
- * Construct an instance of InvalidIDException.
- * @param message
- */
- public InvalidIDException(String message) {
- super(message);
- }
-
- /**
- * Construct an instance of InvalidIDException.
- * @param e
- */
- public InvalidIDException(Throwable e) {
- super(e,INVALID_ID_MESSAGE);
- }
-
-
- /**
- * Construct an instance of InvalidIDException.
- * @param e
- * @param message
- */
- public InvalidIDException(Throwable e, String message) {
- super(e, message);
- }
-
-}
Deleted: trunk/engine/src/main/java/org/teiid/core/id/LongID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/LongID.java 2011-07-19 13:41:13 UTC (rev
3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/LongID.java 2011-07-20 03:27:02 UTC (rev
3317)
@@ -1,126 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import java.io.Serializable;
-
-import org.teiid.core.util.Assertion;
-
-
-public class LongID implements ObjectID, Serializable {
- public static final String PROTOCOL = "mmlong"; //$NON-NLS-1$
-
- private long id;
-
- protected LongID(long id) {
- this.id = id;
- }
- /**
- * Get hash code for object
- * @return Hash code
- */
- public int hashCode() {
- return (int) this.id;
- }
-
- /**
- /**
- * Returns true if the specified object is semantically equal to this instance.
- * Note: this method is consistent with <code>compareTo()</code>.
- * <p>
- * @param obj the object that this instance is to be compared to.
- * @return whether the object is equal to this object.
- */
- public boolean equals(Object obj) {
- // Check if instances are identical ...
- if ( this == obj ) {
- return true;
- }
-
- // Check if object can be compared to this one
- // (this includes checking for null ) ...
- //if ( this.getClass().isInstance(obj) ) {
- if ( obj instanceof LongID ) {
- LongID that = (LongID) obj;
- return ( this.id == that.id );
- }
-
- // Otherwise not comparable ...
- return false;
- }
- /**
- * Compares this object to another. If the specified object is not an instance of
- * the LongID class, then this method throws a
- * ClassCastException (as instances are comparable only to instances of the same
- * class).
- * Note: this method <i>is</i> consistent with
<code>equals()</code>, meaning
- * that <code>(compare(x, y)==0) == (x.equals(y))</code>.
- * <p>
- * @param obj the object that this instance is to be compared to; may not be null.
- * @return a negative integer, zero, or a positive integer as this object
- * is less than, equal to, or greater than the specified object, respectively.
- * @throws ClassCastException if the specified object's type prevents it
- * from being compared to this instance.
- */
- public int compareTo(Object obj) {
- LongID that = (LongID) obj; // May throw ClassCastException
- Assertion.isNotNull(obj);
-
- long diff = this.id - that.id;
- if ( diff < 0 ) {
- return -1;
- }
- if ( diff > 0 ) {
- return 1;
- }
- return 0;
- }
-
- /**
- * Returns a string representing the current state of the object.
- * @return the string representation of this instance.
- */
- public String toString(){
- return PROTOCOL + ObjectID.DELIMITER + this.id;
- }
-
- /**
- * @see org.teiid.core.id.ObjectID#toString(char)
- */
- public String toString(char delim) {
- return PROTOCOL + delim + this.id;
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return PROTOCOL;
- }
-
- public long getValue() {
- return this.id;
- }
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/LongIDFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/LongIDFactory.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/LongIDFactory.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -1,117 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import java.io.Serializable;
-
-import org.teiid.core.CorePlugin;
-
-
-public class LongIDFactory implements ObjectIDFactory, Serializable {
- private long lastID = 0;
- public LongIDFactory() {
- }
-
- /**
- * Return the description for the type of ObjectID described by this object.
- * @return the description
- */
- public String getDescription() {
- return CorePlugin.Util.getString("LongIDFactory.Description");
//$NON-NLS-1$
- }
-
- protected long getNextValue() {
- return ++lastID;
- }
-
- /**
- * Create a new ObjectID instance using this protocol.
- * @return the new instance
- */
- public ObjectID create(){
- return new LongID( getNextValue() );
- }
- /**
- * Return whether the specified ObjectID instance is valid. Only ObjectID instances
- * that are for this protocol will be passed in.
- * <p>
- * This implementation only checks whether the ObjectID is an instance of a LongID.
- * @param id the ID that is to be validated, and which is never null
- * @return true if the instance is valid for this protocol, or false if
- * it is not valid.
- */
- public boolean validate(ObjectID id) {
- if ( id instanceof LongID ) {
- return true;
- }
- return false;
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * This method is called by the {@link IDGenerator#stringToObject(String)} method,
which
- * must process the protocol to determine the correct parser to use. As such, it
guarantees
- * that the parser that receives this call can assume that the protocol was equal to
the
- * protocol returned by the parser's {@link ObjectIDDescriptor#getProtocol()}.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringWithoutProtocolToObject(String value) throws InvalidIDException
{
- try {
- return new LongID( Long.parseLong(value) );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("LongIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id (the result of {@link ObjectID#toString()}),
- * and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringToObject(String value) throws InvalidIDException {
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(value,LongID.PROTOCOL);
- try {
- return new LongID( Long.parseLong(parsedID.getRemainder()) );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("LongIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return LongID.PROTOCOL;
- }
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/ObjectID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/ObjectID.java 2011-07-19 13:41:13 UTC
(rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/ObjectID.java 2011-07-20 03:27:02 UTC
(rev 3317)
@@ -1,63 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-
-
-public interface ObjectID extends Comparable {
-
- char DELIMITER = ':';
-
- /**
- * Compares this object to another. If the specified object is not an instance of
- * the ObjectID class, then this method throws a
- * ClassCastException (as instances are comparable only to instances of the same
- * class).
- * Note: this method <i>is</i> consistent with
<code>equals()</code>, meaning
- * that <code>(compare(x, y)==0) == (x.equals(y))</code>.
- * <p>
- * @param obj the object that this instance is to be compared to; may not be null.
- * @return a negative integer, zero, or a positive integer as this object
- * is less than, equal to, or greater than the specified object, respectively.
- * @throws ClassCastException if the specified object's type prevents it
- * from being compared to this instance.
- */
- int compareTo(Object obj);
- /**
- * Returns a string representing the current state of the object.
- * @return the string representation of this instance.
- */
- String toString();
- /**
- * Returns a string representing the current state of the object.
- * @param delim the delimiter that should be used
- * @return the string representation of this instance.
- */
- String toString( char delim );
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- String getProtocol();
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/ObjectIDFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/ObjectIDFactory.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/ObjectIDFactory.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -1,76 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-
-/**
- * The ObjectIDDescriptor defines the interface that is used to describe a particular
type of
- * {@link ObjectID}.
- */
-public interface ObjectIDFactory {
-
- /**
- * Return the protocol for the type of ObjectID described by this object.
- * @return the protocol
- */
- String getProtocol();
-
- /**
- * Return the description for the type of ObjectID described by this object.
- * @return the description
- */
- String getDescription();
-
- /**
- * Create a new GlobalUID instance using this protocol.
- * @return the new instance
- */
- ObjectID create();
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id (the result of {@link ObjectID#toString()}),
- * and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- ObjectID stringToObject(String value) throws InvalidIDException;
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * This method is called by the {@link IDGenerator#stringToObject(String)} method,
which
- * must process the protocol to determine the correct parser to use. As such, it
guarantees
- * that the parser that receives this call can assume that the protocol was equal to
the
- * protocol returned by the parser's {@link ObjectIDDescriptor#getProtocol()}.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- ObjectID stringWithoutProtocolToObject(String value) throws InvalidIDException;
-
-}
Deleted: trunk/engine/src/main/java/org/teiid/core/id/ParsedObjectID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/ParsedObjectID.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/ParsedObjectID.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -1,88 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.teiid.core.CorePlugin;
-
-
-/**
- * ParsedObjectID
- */
-public class ParsedObjectID {
- private static final int DELIMITER_LENGTH = 1;
- private final String protocol;
- private final String remainder;
-
- protected ParsedObjectID( final String protocol, final String remainder ) {
- this.protocol = protocol;
- this.remainder = remainder;
- }
-
- public String getProtocol() {
- return protocol;
- }
-
- public String getRemainder() {
- return remainder;
- }
-
- public static ParsedObjectID parsedStringifiedObjectID( final String id, final Set
protocols ) throws InvalidIDException {
- final Iterator iter = protocols.iterator();
- while (iter.hasNext()) {
- final String protocol = (String)iter.next();
- if ( id.startsWith(protocol) ) {
- return new
ParsedObjectID(protocol,id.substring(protocol.length()+DELIMITER_LENGTH));
- }
- }
- throw new
InvalidIDException(CorePlugin.Util.getString("ParsedObjectID.The_stringified_ObjectID_does_not_have_a_protocol"));
//$NON-NLS-1$
- }
-
- public static ParsedObjectID parsedStringifiedObjectID( final String id ) throws
InvalidIDException {
- return parsedStringifiedObjectID(id,ObjectID.DELIMITER);
- }
-
- public static ParsedObjectID parsedStringifiedObjectID( final String id, final char
delim ) throws InvalidIDException {
- int index = -1;
- if ( id != null ) {
- // Obtain the protocol from the string
- index = id.indexOf(delim);
- }
- if ( index == -1 ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("ParsedObjectID.The_stringified_ObjectID_does_not_have_a_protocol"));
//$NON-NLS-1$
- }
- return new
ParsedObjectID(id.substring(0,index),id.substring(index+DELIMITER_LENGTH));
- }
-
- public static ParsedObjectID parsedStringifiedObjectID( final String id, final String
expectedProtocol ) throws InvalidIDException {
- if ( expectedProtocol == null ) {
- return new ParsedObjectID("",id); //$NON-NLS-1$
- }
- if ( id.startsWith(expectedProtocol) ) {
- return new
ParsedObjectID(expectedProtocol,id.substring(expectedProtocol.length()+DELIMITER_LENGTH));
- }
- throw new
InvalidIDException(CorePlugin.Util.getString("ParsedObjectID.The_stringified_ObjectID_does_not_have_the_required_protocol_{0}",expectedProtocol));
//$NON-NLS-1$
- }
-
-}
Deleted: trunk/engine/src/main/java/org/teiid/core/id/StringID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/StringID.java 2011-07-19 13:41:13 UTC
(rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/StringID.java 2011-07-20 03:27:02 UTC
(rev 3317)
@@ -1,120 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import java.io.Serializable;
-
-import org.teiid.core.util.Assertion;
-
-
-public class StringID implements ObjectID, Serializable {
- public static final String PROTOCOL = "strid"; //$NON-NLS-1$
-
- private String id;
-
- protected StringID(String id) {
- this.id = id;
- }
- protected StringID(long id) {
- this.id = Long.toString(id);
- }
- /**
- * Get hash code for object
- * @return Hash code
- */
- public int hashCode() {
- return id.hashCode();
- }
-
- /**
- /**
- * Returns true if the specified object is semantically equal to this instance.
- * Note: this method is consistent with <code>compareTo()</code>.
- * <p>
- * @param obj the object that this instance is to be compared to.
- * @return whether the object is equal to this object.
- */
- public boolean equals(Object obj) {
- // Check if instances are identical ...
- if ( this == obj ) {
- return true;
- }
-
- // Check if object can be compared to this one
- // (this includes checking for null ) ...
- //if ( this.getClass().isInstance(obj) ) {
- if ( obj instanceof StringID ) {
- StringID that = (StringID) obj;
- return ( this.id.equals( that.id ) );
- }
-
- // Otherwise not comparable ...
- return false;
- }
- /**
- * Compares this object to another. If the specified object is not an instance of
- * the StringID class, then this method throws a
- * ClassCastException (as instances are comparable only to instances of the same
- * class).
- * Note: this method <i>is</i> consistent with
<code>equals()</code>, meaning
- * that <code>(compare(x, y)==0) == (x.equals(y))</code>.
- * <p>
- * @param obj the object that this instance is to be compared to; may not be null.
- * @return a negative integer, zero, or a positive integer as this object
- * is less than, equal to, or greater than the specified object, respectively.
- * @throws ClassCastException if the specified object's type prevents it
- * from being compared to this instance.
- */
- public int compareTo(Object obj) {
- StringID that = (StringID) obj; // May throw ClassCastException
- Assertion.isNotNull(obj);
- return this.id.compareTo(that.id);
- }
-
- /**
- * Returns a string representing the current state of the object.
- * @return the string representation of this instance.
- */
- public String toString(){
- return PROTOCOL + ObjectID.DELIMITER + this.id;
- }
- /**
- * @see org.teiid.core.id.ObjectID#toString(char)
- */
- public String toString(char delim) {
- return PROTOCOL + delim + this.id;
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return PROTOCOL;
- }
-
- protected String getValue() {
- return this.id;
- }
-}
-
Deleted: trunk/engine/src/main/java/org/teiid/core/id/StringIDFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/StringIDFactory.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/StringIDFactory.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -1,116 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import org.teiid.core.CorePlugin;
-
-
-
-public class StringIDFactory implements ObjectIDFactory {
- private long lastID = 0;
- public StringIDFactory() {
- }
-
- /**
- * Return the description for the type of ObjectID described by this object.
- * @return the description
- */
- public String getDescription() {
- return CorePlugin.Util.getString("StringIDFactory.Description");
//$NON-NLS-1$
- }
-
- protected long getNextValue() {
- return ++lastID;
- }
-
- /**
- * Create a new ObjectID instance using this protocol.
- * @return the new instance
- */
- public ObjectID create(){
- return new StringID( getNextValue() );
- }
- /**
- * Return whether the specified ObjectID instance is valid. Only ObjectID instances
- * that are for this protocol will be passed in.
- * <p>
- * This implementation only checks whether the ObjectID is an instance of a
StringID.
- * @param id the ID that is to be validated, and which is never null
- * @return true if the instance is valid for this protocol, or false if
- * it is not valid.
- */
- public boolean validate(ObjectID id) {
- if ( id instanceof StringID ) {
- return true;
- }
- return false;
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * This method is called by the {@link IDGenerator#stringToObject(String)} method,
which
- * must process the protocol to determine the correct parser to use. As such, it
guarantees
- * that the parser that receives this call can assume that the protocol was equal to
the
- * protocol returned by the parser's {@link ObjectIDDescriptor#getProtocol()}.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringWithoutProtocolToObject(String value) throws InvalidIDException
{
- try {
- return new StringID( value );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("StringIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id (the result of {@link ObjectID#toString()}),
- * and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringToObject(String value) throws InvalidIDException {
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(value,LongID.PROTOCOL);
- try {
- return new StringID( parsedID.getRemainder() );
- } catch ( NumberFormatException e ) {
- throw new
InvalidIDException(CorePlugin.Util.getString("StringIDFactory.The_specified_ID_value_is_invalid",value,getProtocol()));
//$NON-NLS-1$
- }
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return StringID.PROTOCOL;
- }
-}
-
Modified: trunk/engine/src/main/java/org/teiid/core/id/UUID.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/UUID.java 2011-07-19 13:41:13 UTC (rev
3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/UUID.java 2011-07-20 03:27:02 UTC (rev
3317)
@@ -24,10 +24,7 @@
import java.io.Serializable;
-import org.teiid.core.CorePlugin;
-import org.teiid.core.util.Assertion;
-
/**
* <p>This class represents a universally unique identifier, consisting of
* two long integral values. </p>
@@ -35,10 +32,11 @@
* <p>This identifier is supposed to be unique both spatially and temporally.
* It is based on version 4 IETF variant random UUIDs. </p>
*/
-public class UUID implements ObjectID, Serializable {
+public class UUID implements Serializable {
+
+ private static final long serialVersionUID = 4730187208307761197L;
- private static final String NOT_UUID_MESSAGE =
CorePlugin.Util.getString("UUID.ID_must_be_of_type_UUID_1"); //$NON-NLS-1$
- private static final String UNPARSABLE_MESSAGE =
CorePlugin.Util.getString("UUID.ID_must_be_of_type_UUID_to_parse_2");
//$NON-NLS-1$
+ char DELIMITER = ':';
/**
* The variants allowed by the UUID specification.
*/
@@ -78,42 +76,6 @@
}
/**
- * Return the first part of the UUID as a long.
- * @return first part of the UUID as a long
- */
- public static long getPart1(ObjectID id) {
- Assertion.assertTrue((id instanceof UUID), UNPARSABLE_MESSAGE);
-
- UUID uuid = (UUID)id;
- return uuid.uuid.getMostSignificantBits();
- }
-
- /**
- * Return the first part of the UUID as a long.
- * @return first part of the UUID as a long
- */
- public static long getPart2(ObjectID id) {
- Assertion.assertTrue((id instanceof UUID), UNPARSABLE_MESSAGE);
-
- UUID uuid = (UUID)id;
- return uuid.uuid.getLeastSignificantBits();
- }
-
- public static int getVariant(ObjectID id ) {
- Assertion.assertTrue((id instanceof UUID), NOT_UUID_MESSAGE);
-
- UUID uuid = (UUID)id;
- return uuid.uuid.variant();
- }
-
- public static int getVersion(ObjectID id ) {
- Assertion.assertTrue((id instanceof UUID), NOT_UUID_MESSAGE);
-
- UUID uuid = (UUID)id;
- return uuid.uuid.version();
- }
-
- /**
* Return the name of the protocol that this factory uses.
* @return the protocol name
*/
@@ -179,7 +141,7 @@
* @return the string representation of this instance.
*/
public String toString(){
- return toString(ObjectID.DELIMITER);
+ return toString(DELIMITER);
}
/**
@@ -206,20 +168,4 @@
return this.cachedExportableFormUuidString;
}
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and which is never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- */
- public static ObjectID stringToObject(String value) throws InvalidIDException {
- try {
- return new UUID(java.util.UUID.fromString(value));
- } catch ( IllegalArgumentException e ) {
- throw new InvalidIDException(
-
CorePlugin.Util.getString("UUID.InvalidFormatForProtocol",value,PROTOCOL));
//$NON-NLS-1$
- }
- }
-
}
Deleted: trunk/engine/src/main/java/org/teiid/core/id/UUIDFactory.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/core/id/UUIDFactory.java 2011-07-19 13:41:13 UTC
(rev 3316)
+++ trunk/engine/src/main/java/org/teiid/core/id/UUIDFactory.java 2011-07-20 03:27:02 UTC
(rev 3317)
@@ -1,132 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * See the COPYRIGHT.txt file distributed with this work for information
- * regarding copyright ownership. Some portions may be licensed
- * to Red Hat, Inc. under one or more contributor license agreements.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301 USA.
- */
-
-package org.teiid.core.id;
-
-import org.teiid.core.CorePlugin;
-
-/**
- * <p>This class is a factory for generating universally unique identifiers
- * (UUID's). </p>
- *
- * <h3>Output format for UUIDs</h3>
- * <p>UUIDs are output in the following 36-character format:
- * <pre>
- * xxxxxxxx-yyyy-zzzz-cccc-nnnnnnnnnnnn
- * </pre>
- * where x=least significant time component, y=middle significant time component,
- * z=most significant time component multiplexed with version, c=clock sequence
- * multiplexed with variant, and n=node component (random number).
- * </p>
- *
- * <p>The generated ID's conform somewhat to the (now expired) IETF internet
- * draft standard, "UUIDs and GUIDs", DCE spec on UUIDs. </p>
- *
- * <ul>
- * <li>
- * <a
href="http://hegel.ittc.ukans.edu/topics/internet/internet-drafts/dr...
- * UUIDs and GUIDs, P. Leach, R. Salz, 02/05/1998</a>
- * </li>
- * <li>
- * <a
href="http://www.opengroup.org/onlinepubs/009629399/apdxa.htm">
- * DCE Universal Unique Identifier</a>.
- * </li>
- * </ul></p>
- *
- * <p>All references in this code to bit positions as "least significant"
and
- * "most significant" refer to the bits moving from right to left,
respectively.
- * </p>
- */
-public class UUIDFactory implements ObjectIDFactory {
-
- // -------------------------------------------------------------------------
- // C O N S T R U C T O R
- // -------------------------------------------------------------------------
-
- public UUIDFactory() {
- }
-
- // -------------------------------------------------------------------------
- // P U B L I C M E T H O D S
- // -------------------------------------------------------------------------
-
- /**
- * Return the description for the type of ObjectID described by this object.
- * @return the description
- */
- public String getDescription() {
- return CorePlugin.Util.getString("UUIDFactory.Description");
//$NON-NLS-1$
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * This method is called by the {@link IDGenerator#stringToObject(String)} method,
which
- * must process the protocol to determine the correct parser to use. As such, it
guarantees
- * that the parser that receives this call can assume that the protocol was equal to
the
- * protocol returned by the parser's {@link ObjectIDDescriptor#getProtocol()}.
- * @param value the stringified id with the protocol and ObjectID.DELIMITER already
- * removed, and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringWithoutProtocolToObject(String value) throws InvalidIDException
{
- return UUID.stringToObject(value);
- }
-
- /**
- * Attempt to convert the specified string to the appropriate ObjectID instance.
- * @param value the stringified id (the result of {@link ObjectID#toString()}),
- * and should never null or zero length
- * @return the ObjectID instance for the stringified ID if this factory is able
- * to parse the string, or null if the factory is unaware of the specified format.
- * @throws InvalidIDException if the parser is aware of this protocol, but it is of
the wrong
- * format for this type of ObjectID.
- */
- public ObjectID stringToObject(String value) throws InvalidIDException {
- final ParsedObjectID parsedID =
ParsedObjectID.parsedStringifiedObjectID(value,UUID.PROTOCOL);
- return UUID.stringToObject(parsedID.getRemainder());
- }
-
- /**
- * Return the name of the protocol that this factory uses.
- * @return the protocol name
- */
- public String getProtocol() {
- return UUID.PROTOCOL;
- }
-
- // -------------------------------------------------------------------------
- // G E N E R A T I O N M E T H O D S
- // -------------------------------------------------------------------------
-
- /**
- * <p>Create a new ObjectID instance using this protocol. </p>
- * @return Universally unique ID (UUID)
- */
- public ObjectID create() {
- return new UUID(java.util.UUID.randomUUID());
- }
-
-}
-
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/CapabilitiesConverter.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -99,6 +99,9 @@
tgtCaps.setCapabilitySupport(Capability.QUERY_ORDERBY_NULL_ORDERING,
srcCaps.supportsOrderByNullOrdering());
tgtCaps.setCapabilitySupport(Capability.INSERT_WITH_ITERATOR,
srcCaps.supportsInsertWithIterator());
tgtCaps.setCapabilitySupport(Capability.COMMON_TABLE_EXPRESSIONS,
srcCaps.supportsCommonTableExpressions());
+ tgtCaps.setCapabilitySupport(Capability.ADVANCED_OLAP,
srcCaps.supportsAdvancedOlapOperations());
+ tgtCaps.setCapabilitySupport(Capability.ELEMENTARY_OLAP,
srcCaps.supportsAdvancedOlapOperations());
+ tgtCaps.setCapabilitySupport(Capability.QUERY_AGGREGATES_ARRAY,
srcCaps.supportsArrayAgg());
List functions = srcCaps.getSupportedFunctions();
if(functions != null && functions.size() > 0) {
Iterator iter = functions.iterator();
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/LanguageBridgeFactory.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -570,10 +570,12 @@
}
AggregateFunction translate(AggregateSymbol symbol) {
- return new AggregateFunction(symbol.getAggregateFunction().name(),
+ AggregateFunction af = new AggregateFunction(symbol.getAggregateFunction().name(),
symbol.isDistinct(),
translate(symbol.getExpression()),
symbol.getType());
+ af.setCondition(translate(symbol.getCondition()));
+ return af;
}
org.teiid.language.Expression translate(ExpressionSymbol symbol) {
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-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/dqp/internal/process/Request.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -43,7 +43,6 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerIDFactory;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.Assertion;
import org.teiid.dqp.internal.datamgr.ConnectorManagerRepository;
@@ -150,7 +149,6 @@
this.processorDataManager = processorDataManager;
this.transactionService = transactionService;
this.tempTableStore = tempTableStore;
- idGenerator.setDefaultFactory(new IntegerIDFactory());
this.workContext = workContext;
this.requestId = workContext.getRequestID(this.requestMsg.getExecutionId());
this.connectorManagerRepo =
workContext.getVDB().getAttachment(ConnectorManagerRepository.class);
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/BatchedUpdatePlanner.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/BatchedUpdatePlanner.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/BatchedUpdatePlanner.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -30,7 +30,6 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerID;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -142,9 +141,9 @@
}
// If two or more contiguous commands made on the same model were
found, then batch them
if (batch.size() > 1) {
- ProjectNode projectNode = new
ProjectNode(((IntegerID)idGenerator.create()).getValue());
+ ProjectNode projectNode = new
ProjectNode(idGenerator.nextInt());
// Create a BatchedUpdateNode that creates a batched request for
the connector
- BatchedUpdateNode batchNode = new
BatchedUpdateNode(((IntegerID)idGenerator.create()).getValue(),
+ BatchedUpdateNode batchNode = new
BatchedUpdateNode(idGenerator.nextInt(),
batch,
contexts, shouldEvaluate,
modelName);
List symbols = batchedUpdateCommand.getProjectedSymbols();
Modified: trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/optimizer/QueryOptimizer.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -34,7 +34,6 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerIDFactory;
import org.teiid.dqp.internal.process.PreparedPlan;
import org.teiid.metadata.Procedure;
import org.teiid.metadata.FunctionMethod.Determinism;
@@ -99,7 +98,6 @@
// Create an ID generator that can be used for all plans to generate unique data
node IDs
if(idGenerator == null) {
idGenerator = new IDGenerator();
- idGenerator.setDefaultFactory(new IntegerIDFactory());
}
if(debug) {
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/capabilities/SourceCapabilities.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -321,6 +321,9 @@
INSERT_WITH_ITERATOR,
COMMON_TABLE_EXPRESSIONS,
MAX_DEPENDENT_PREDICATES,
+ ADVANCED_OLAP,
+ QUERY_AGGREGATES_ARRAY,
+ ELEMENTARY_OLAP
}
public enum Scope {
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/PlanToProcessConverter.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -32,8 +32,6 @@
import org.teiid.core.CoreConstants;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerID;
-import org.teiid.core.id.IntegerIDFactory;
import org.teiid.core.util.Assertion;
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
@@ -53,6 +51,7 @@
import org.teiid.query.processor.relational.DependentAccessNode;
import org.teiid.query.processor.relational.DependentProcedureAccessNode;
import org.teiid.query.processor.relational.DependentProcedureExecutionNode;
+import org.teiid.query.processor.relational.EnhancedSortMergeJoinStrategy;
import org.teiid.query.processor.relational.GroupingNode;
import org.teiid.query.processor.relational.InsertPlanExecutionNode;
import org.teiid.query.processor.relational.JoinNode;
@@ -61,7 +60,6 @@
import org.teiid.query.processor.relational.NestedLoopJoinStrategy;
import org.teiid.query.processor.relational.NestedTableJoinStrategy;
import org.teiid.query.processor.relational.NullNode;
-import org.teiid.query.processor.relational.EnhancedSortMergeJoinStrategy;
import org.teiid.query.processor.relational.PlanExecutionNode;
import org.teiid.query.processor.relational.ProjectIntoNode;
import org.teiid.query.processor.relational.ProjectNode;
@@ -169,8 +167,7 @@
}
protected int getID() {
- IntegerIDFactory intFactory = (IntegerIDFactory)
idGenerator.getDefaultFactory();
- return ((IntegerID) intFactory.create()).getValue();
+ return idGenerator.nextInt();
}
protected RelationalNode convertNode(PlanNode node)
@@ -377,7 +374,8 @@
break;
case NodeConstants.Types.GROUP:
GroupingNode gnode = new GroupingNode(getID());
- gnode.setGroupingElements( (List) node.getProperty(NodeConstants.Info.GROUP_COLS) );
+ gnode.setGroupingElements( (List<Expression>)
node.getProperty(NodeConstants.Info.GROUP_COLS) );
+ gnode.setOutputMapping((SymbolMap)node.getProperty(NodeConstants.Info.SYMBOL_MAP));
gnode.setRemoveDuplicates(node.hasBooleanProperty(NodeConstants.Info.IS_DUP_REMOVAL));
processNode = gnode;
break;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/RelationalPlanner.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -27,6 +27,8 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -45,9 +47,11 @@
import org.teiid.query.QueryPlugin;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.mapping.relational.QueryNode;
+import org.teiid.query.metadata.BasicQueryMetadata;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataAdapter;
import org.teiid.query.metadata.TempMetadataID;
+import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.QueryOptimizer;
import org.teiid.query.optimizer.TriggerActionPlanner;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
@@ -62,6 +66,8 @@
import org.teiid.query.optimizer.relational.rules.RuleCollapseSource;
import org.teiid.query.optimizer.relational.rules.RuleConstants;
import org.teiid.query.optimizer.relational.rules.RuleMergeCriteria;
+import org.teiid.query.optimizer.relational.rules.RulePlaceAccess;
+import org.teiid.query.optimizer.relational.rules.RulePushAggregates;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.processor.relational.AccessNode;
import org.teiid.query.processor.relational.RelationalPlan;
@@ -104,9 +110,13 @@
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.proc.CreateUpdateProcedureCommand;
import org.teiid.query.sql.proc.TriggerAction;
+import org.teiid.query.sql.symbol.AggregateSymbol;
+import org.teiid.query.sql.symbol.AliasSymbol;
import org.teiid.query.sql.symbol.AllSymbol;
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.GroupSymbol;
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.ScalarSubquery;
@@ -115,6 +125,8 @@
import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.CorrelatedReferenceCollectorVisitor;
+import org.teiid.query.sql.visitor.ElementCollectorVisitor;
+import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.util.CommandContext;
@@ -401,7 +413,7 @@
rules.push(RuleConstants.PLAN_PROCEDURES);
}
if(hints.hasAggregates) {
- rules.push(RuleConstants.PUSH_AGGREGATES);
+ rules.push(new RulePushAggregates(idGenerator));
}
if(hints.hasJoin) {
rules.push(RuleConstants.CHOOSE_DEPENDENT);
@@ -729,9 +741,18 @@
}
// Attach grouping node on top
- if(query.hasAggregates()) {
- plan = attachGrouping(plan, query, hints);
+ Collection<AggregateSymbol> aggs =
AggregateSymbolCollectorVisitor.getAggregates(query.getSelect(), true);
+ boolean hasGrouping = !aggs.isEmpty();
+ if (query.getHaving() != null) {
+ AggregateSymbolCollectorVisitor.getAggregates(query.getHaving(), aggs, null);
+ hasGrouping = true;
}
+ if (query.getGroupBy() != null) {
+ hasGrouping = true;
+ }
+ if(hasGrouping) {
+ plan = attachGrouping(plan, query, aggs);
+ }
// Attach having criteria node on top
if(query.getHaving() != null) {
@@ -982,7 +1003,7 @@
public static PlanNode createSelectNode(final Criteria crit, boolean isHaving) {
PlanNode critNode = NodeFactory.getNewNode(NodeConstants.Types.SELECT);
critNode.setProperty(NodeConstants.Info.SELECT_CRITERIA, crit);
- if (isHaving && !AggregateSymbolCollectorVisitor.getAggregates(crit,
false).isEmpty()) {
+ if (isHaving && !ElementCollectorVisitor.getAggregates(crit,
false).isEmpty()) {
critNode.setProperty(NodeConstants.Info.IS_HAVING, Boolean.TRUE);
}
// Add groups to crit node
@@ -994,19 +1015,29 @@
/**
* Attach a grouping node at top of tree.
* @param plan Existing plan
+ * @param aggs
* @param groupBy Group by clause, which may be null
* @return Updated plan
+ * @throws TeiidComponentException
+ * @throws QueryMetadataException
*/
- private static PlanNode attachGrouping(PlanNode plan, Query query, PlanHints hints) {
- PlanNode groupNode = NodeFactory.getNewNode(NodeConstants.Types.GROUP);
-
+ private PlanNode attachGrouping(PlanNode plan, Query query,
Collection<AggregateSymbol> aggs) throws QueryMetadataException,
TeiidComponentException {
+ //TODO: correlated agg
+
GroupBy groupBy = query.getGroupBy();
- if(groupBy != null) {
- groupNode.setProperty(NodeConstants.Info.GROUP_COLS, groupBy.getSymbols());
- groupNode.addGroups(GroupsUsedByElementsVisitor.getGroups(groupBy));
+ List<Expression> groupingCols = null;
+ if (groupBy != null) {
+ groupingCols = groupBy.getSymbols();
}
+
+ PlanNode groupNode = NodeFactory.getNewNode(NodeConstants.Types.GROUP);
+
+ Map<Expression, ElementSymbol> mapping = buildGroupingNode(aggs, groupingCols,
groupNode, this.context, this.idGenerator).inserseMapping();
attachLast(groupNode, plan);
+ ExpressionMappingVisitor.mapExpressions(query.getHaving(), mapping);
+ ExpressionMappingVisitor.mapExpressions(query.getSelect(), mapping);
+ ExpressionMappingVisitor.mapExpressions(query.getOrderBy(), mapping);
// Mark in hints
hints.hasAggregates = true;
@@ -1014,6 +1045,57 @@
return groupNode;
}
+ /**
+ * Build a grouping node that introduces a anon group (without a inline view source
node)
+ */
+ public static SymbolMap buildGroupingNode(
+ Collection<AggregateSymbol> aggs, List<? extends Expression>
groupingCols,
+ PlanNode groupNode, CommandContext cc, IDGenerator idGenerator) throws
QueryMetadataException, TeiidComponentException {
+ SymbolMap map = new SymbolMap();
+ aggs = LanguageObject.Util.deepClone(aggs, AggregateSymbol.class);
+ groupingCols = LanguageObject.Util.deepClone(groupingCols, Expression.class);
+ GroupSymbol group = new GroupSymbol("anon_grp" + idGenerator.nextInt());
//$NON-NLS-1$
+ if (!cc.getGroups().add(group.getName())) {
+ group = RulePlaceAccess.recontextSymbol(group, cc.getGroups());
+ }
+
+ TempMetadataStore tms = new TempMetadataStore();
+
+ int i = 0;
+
+ List<AliasSymbol> symbols = new LinkedList<AliasSymbol>();
+ List<Expression> targets = new LinkedList<Expression>();
+
+ if(groupingCols != null) {
+ groupNode.setProperty(NodeConstants.Info.GROUP_COLS, groupingCols);
+ groupNode.addGroups(GroupsUsedByElementsVisitor.getGroups(groupingCols));
+ for (Expression ex : groupingCols) {
+ AliasSymbol as = new AliasSymbol("gcol" + i++, new
ExpressionSymbol("expr", ex)); //$NON-NLS-1$ //$NON-NLS-2$
+ targets.add(ex);
+ symbols.add(as);
+ }
+ }
+
+ i = 0;
+ for (AggregateSymbol ex : aggs) {
+ AliasSymbol as = new AliasSymbol("agg" + i++, new
ExpressionSymbol("expr", ex)); //$NON-NLS-1$ //$NON-NLS-2$
+ targets.add(ex);
+ symbols.add(as);
+ }
+
+ group.setMetadataID(tms.addTempGroup(group.getName(), symbols, true, false));
+ Iterator<Expression> targetIter = targets.iterator();
+ for (ElementSymbol es : ResolverUtil.resolveElementsInGroup(group, new
TempMetadataAdapter(new BasicQueryMetadata(), tms))) {
+ Expression target = targetIter.next();
+ es.setAggregate(target instanceof AggregateSymbol);
+ map.addMapping(es, target);
+ }
+
+ groupNode.setProperty(NodeConstants.Info.SYMBOL_MAP, map);
+ groupNode.addGroup(group);
+ return map;
+ }
+
/**
* Attach SORT node at top of tree. The SORT may be pushed down to a source (or
sources)
* if possible by the optimizer.
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/plantree/NodeConstants.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -130,7 +130,7 @@
MAKE_IND,
// Group node properties
- GROUP_COLS, // List <SingleElementSymbol>
+ GROUP_COLS, // List <Expression>
// Special constant used in converting plan to process for all nodes
OUTPUT_COLS, // List <SingleElementSymbol>
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/CapabilitiesUtil.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -120,12 +120,13 @@
return false;
}
boolean supportsFunctionsInGroupBy =
caps.supportsCapability(Capability.QUERY_FUNCTIONS_IN_GROUP_BY);
+ boolean supportsInlineView =
caps.supportsCapability(Capability.QUERY_FROM_INLINE_VIEWS);
// Also verify that if there is a function that we can support pushdown of
functions in group by
Iterator colIter = groupCols.iterator();
while(colIter.hasNext()) {
Expression col = (Expression) colIter.next();
- if(!(col instanceof ElementSymbol) &&
!supportsFunctionsInGroupBy) {
+ if(!(col instanceof ElementSymbol) && !supportsFunctionsInGroupBy
&& !supportsInlineView) {
// Function in GROUP BY can't be pushed
return false;
}
@@ -179,6 +180,11 @@
return false;
}
break;
+ case ARRAY_AGG:
+ if(! caps.supportsCapability(Capability.QUERY_AGGREGATES_ARRAY)) {
+ return false;
+ }
+ break;
default:
if (aggregate.isEnhancedNumeric()) {
if (!caps.supportsCapability(Capability.QUERY_AGGREGATES_ENHANCED_NUMERIC)) {
@@ -195,10 +201,12 @@
return false;
}
+ if (aggregate.getCondition() != null &&
!caps.supportsCapability(Capability.ADVANCED_OLAP)) {
+ return false;
+ }
+
// Passed all the checks!
return true;
-
-
}
public static boolean supportsScalarFunction(Object modelID, Function function,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder)
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/FrameUtil.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -45,6 +45,7 @@
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.NodeFactory;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
import org.teiid.query.processor.ProcessorPlan;
import org.teiid.query.resolver.util.AccessPattern;
import org.teiid.query.resolver.util.ResolverUtil;
@@ -178,6 +179,10 @@
// multiple new groups.
static void convertNode(PlanNode node, GroupSymbol oldGroup, Set<GroupSymbol>
newGroups, Map symbolMap, QueryMetadataInterface metadata, boolean rewrite)
throws QueryPlannerException {
+
+ if (node.getType() == NodeConstants.Types.GROUP) {
+ correctSymbolMap(symbolMap, node);
+ }
// Convert expressions from correlated subquery references;
List<SymbolMap> refMaps = node.getAllReferences();
@@ -256,7 +261,7 @@
GroupsUsedByElementsVisitor.getGroups(orderBy, groups);
}
} else if(type == NodeConstants.Types.GROUP) {
- List<SingleElementSymbol> groupCols =
(List<SingleElementSymbol>)node.getProperty(NodeConstants.Info.GROUP_COLS);
+ List<Expression> groupCols =
(List<Expression>)node.getProperty(NodeConstants.Info.GROUP_COLS);
if (groupCols != null) {
GroupBy groupBy= new GroupBy(groupCols);
ExpressionMappingVisitor.mapExpressions(groupBy, symbolMap);
@@ -265,6 +270,10 @@
GroupsUsedByElementsVisitor.getGroups(groupBy, groups);
}
}
+ if (!singleMapping) {
+ //add back the anon group
+
groups.add(((SymbolMap)node.getProperty(Info.SYMBOL_MAP)).asMap().keySet().iterator().next().getGroupSymbol());
+ }
} else if (type == NodeConstants.Types.SOURCE || type ==
NodeConstants.Types.ACCESS) {
convertAccessPatterns(symbolMap, node);
}
@@ -281,7 +290,9 @@
if (mappedSymbol != null) {
return mappedSymbol;
}
- return expression;
+ if (expression instanceof ElementSymbol) {
+ return expression;
+ }
}
ExpressionMappingVisitor.mapExpressions(expression, symbolMap);
@@ -377,8 +388,7 @@
private static PlanNode findOriginatingNode(PlanNode root, Set<GroupSymbol>
groups, boolean joinSource) {
boolean containsGroups = false;
- if(root.getType() == NodeConstants.Types.NULL || root.getType() ==
NodeConstants.Types.SOURCE
- || root.getType() == NodeConstants.Types.JOIN || root.getType()
== NodeConstants.Types.SET_OP ||
+ if((root.getType() & (NodeConstants.Types.NULL | NodeConstants.Types.SOURCE |
NodeConstants.Types.JOIN | NodeConstants.Types.SET_OP | NodeConstants.Types.GROUP)) ==
root.getType() ||
(joinSource && root.getType() ==
NodeConstants.Types.ACCESS)) {
//if there are no groups then the first possible match is the one we want
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/NewCalculateCostUtil.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -74,7 +74,6 @@
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
-import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
@@ -440,7 +439,7 @@
if (stats == null) {
if (node.getType() == NodeConstants.Types.PROJECT) {
Collection<SingleElementSymbol> elems = new
HashSet<SingleElementSymbol>();
- AggregateSymbolCollectorVisitor.getAggregates(expr, elems, elems);
+ ElementCollectorVisitor.getElements(expr, elems);
newStats[Stat.NDV.ordinal()] = getStat(Stat.NDV, elems, node,
childCardinality, metadata);
newStats[Stat.NNV.ordinal()] = getStat(Stat.NNV, elems, node,
childCardinality, metadata);
} else {
@@ -578,9 +577,8 @@
if (node.getType() == NodeConstants.Types.PROJECT) {
return (List<? extends Expression>)
node.getProperty(NodeConstants.Info.PROJECT_COLS);
} else if (node.getType() == NodeConstants.Types.GROUP) {
- LinkedList<Expression> result = new
LinkedList<Expression>(RulePushAggregates.collectAggregates(node));
- result.addAll((Collection<? extends Expression>)
node.getProperty(Info.GROUP_COLS));
- return result;
+ SymbolMap map = (SymbolMap)node.getProperty(Info.SYMBOL_MAP);
+ return map.getKeys();
}
LinkedList<ElementSymbol> elements = new LinkedList<ElementSymbol>();
for (GroupSymbol group : node.getGroups()) {
@@ -1014,7 +1012,7 @@
return cost;
}
- static boolean usesKey(PlanNode planNode, Collection<? extends
SingleElementSymbol> allElements, QueryMetadataInterface metadata) throws
QueryMetadataException, TeiidComponentException {
+ static boolean usesKey(PlanNode planNode, Collection<? extends Expression>
allElements, QueryMetadataInterface metadata) throws QueryMetadataException,
TeiidComponentException {
//TODO: key preserved joins should be marked
return isSingleTable(planNode)
&& usesKey(allElements, metadata);
@@ -1035,17 +1033,17 @@
* we are in the plan.
* if a key column is used after a non 1-1 join or a union all, then it may be
non-unique.
*/
- public static boolean usesKey(Collection<? extends SingleElementSymbol>
allElements, QueryMetadataInterface metadata)
+ public static boolean usesKey(Collection<? extends Expression> allElements,
QueryMetadataInterface metadata)
throws QueryMetadataException, TeiidComponentException {
return usesKey(allElements, null, metadata, true);
}
- public static boolean usesKey(Collection<? extends SingleElementSymbol>
allElements, Set<GroupSymbol> groups, QueryMetadataInterface metadata, boolean
unique)
+ public static boolean usesKey(Collection<? extends Expression> allElements,
Set<GroupSymbol> groups, QueryMetadataInterface metadata, boolean unique)
throws QueryMetadataException, TeiidComponentException {
return getKeyUsed(allElements, groups, metadata, unique) != null;
}
- public static Object getKeyUsed(Collection<? extends SingleElementSymbol>
allElements, Set<GroupSymbol> groups, QueryMetadataInterface metadata, Boolean
unique)
+ public static Object getKeyUsed(Collection<? extends Expression> allElements,
Set<GroupSymbol> groups, QueryMetadataInterface metadata, Boolean unique)
throws QueryMetadataException, TeiidComponentException {
if(allElements == null || allElements.size() == 0) {
@@ -1054,7 +1052,7 @@
// Sort elements into groups
Map<GroupSymbol, List<Object>> groupMap = new HashMap<GroupSymbol,
List<Object>>();
- for (SingleElementSymbol ses : allElements) {
+ for (Expression ses : allElements) {
Expression ex = SymbolMap.getExpression(ses);
if (!(ex instanceof ElementSymbol)) {
continue; //TODO: function based indexes are possible, but we don't have
the metadata
@@ -1337,7 +1335,7 @@
static float getNDVEstimate(PlanNode indNode,
QueryMetadataInterface metadata, float cardinality,
- Collection<? extends SingleElementSymbol> elems, boolean
useCardinalityIfUnknown) throws QueryMetadataException,
+ Collection<? extends Expression> elems, boolean useCardinalityIfUnknown) throws
QueryMetadataException,
TeiidComponentException {
if (elems == null || elems.isEmpty()) {
return cardinality;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleAssignOutputElements.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -57,7 +57,7 @@
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
-import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
+import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.GroupsUsedByElementsVisitor;
import org.teiid.query.util.CommandContext;
@@ -437,8 +437,6 @@
* are any symbols that are required in the processing of this node,
* for instance to create a new element symbol or sort on it, etc.
* @param node Node to collect for
- * @param requiredSymbols Collection<SingleElementSymbol> Place to collect
required symbols
- * @param createdSymbols Set<SingleElementSymbol> Place to collect any symbols
created by this node
*/
private List<SingleElementSymbol> collectRequiredInputSymbols(PlanNode node) {
@@ -459,57 +457,53 @@
}
if (ss instanceof ExpressionSymbol && !(ss instanceof
AggregateSymbol)) {
- ExpressionSymbol exprSymbol = (ExpressionSymbol)ss;
-
- if (!exprSymbol.isDerivedExpression()) {
- createdSymbols.add(ss);
- }
+ createdSymbols.add(ss);
}
- AggregateSymbolCollectorVisitor.getAggregates(ss, requiredSymbols,
requiredSymbols);
+ ElementCollectorVisitor.getElements(ss, requiredSymbols);
}
break;
}
case NodeConstants.Types.SELECT:
Criteria selectCriteria = (Criteria)
node.getProperty(NodeConstants.Info.SELECT_CRITERIA);
- AggregateSymbolCollectorVisitor.getAggregates(selectCriteria,
requiredSymbols, requiredSymbols);
+ ElementCollectorVisitor.getElements(selectCriteria, requiredSymbols);
break;
case NodeConstants.Types.JOIN:
List<Criteria> crits = (List)
node.getProperty(NodeConstants.Info.JOIN_CRITERIA);
if(crits != null) {
for (Criteria joinCriteria : crits) {
- AggregateSymbolCollectorVisitor.getAggregates(joinCriteria, requiredSymbols,
requiredSymbols);
+ ElementCollectorVisitor.getElements(joinCriteria, requiredSymbols);
}
}
break;
case NodeConstants.Types.GROUP:
- List<SingleElementSymbol> groupCols = (List<SingleElementSymbol>)
node.getProperty(NodeConstants.Info.GROUP_COLS);
+ List<Expression> groupCols = (List<Expression>)
node.getProperty(NodeConstants.Info.GROUP_COLS);
if(groupCols != null) {
- for (SingleElementSymbol expression : groupCols) {
- if(expression instanceof ElementSymbol || expression instanceof
AggregateSymbol) {
- requiredSymbols.add(expression);
- } else {
- ExpressionSymbol exprSymbol = (ExpressionSymbol) expression;
- Expression expr = exprSymbol.getExpression();
- AggregateSymbolCollectorVisitor.getAggregates(expr,
requiredSymbols, requiredSymbols);
- createdSymbols.add(exprSymbol);
- }
+ for (Expression expression : groupCols) {
+ ElementCollectorVisitor.getElements(expression, requiredSymbols);
}
}
-
+
+ SymbolMap symbolMap = (SymbolMap) node.getProperty(NodeConstants.Info.SYMBOL_MAP);
+
// Take credit for creating any aggregates that are needed above
for (SingleElementSymbol outputSymbol : outputCols) {
- if(outputSymbol instanceof AggregateSymbol) {
- AggregateSymbol agg = (AggregateSymbol)outputSymbol;
- createdSymbols.add(outputSymbol);
+ createdSymbols.add(outputSymbol);
+ Expression ex = symbolMap.getMappedExpression((ElementSymbol) outputSymbol);
+ if(ex instanceof AggregateSymbol) {
+ AggregateSymbol agg = (AggregateSymbol)ex;
Expression aggExpr = agg.getExpression();
if(aggExpr != null) {
- AggregateSymbolCollectorVisitor.getAggregates(aggExpr,
requiredSymbols, requiredSymbols);
+ ElementCollectorVisitor.getElements(aggExpr, requiredSymbols);
}
OrderBy orderBy = agg.getOrderBy();
if(orderBy != null) {
- AggregateSymbolCollectorVisitor.getAggregates(orderBy,
requiredSymbols, requiredSymbols);
+ ElementCollectorVisitor.getElements(orderBy, requiredSymbols);
}
+ Expression condition = agg.getCondition();
+ if(condition != null) {
+ ElementCollectorVisitor.getElements(condition, requiredSymbols);
+ }
}
}
@@ -519,7 +513,7 @@
// Gather elements from correlated subquery references;
for (SymbolMap refs : node.getAllReferences()) {
for (Expression expr : refs.asMap().values()) {
- AggregateSymbolCollectorVisitor.getAggregates(expr, requiredSymbols,
requiredSymbols);
+ ElementCollectorVisitor.getElements(expr, requiredSymbols);
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleChooseJoinStrategy.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -71,7 +71,6 @@
* Determines whether this node should be converted to a merge join node
* @param joinNode The join node
* @param metadata The metadata
- * @return True if merge is possible
*/
static void chooseJoinStrategy(PlanNode joinNode, QueryMetadataInterface metadata) {
// Check that join is an inner join
@@ -183,7 +182,6 @@
ExpressionSymbol expressionSymbol = uniqueExpressions.get(expression);
if (expressionSymbol == null) {
expressionSymbol = new ExpressionSymbol("$" +
EXPRESSION_INDEX.getAndIncrement(), expression); //$NON-NLS-1$
- expressionSymbol.setDerivedExpression(true);
uniqueExpressions.put(expression, expressionSymbol);
}
result.add(expressionSymbol);
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleCollapseSource.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -24,14 +24,19 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import org.teiid.api.exception.query.QueryMetadataException;
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidException;
+import org.teiid.core.TeiidRuntimeException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -72,6 +77,7 @@
import org.teiid.query.sql.lang.UnaryFromClause;
import org.teiid.query.sql.lang.SetQuery.Operation;
import org.teiid.query.sql.navigator.DeepPostOrderNavigator;
+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;
@@ -80,6 +86,7 @@
import org.teiid.query.sql.symbol.ScalarSubquery;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.SymbolMap;
+import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.util.CommandContext;
@@ -241,11 +248,12 @@
if (query.getCriteria() instanceof CompoundCriteria) {
query.setCriteria(QueryRewriter.optimizeCriteria((CompoundCriteria)query.getCriteria(),
metadata));
}
- if (!CapabilitiesUtil.useAnsiJoin(RuleRaiseAccess.getModelIDFromAccess(accessRoot,
metadata), metadata, capFinder)) {
+ Object modelID = RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata);
+ if (!CapabilitiesUtil.useAnsiJoin(modelID, metadata, capFinder)) {
simplifyFromClause(query);
}
if (columns.isEmpty()) {
- if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION,
RuleRaiseAccess.getModelIDFromAccess(accessRoot, metadata), metadata, capFinder)) {
+ if (CapabilitiesUtil.supports(Capability.QUERY_SELECT_EXPRESSION, modelID,
metadata, capFinder)) {
select.addSymbol(new ExpressionSymbol("dummy", new Constant(1)));
//$NON-NLS-1$
} else {
//TODO: need to ensure the type is consistent
@@ -253,6 +261,20 @@
select.addSymbol(selectOutputElement(query.getFrom().getGroups(), metadata));
}
}
+ PlanNode groupNode = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP,
NodeConstants.Types.SOURCE);
+ if (groupNode != null) {
+ SymbolMap symbolMap = (SymbolMap)
groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+
+ //map back to expression form
+ ExpressionMappingVisitor.mapExpressions(query.getOrderBy(), symbolMap.asMap());
+ ExpressionMappingVisitor.mapExpressions(query.getSelect(), symbolMap.asMap());
+ ExpressionMappingVisitor.mapExpressions(query.getHaving(), symbolMap.asMap());
+
+ if (!CapabilitiesUtil.supports(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, modelID,
metadata, capFinder)) {
+ //if group by expressions are not support, add an inline view to compensate
+ query = RuleCollapseSource.rewriteGroupByExpressionsAsView(query, metadata);
+ }
+ }
return query;
}
@@ -273,7 +295,7 @@
for (ElementSymbol element : elements) {
if(metadata.elementSupports(element.getMetadataID(),
SupportConstants.Element.SELECT)) {
- element = (ElementSymbol)element.clone();
+ element = element.clone();
element.setGroupSymbol(group);
return element;
}
@@ -323,10 +345,10 @@
// Get last two clauses added to the FROM and combine them into a
JoinPredicate
From from = query.getFrom();
- List clauses = from.getClauses();
+ List<FromClause> clauses = from.getClauses();
int lastClause = clauses.size()-1;
- FromClause clause1 = (FromClause) clauses.get(lastClause-1);
- FromClause clause2 = (FromClause) clauses.get(lastClause);
+ FromClause clause1 = clauses.get(lastClause-1);
+ FromClause clause2 = clauses.get(lastClause);
//correct the criteria or the join type if necessary
if (joinType != JoinType.JOIN_CROSS && crits.isEmpty()) {
@@ -492,13 +514,13 @@
*/
private void simplifyFromClause(Query query) {
From from = query.getFrom();
- List clauses = from.getClauses();
- FromClause rootClause = (FromClause) clauses.get(0);
+ List<FromClause> clauses = from.getClauses();
+ FromClause rootClause = clauses.get(0);
// If all joins are inner joins, move criteria to WHERE and make
// FROM a list of groups instead of a tree of JoinPredicates
if(! hasOuterJoins(rootClause)) {
- from.setClauses(new ArrayList());
+ from.setClauses(new ArrayList<FromClause>());
shredJoinTree(rootClause, query);
} // else leave as is
}
@@ -554,4 +576,75 @@
return "CollapseSource"; //$NON-NLS-1$
}
+ public static Query rewriteGroupByExpressionsAsView(Query query, QueryMetadataInterface
metadata) {
+ if (query.getGroupBy() == null) {
+ return query;
+ }
+ // we check for group by expressions here to create an ANSI SQL plan
+ boolean hasExpression = false;
+ for (final Iterator<Expression> iterator =
query.getGroupBy().getSymbols().iterator(); !hasExpression && iterator.hasNext();)
{
+ hasExpression = !(iterator.next() instanceof ElementSymbol);
+ }
+ if (!hasExpression) {
+ return query;
+ }
+ Select select = query.getSelect();
+ GroupBy groupBy = query.getGroupBy();
+ query.setGroupBy(null);
+ Criteria having = query.getHaving();
+ query.setHaving(null);
+ OrderBy orderBy = query.getOrderBy();
+ query.setOrderBy(null);
+ Limit limit = query.getLimit();
+ query.setLimit(null);
+ Set<Expression> newSelectColumns = new HashSet<Expression>();
+ for (final Iterator<Expression> iterator = groupBy.getSymbols().iterator();
iterator.hasNext();) {
+ newSelectColumns.add(iterator.next());
+ }
+ Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
+ aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(select, true));
+ if (having != null) {
+ aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(having, true));
+ }
+ for (AggregateSymbol aggregateSymbol : aggs) {
+ if (aggregateSymbol.getExpression() != null) {
+ Expression expr = aggregateSymbol.getExpression();
+ newSelectColumns.add(SymbolMap.getExpression(expr));
+ }
+ }
+ Select innerSelect = new Select();
+ int index = 0;
+ for (Expression expr : newSelectColumns) {
+ if (expr instanceof SingleElementSymbol) {
+ innerSelect.addSymbol((SingleElementSymbol)expr);
+ } else {
+ innerSelect.addSymbol(new ExpressionSymbol("EXPR" + index++ ,
expr)); //$NON-NLS-1$
+ }
+ }
+ query.setSelect(innerSelect);
+ Query outerQuery = null;
+ try {
+ outerQuery = QueryRewriter.createInlineViewQuery(new GroupSymbol("X"),
query, metadata, query.getSelect().getProjectedSymbols()); //$NON-NLS-1$
+ } catch (TeiidException err) {
+ throw new TeiidRuntimeException(err);
+ }
+ Iterator<SingleElementSymbol> iter =
outerQuery.getSelect().getProjectedSymbols().iterator();
+ HashMap<Expression, SingleElementSymbol> expressionMap = new
HashMap<Expression, SingleElementSymbol>();
+ for (SingleElementSymbol symbol : query.getSelect().getProjectedSymbols()) {
+ expressionMap.put(SymbolMap.getExpression(symbol), iter.next());
+ }
+ ExpressionMappingVisitor.mapExpressions(groupBy, expressionMap);
+ outerQuery.setGroupBy(groupBy);
+ ExpressionMappingVisitor.mapExpressions(having, expressionMap);
+ outerQuery.setHaving(having);
+ ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap);
+ outerQuery.setOrderBy(orderBy);
+ outerQuery.setLimit(limit);
+ ExpressionMappingVisitor.mapExpressions(select, expressionMap);
+ outerQuery.setSelect(select);
+ outerQuery.setOption(query.getOption());
+ query = outerQuery;
+ return query;
+ }
+
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleConstants.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -34,7 +34,6 @@
public static final OptimizerRule MERGE_VIRTUAL = new RuleMergeVirtual();
public static final OptimizerRule CHOOSE_JOIN_STRATEGY = new
RuleChooseJoinStrategy();
public static final OptimizerRule RAISE_ACCESS = new RuleRaiseAccess();
- public static final OptimizerRule PUSH_AGGREGATES = new RulePushAggregates();
public static final OptimizerRule CHOOSE_DEPENDENT = new RuleChooseDependent();
public static final OptimizerRule COLLAPSE_SOURCE = new RuleCollapseSource();
public static final OptimizerRule ASSIGN_OUTPUT_ELEMENTS = new
RuleAssignOutputElements();
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleDecomposeJoin.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -25,7 +25,6 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
@@ -208,20 +207,15 @@
throws TeiidComponentException, QueryPlannerException,
QueryMetadataException {
Set<String> groups = context.getGroups();
- if (groups == null) {
- groups = new HashSet<String>();
- context.setGroups(groups);
- }
group = RulePlaceAccess.recontextSymbol(group, groups);
PlanNode projectNode = NodeEditor.findNodePreOrder(newUnion,
NodeConstants.Types.PROJECT);
List<? extends SingleElementSymbol> projectedSymbols = (List<? extends
SingleElementSymbol>)projectNode.getProperty(Info.PROJECT_COLS);
- PlanNode view = RulePushAggregates.createView(group, projectedSymbols, newUnion,
metadata);
+ SymbolMap newSymbolMap = RulePushAggregates.createSymbolMap(group, projectedSymbols,
newUnion, metadata);
+ PlanNode view = RuleDecomposeJoin.createSource(group, newUnion, newSymbolMap);
- SymbolMap newSymbolMap = (SymbolMap)view.getProperty(Info.SYMBOL_MAP);
-
Map<Expression, ElementSymbol> inverseMap = newSymbolMap.inserseMapping();
toReplace.getParent().replaceChild(toReplace, view);
Set<GroupSymbol> newGroups = Collections.singleton(group);
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeCriteria.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -591,7 +591,7 @@
boolean distinct = false;
if (query.getGroupBy() != null) {
distinct = true;
- for (SingleElementSymbol groupByExpr :
(List<SingleElementSymbol>)query.getGroupBy().getSymbols()) {
+ for (Expression groupByExpr : query.getGroupBy().getSymbols()) {
if (!expressions.contains(groupByExpr)) {
distinct = false;
break;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleMergeVirtual.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -41,6 +41,7 @@
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
+import org.teiid.query.resolver.util.AccessPattern;
import org.teiid.query.sql.lang.JoinType;
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
@@ -161,13 +162,7 @@
return root;
}
- PlanNode parentGroup = NodeEditor.findParent(frame, NodeConstants.Types.GROUP,
NodeConstants.Types.SOURCE);
- List<SingleElementSymbol> groupCols = null;
- if (parentGroup != null) {
- groupCols =
(List<SingleElementSymbol>)parentGroup.getProperty(NodeConstants.Info.GROUP_COLS);
- }
-
- if (!checkProjectedSymbols(projectNode, virtualGroup, parentJoin, groupCols,
symbolMap, metadata)) {
+ if (!checkProjectedSymbols(projectNode, virtualGroup, parentJoin, metadata)) {
return root;
}
@@ -190,9 +185,9 @@
// find the new root of the frame so that access patterns can be propagated
PlanNode newRoot = FrameUtil.findJoinSourceNode(frame.getFirstChild());
if (newRoot != null) {
- Collection ap =
(Collection)frame.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
+ Collection<AccessPattern> ap =
(Collection)frame.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
if (ap != null) {
- Collection newAp =
(Collection)newRoot.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
+ Collection<AccessPattern> newAp =
(Collection)newRoot.getProperty(NodeConstants.Info.ACCESS_PATTERNS);
if (newAp == null) {
newRoot.setProperty(NodeConstants.Info.ACCESS_PATTERNS, ap);
} else {
@@ -323,8 +318,6 @@
private static boolean checkProjectedSymbols(PlanNode projectNode,
GroupSymbol virtualGroup,
PlanNode parentJoin,
- List<SingleElementSymbol>
parentGroupingCols,
- SymbolMap symbolMap,
QueryMetadataInterface metadata) {
List<SingleElementSymbol> selectSymbols =
(List<SingleElementSymbol>)projectNode.getProperty(NodeConstants.Info.PROJECT_COLS);
@@ -351,7 +344,6 @@
}
}
- List<ElementSymbol> virtualElements = symbolMap.getKeys();
for (int i = 0; i < selectSymbols.size(); i++) {
SingleElementSymbol symbol = selectSymbols.get(i);
Collection scalarSubqueries =
ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(symbol);
@@ -361,9 +353,6 @@
if (checkForNullDependent && JoinUtil.isNullDependent(metadata,
groups, SymbolMap.getExpression(symbol))) {
return false;
}
- if (parentGroupingCols != null && !(SymbolMap.getExpression(symbol)
instanceof SingleElementSymbol) &&
parentGroupingCols.contains(virtualElements.get(i))) {
- return false;
- }
// TEIID-16: We do not want to merge a non-deterministic scalar function
if (FunctionCollectorVisitor.isNonDeterministic(symbol)) {
return false;
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlaceAccess.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlaceAccess.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlaceAccess.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -69,10 +69,6 @@
QueryPlannerException {
Set<String> groups = context.getGroups();
- if (groups == null) {
- groups = new HashSet<String>();
- context.setGroups(groups);
- }
boolean[] addtionalRules = new boolean[2];
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePlanSorts.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -22,6 +22,7 @@
package org.teiid.query.optimizer.relational.rules;
+import java.util.ArrayList;
import java.util.List;
import org.teiid.api.exception.query.QueryMetadataException;
@@ -43,8 +44,11 @@
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.AliasSymbol;
+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.sql.util.SymbolMap;
import org.teiid.query.util.CommandContext;
@@ -86,13 +90,25 @@
root = checkForProjectOptimization(node, root, metadata, capFinder, record);
}
List<SingleElementSymbol> orderColumns =
((OrderBy)node.getProperty(NodeConstants.Info.SORT_ORDER)).getSortKeys();
+ List<Expression> sortExpressions = new
ArrayList<Expression>(orderColumns.size());
PlanNode possibleSort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.GROUP,
NodeConstants.Types.SOURCE | NodeConstants.Types.ACCESS);
if (possibleSort != null) {
- List exprs = (List)possibleSort.getProperty(Info.GROUP_COLS);
- if (exprs != null && exprs.containsAll(orderColumns)) {
- exprs.removeAll(orderColumns);
- orderColumns.addAll(exprs);
- possibleSort.setProperty(Info.GROUP_COLS, orderColumns);
+ boolean otherExpression = false;
+ SymbolMap groupMap = (SymbolMap)possibleSort.getProperty(Info.SYMBOL_MAP);
+ for (SingleElementSymbol singleElementSymbol : orderColumns) {
+ Expression ex = SymbolMap.getExpression(singleElementSymbol);
+ if (ex instanceof ElementSymbol) {
+ sortExpressions.add(groupMap.getMappedExpression((ElementSymbol) ex));
+ } else {
+ otherExpression = true;
+ break;
+ }
+ }
+
+ List<Expression> exprs =
(List<Expression>)possibleSort.getProperty(Info.GROUP_COLS);
+ if (!otherExpression && exprs != null &&
exprs.containsAll(sortExpressions)) {
+ exprs.removeAll(sortExpressions);
+ exprs.addAll(0, sortExpressions);
if (node.getParent() == null) {
root = node.getFirstChild();
root.removeFromParent();
@@ -105,54 +121,6 @@
}
break;
}
-/* possibleSort = NodeEditor.findNodePreOrder(node, NodeConstants.Types.JOIN,
NodeConstants.Types.SOURCE | NodeConstants.Types.ACCESS);
- if (possibleSort == null) {
- break;
- }
- boolean left = false;
- if (possibleSort.getType() == NodeConstants.Types.JOIN) {
- if (possibleSort.getProperty(NodeConstants.Info.JOIN_STRATEGY) !=
JoinStrategyType.MERGE
- || possibleSort.getProperty(NodeConstants.Info.JOIN_TYPE) != JoinType.JOIN_INNER) {
- break;
- }
- if
(FrameUtil.findJoinSourceNode(possibleSort.getFirstChild()).getGroups().containsAll(node.getGroups())
- && possibleSort.getProperty(NodeConstants.Info.SORT_LEFT) ==
SortOption.SORT) {
- left = true;
- } else if
(!FrameUtil.findJoinSourceNode(possibleSort.getLastChild()).getGroups().containsAll(node.getGroups())
- || possibleSort.getProperty(NodeConstants.Info.SORT_RIGHT) != SortOption.SORT) {
- break;
- }
- }
- List exprs =
(List)possibleSort.getProperty(left?Info.LEFT_EXPRESSIONS:Info.RIGHT_EXPRESSIONS);
- if (exprs != null && exprs.containsAll(orderColumns)) {
- List<Integer> indexes = new ArrayList<Integer>(orderColumns.size());
- for (Expression expr : (List<Expression>)orderColumns) {
- indexes.add(0, exprs.indexOf(expr));
- }
- exprs.removeAll(orderColumns);
- List newExprs = new ArrayList(orderColumns);
- newExprs.addAll(exprs);
- possibleSort.setProperty(left?Info.LEFT_EXPRESSIONS:Info.RIGHT_EXPRESSIONS,
newExprs);
- if (node.getParent() == null) {
- root = node.getFirstChild();
- root.removeFromParent();
- node = root;
- } else {
- PlanNode nextNode = node.getFirstChild();
- NodeEditor.removeChildNode(node.getParent(), node);
- node = nextNode;
- }
- exprs =
(List)possibleSort.getProperty(left?Info.RIGHT_EXPRESSIONS:Info.LEFT_EXPRESSIONS);
- List toRemove = new ArrayList();
- for (Integer index : indexes) {
- Object o = exprs.get(index);
- exprs.add(0, o);
- toRemove.add(o);
- }
- exprs.subList(indexes.size(), exprs.size()).removeAll(toRemove);
- possibleSort.setProperty(left?NodeConstants.Info.SORT_LEFT:NodeConstants.Info.SORT_RIGHT,
SortOption.SORT_REQUIRED);
- }
-*/
break;
case NodeConstants.Types.DUP_REMOVE:
if (parentBlocking) {
@@ -243,13 +211,8 @@
if(ss instanceof AliasSymbol) {
ss = ((AliasSymbol)ss).getSymbol();
}
-
if (ss instanceof ExpressionSymbol && !(ss instanceof
AggregateSymbol)) {
- ExpressionSymbol exprSymbol = (ExpressionSymbol)ss;
-
- if (!exprSymbol.isDerivedExpression()) {
- return root; //TODO: insert a new project node to handle this case
- }
+ return root; //TODO: insert a new project node to handle this case
}
if (!childOutputCols.contains(ss)) {
return root;
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-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushAggregates.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -40,17 +40,18 @@
import org.teiid.api.exception.query.QueryPlannerException;
import org.teiid.api.exception.query.QueryResolverException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.core.id.IDGenerator;
import org.teiid.core.types.DataTypeManager;
import org.teiid.language.SQLConstants.NonReserved;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.function.FunctionLibrary;
import org.teiid.query.metadata.QueryMetadataInterface;
import org.teiid.query.metadata.TempMetadataAdapter;
-import org.teiid.query.metadata.TempMetadataID;
import org.teiid.query.metadata.TempMetadataStore;
import org.teiid.query.optimizer.capabilities.CapabilitiesFinder;
import org.teiid.query.optimizer.capabilities.SourceCapabilities.Capability;
import org.teiid.query.optimizer.relational.OptimizerRule;
+import org.teiid.query.optimizer.relational.RelationalPlanner;
import org.teiid.query.optimizer.relational.RuleStack;
import org.teiid.query.optimizer.relational.plantree.NodeConstants;
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
@@ -61,7 +62,6 @@
import org.teiid.query.resolver.util.ResolverVisitor;
import org.teiid.query.rewriter.QueryRewriter;
import org.teiid.query.sql.LanguageObject;
-import org.teiid.query.sql.LanguageObject.Util;
import org.teiid.query.sql.lang.CompareCriteria;
import org.teiid.query.sql.lang.Criteria;
import org.teiid.query.sql.lang.IsNullCriteria;
@@ -94,6 +94,12 @@
*/
public class RulePushAggregates implements
OptimizerRule {
+
+ private IDGenerator idGenerator;
+
+ public RulePushAggregates(IDGenerator idGenerator) {
+ this.idGenerator = idGenerator;
+ }
/**
* @see
org.teiid.query.optimizer.relational.OptimizerRule#execute(org.teiid.query.optimizer.relational.plantree.PlanNode,
@@ -113,13 +119,16 @@
for (PlanNode groupNode : NodeEditor.findAllNodes(plan,
NodeConstants.Types.GROUP, NodeConstants.Types.ACCESS)) {
PlanNode child = groupNode.getFirstChild();
- List<SingleElementSymbol> groupingExpressions =
(List<SingleElementSymbol>)groupNode.getProperty(NodeConstants.Info.GROUP_COLS);
+ List<Expression> groupingExpressions =
(List<Expression>)groupNode.getProperty(NodeConstants.Info.GROUP_COLS);
+ if (groupingExpressions == null) {
+ groupingExpressions = Collections.emptyList();
+ }
if (child.getType() == NodeConstants.Types.SOURCE) {
PlanNode setOp = child.getFirstChild();
try {
- pushGroupNodeOverUnion(plan, metadata, capFinder, groupNode, child,
groupingExpressions, setOp, context, analysisRecord);
+ pushGroupNodeOverUnion(metadata, capFinder, groupNode, child, groupingExpressions,
setOp, context, analysisRecord);
} catch (QueryResolverException e) {
throw new TeiidComponentException(e);
}
@@ -132,7 +141,7 @@
Set<AggregateSymbol> aggregates = collectAggregates(groupNode);
- pushGroupNode(groupNode, groupingExpressions, aggregates, metadata,
capFinder);
+ pushGroupNode(groupNode, groupingExpressions, aggregates, metadata,
capFinder, context);
}
return plan;
@@ -159,48 +168,16 @@
* ...
*
* Or if the child does not support pushdown we add dummy aggregate projection
- * count(*) = 1, count(x) = case x is null then 0 else 1 end, avg(x) = x, etc.
- *
- * if partitioned, then we don't need decomposition or the top level group by
- *
- * source
- * set op
- * project
- * [select]
- * group [agg(x), {a, b}]
- * source
- * child 1
- * ...
- *
+ * count(*) = 1, count(x) = case x is null then 0 else 1 end, avg(x) = x, etc.
*/
- private void pushGroupNodeOverUnion(PlanNode plan,
- QueryMetadataInterface metadata, CapabilitiesFinder capFinder,
+ private void pushGroupNodeOverUnion(QueryMetadataInterface metadata, CapabilitiesFinder
capFinder,
PlanNode groupNode, PlanNode unionSourceParent,
- List<SingleElementSymbol> groupingExpressions, PlanNode setOp, CommandContext
context, AnalysisRecord record)
+ List<Expression> groupingExpressions, PlanNode setOp, CommandContext context,
AnalysisRecord record)
throws TeiidComponentException, QueryMetadataException,
QueryPlannerException, QueryResolverException {
- if (setOp == null) {
+ if (setOp == null || setOp.getProperty(NodeConstants.Info.SET_OPERATION) !=
Operation.UNION) {
return;
}
- PlanNode intermediateView = null;
- if (setOp.getType() != NodeConstants.Types.SET_OP) {
- if (setOp.getType() != NodeConstants.Types.PROJECT) {
- return;
- }
- intermediateView = unionSourceParent;
- unionSourceParent = setOp.getFirstChild();
- if (unionSourceParent == null || unionSourceParent.getType() !=
NodeConstants.Types.SOURCE || unionSourceParent.getFirstChild() == null
- || unionSourceParent.getFirstChild().getType() != NodeConstants.Types.SET_OP ||
unionSourceParent.getFirstChild().getProperty(NodeConstants.Info.SET_OPERATION) !=
Operation.UNION) {
- return; //not an eligible union
- }
- setOp = unionSourceParent.getFirstChild();
- if (groupingExpressions == null) {
- return; //shouldn't happen - the view should have been removed
- }
- }
- if (setOp.getProperty(NodeConstants.Info.SET_OPERATION) != Operation.UNION) {
- return;
- }
LinkedHashSet<AggregateSymbol> aggregates = collectAggregates(groupNode);
Map<ElementSymbol, List<Set<Constant>>> partitionInfo =
(Map<ElementSymbol,
List<Set<Constant>>>)unionSourceParent.getProperty(Info.PARTITION_INFO);
@@ -212,33 +189,10 @@
findUnionChildren(unionChildren, cardinalityDependent, setOp);
SymbolMap parentMap =
(SymbolMap)unionSourceParent.getProperty(NodeConstants.Info.SYMBOL_MAP);
- List<ElementSymbol> virtualElements = parentMap.getKeys();
- GroupSymbol virtualGroup = unionSourceParent.getGroups().iterator().next();
- List<SingleElementSymbol> actualGroupingExpressions = groupingExpressions;
- if (intermediateView != null) {
- actualGroupingExpressions = new
ArrayList<SingleElementSymbol>(groupingExpressions.size());
- SymbolMap viewMap =
(SymbolMap)intermediateView.getProperty(NodeConstants.Info.SYMBOL_MAP);
- for (SingleElementSymbol ses : groupingExpressions) {
- Expression ex = viewMap.getMappedExpression((ElementSymbol)ses);
- SingleElementSymbol newCol = null;
- if (ex instanceof SingleElementSymbol) {
- newCol = (SingleElementSymbol)ex;
- } else {
- newCol = new ExpressionSymbol("grouping", ex); //$NON-NLS-1$
- }
- actualGroupingExpressions.add(newCol);
- }
- }
-
//partitioned union
- if (partitionInfo != null && !Collections.disjoint(partitionInfo.keySet(),
actualGroupingExpressions)) {
- if (intermediateView != null) {
- parentMap = pushGroupByView(plan, metadata, capFinder, unionSourceParent,
- setOp, intermediateView, cardinalityDependent,
- unionChildren, virtualElements, virtualGroup);
- }
- decomposeGroupBy(groupNode, unionSourceParent, groupingExpressions, aggregates,
unionChildren, parentMap, metadata, capFinder, intermediateView != null);
+ if (partitionInfo != null && !Collections.disjoint(partitionInfo.keySet(),
groupingExpressions)) {
+ decomposeGroupBy(groupNode, unionSourceParent, groupingExpressions, aggregates,
unionChildren, parentMap, metadata, capFinder, context);
return;
}
@@ -248,10 +202,15 @@
* serves as a hint to distribute a distinct to the union queries
*/
if (aggregates.isEmpty()) {
- if (groupingExpressions != null && !groupingExpressions.isEmpty()) {
+ if (!groupingExpressions.isEmpty()) {
setOp.setProperty(NodeConstants.Info.USE_ALL, Boolean.FALSE);
}
return;
+ }
+ for (AggregateSymbol agg : aggregates) {
+ if (!agg.canStage()) {
+ return;
+ }
}
//TODO: merge virtual, plan unions, raise null - change the partition information
@@ -263,12 +222,12 @@
List<SingleElementSymbol> copy = new
ArrayList<SingleElementSymbol>(aggregates);
aggregates.clear();
Map<AggregateSymbol, Expression> aggMap = buildAggregateMap(copy, metadata,
aggregates);
-
+
boolean shouldPushdown = false;
List<Boolean> pushdownList = new ArrayList<Boolean>(unionChildren.size());
for (PlanNode planNode : unionChildren) {
- boolean pushdown = canPushGroupByToUnionChild(metadata, capFinder,
actualGroupingExpressions, aggregates, planNode, record);
+ boolean pushdown = canPushGroupByToUnionChild(metadata, capFinder,
groupingExpressions, aggregates, planNode, record);
pushdownList.add(pushdown);
shouldPushdown |= pushdown;
}
@@ -277,140 +236,238 @@
return;
}
- if (intermediateView != null) {
- parentMap = pushGroupByView(plan, metadata, capFinder, unionSourceParent,
- setOp, intermediateView, cardinalityDependent,
- unionChildren, virtualElements, virtualGroup);
- virtualElements = parentMap.getKeys();
- virtualGroup = unionSourceParent.getGroups().iterator().next();
- }
+ GroupSymbol group = unionSourceParent.getGroups().iterator().next().clone();
Iterator<Boolean> pushdownIterator = pushdownList.iterator();
+ boolean first = true;
for (PlanNode planNode : unionChildren) {
- addView(plan, planNode, pushdownIterator.next(), new GroupSymbol("X"),
groupingExpressions, aggregates, virtualElements, metadata, capFinder, null);
//$NON-NLS-1$
+ addUnionGroupBy(groupingExpressions, aggregates, parentMap, metadata, capFinder,
context, group, first, planNode, !pushdownIterator.next());
+ first = false;
}
- //update the parent plan with the staged aggregates and the new projected symbols
- List<SingleElementSymbol> projectedViewSymbols =
(List<SingleElementSymbol>)NodeEditor.findNodePreOrder(unionSourceParent,
NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS);
+ updateParentAggs(groupNode, context, aggMap, metadata);
- //hack to introduce aggregate symbols to the parent view TODO: this should change the
metadata properly.
- SymbolMap newParentMap = modifyUnionSourceParent(unionSourceParent, virtualGroup,
projectedViewSymbols, virtualElements);
- Map<AggregateSymbol, ElementSymbol> projectedMap = new
HashMap<AggregateSymbol, ElementSymbol>();
- Iterator<AggregateSymbol> aggIter = aggregates.iterator();
- for (ElementSymbol projectedViewSymbol :
newParentMap.getKeys().subList(projectedViewSymbols.size() - aggregates.size(),
projectedViewSymbols.size())) {
- projectedMap.put(aggIter.next(), projectedViewSymbol);
+ List<SingleElementSymbol> symbols = (List<SingleElementSymbol>)
NodeEditor.findNodePreOrder(unionSourceParent,
NodeConstants.Types.PROJECT).getProperty(Info.PROJECT_COLS);
+ GroupSymbol modifiedGroup = group.clone();
+ SymbolMap symbolMap = createSymbolMap(modifiedGroup, symbols, unionSourceParent,
metadata);
+ unionSourceParent.setProperty(Info.SYMBOL_MAP, symbolMap);
+
+ //correct the parent frame
+ Map<Expression, ElementSymbol> mapping = new HashMap<Expression,
ElementSymbol>();
+ Iterator<ElementSymbol> elemIter = symbolMap.getKeys().iterator();
+ for (Expression expr : groupingExpressions) {
+ mapping.put(expr, elemIter.next());
}
- for (Expression expr : aggMap.values()) {
- ExpressionMappingVisitor.mapExpressions(expr, projectedMap);
+ for (AggregateSymbol agg : aggregates) {
+ mapping.put(agg, elemIter.next());
}
- mapExpressions(groupNode.getParent(), aggMap, metadata);
- }
-
- private SymbolMap pushGroupByView(PlanNode plan,
- QueryMetadataInterface metadata, CapabilitiesFinder capFinder,
- PlanNode unionSourceParent, PlanNode setOp,
- PlanNode intermediateView, boolean cardinalityDependent,
- LinkedList<PlanNode> unionChildren,
- List<ElementSymbol> virtualElements, GroupSymbol virtualGroup)
- throws TeiidComponentException, QueryPlannerException,
- QueryResolverException {
- //perform view pushing
- /*
- * TODO: this introduces yet another potentially unneeded view, but cannot be removed
by the normal merge virtual logic
- * due to an intervening access node
- */
- PlanNode intermediateProject = intermediateView.getFirstChild();
- List<SingleElementSymbol> projectedViewSymbols =
(List<SingleElementSymbol>)intermediateProject.getProperty(NodeConstants.Info.PROJECT_COLS);
- for (PlanNode planNode : unionChildren) {
- addView(plan, planNode, false, virtualGroup.clone(), null, Collections.EMPTY_SET,
virtualElements, metadata, capFinder, LanguageObject.Util.deepClone(projectedViewSymbols,
SingleElementSymbol.class));
+ PlanNode node = unionSourceParent;
+ while (node != groupNode.getParent()) {
+ FrameUtil.convertNode(node, null, null, mapping, metadata, false);
+ node = node.getParent();
}
- unionChildren.clear();
- findUnionChildren(unionChildren, cardinalityDependent, setOp);
- virtualGroup = intermediateView.getGroups().iterator().next();
- unionSourceParent.getGroups().clear();
- unionSourceParent.addGroup(virtualGroup);
- projectedViewSymbols =
(List<SingleElementSymbol>)NodeEditor.findNodePreOrder(unionSourceParent,
NodeConstants.Types.PROJECT).getProperty(NodeConstants.Info.PROJECT_COLS);
- SymbolMap parentMap = modifyUnionSourceParent(unionSourceParent, virtualGroup,
projectedViewSymbols, Collections.EMPTY_LIST);
- //remove the old view
- NodeEditor.removeChildNode(intermediateView, intermediateProject);
- NodeEditor.removeChildNode(intermediateView.getParent(), intermediateView);
- return parentMap;
}
- private SymbolMap modifyUnionSourceParent(PlanNode unionSourceParent,
- GroupSymbol virtualGroup,
- List<SingleElementSymbol> projectedViewSymbols, List<ElementSymbol>
baseVirtualElements) {
- List<ElementSymbol> updatedVirturalElement = new
ArrayList<ElementSymbol>(baseVirtualElements);
- for (int i = updatedVirturalElement.size(); i < projectedViewSymbols.size(); i++) {
- SingleElementSymbol symbol = projectedViewSymbols.get(i);
- String name = symbol.getShortName();
- String virtualElementName = virtualGroup.getCanonicalName() +
ElementSymbol.SEPARATOR + name;
- ElementSymbol virtualElement = new ElementSymbol(virtualElementName);
- virtualElement.setGroupSymbol(virtualGroup);
- virtualElement.setType(symbol.getType());
- virtualElement.setMetadataID(new TempMetadataID(virtualElementName,
symbol.getType()));
- updatedVirturalElement.add(virtualElement);
+ private void updateParentAggs(PlanNode groupNode, CommandContext context,
+ Map<AggregateSymbol, Expression> aggMap, QueryMetadataInterface metadata)
+ throws QueryMetadataException, TeiidComponentException, QueryPlannerException {
+ LinkedHashSet<AggregateSymbol> compositeAggs = new
LinkedHashSet<AggregateSymbol>();
+ boolean hasExpressionMapping = false;
+ for (Expression ex : aggMap.values()) {
+ if (ex instanceof AggregateSymbol) {
+ compositeAggs.add((AggregateSymbol) ex);
+ } else {
+ AggregateSymbolCollectorVisitor.getAggregates(ex, compositeAggs, null);
+ hasExpressionMapping = true;
+ }
}
- SymbolMap newParentMap = SymbolMap.createSymbolMap(updatedVirturalElement,
projectedViewSymbols);
- unionSourceParent.setProperty(NodeConstants.Info.SYMBOL_MAP, newParentMap);
- return newParentMap;
+ if (!hasExpressionMapping) {
+ //if no new expressions are created we can just modify the existing aggregates
+ FrameUtil.correctSymbolMap(aggMap, groupNode);
+ } else {
+ //if new expressions are created we insert a view to handle the projection
+ groupNode.getGroups().clear();
+ SymbolMap oldGroupingMap = (SymbolMap) groupNode.getProperty(Info.SYMBOL_MAP);
+ GroupSymbol oldGroup =
oldGroupingMap.asMap().keySet().iterator().next().getGroupSymbol();
+ SymbolMap groupingMap = RelationalPlanner.buildGroupingNode(compositeAggs, (List<?
extends Expression>) groupNode.getProperty(Info.GROUP_COLS), groupNode, context,
idGenerator);
+ ArrayList<SingleElementSymbol> projectCols = new
ArrayList<SingleElementSymbol>(oldGroupingMap.asMap().size());
+ SymbolMap correctedMap = new SymbolMap();
+ Map<Expression, ElementSymbol> inverseMap = groupingMap.inserseMapping();
+ for (Map.Entry<ElementSymbol, Expression> entry :
oldGroupingMap.asMap().entrySet()) {
+ SingleElementSymbol ses = null;
+ if (entry.getValue() instanceof AggregateSymbol) {
+ Expression ex = aggMap.get(entry.getValue());
+ if (ex instanceof AggregateSymbol) {
+ ses = inverseMap.get(ex);
+ } else {
+ ExpressionMappingVisitor.mapExpressions(ex, inverseMap);
+ ses = new ExpressionSymbol("expr", ex); //$NON-NLS-1$
+ }
+ } else {
+ ses = inverseMap.get(entry.getValue());
+ }
+ ses = (SingleElementSymbol) ses.clone();
+ projectCols.add(new AliasSymbol(entry.getKey().getShortCanonicalName(), ses));
+ correctedMap.addMapping(entry.getKey(), SymbolMap.getExpression(ses));
+ }
+ PlanNode projectNode = groupNode.getParent();
+ if (projectNode.getType() != NodeConstants.Types.PROJECT) {
+ projectNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
+ groupNode.addAsParent(projectNode);
+ projectNode.setProperty(Info.PROJECT_COLS, projectCols);
+ RuleDecomposeJoin.createSource(oldGroup, projectNode, correctedMap);
+ } else {
+ FrameUtil.convertFrame(projectNode, oldGroup, null, correctedMap.asMap(), metadata);
+ }
+ }
}
+ /* if partitioned, then we don't need decomposition or the top level group by
+ *
+ * source
+ * set op
+ * project
+ * group [agg(x), {a, b}]
+ * source
+ * child 1
+ * ...
+ *
+ */
private void decomposeGroupBy(PlanNode groupNode, PlanNode sourceNode,
- List<SingleElementSymbol> groupingExpressions,
+ List<Expression> groupingExpressions,
LinkedHashSet<AggregateSymbol> aggregates,
LinkedList<PlanNode> unionChildren, SymbolMap parentMap, QueryMetadataInterface
metadata,
- CapabilitiesFinder capFinder, boolean hadIntermediateView) throws
QueryPlannerException, QueryMetadataException, TeiidComponentException {
+ CapabilitiesFinder capFinder, CommandContext cc) throws QueryPlannerException,
QueryMetadataException, TeiidComponentException, QueryResolverException {
// remove the group node
groupNode.getParent().replaceChild(groupNode, groupNode.getFirstChild());
+
GroupSymbol group = sourceNode.getGroups().iterator().next().clone();
boolean first = true;
- List<SingleElementSymbol> symbols = null;
for (PlanNode planNode : unionChildren) {
- PlanNode groupClone = NodeFactory.getNewNode(NodeConstants.Types.GROUP);
- groupClone.setProperty(Info.GROUP_COLS,
LanguageObject.Util.deepClone(groupingExpressions, SingleElementSymbol.class));
- groupClone.addGroups(groupNode.getGroups());
-
- PlanNode view = RuleDecomposeJoin.createSource(group, planNode, parentMap);
-
- view.addAsParent(groupClone);
-
- PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
-
- Select allSymbols = new Select(groupingExpressions);
- allSymbols.addSymbols(aggregates);
- if (first) {
- first = false;
- QueryRewriter.makeSelectUnique(allSymbols, false);
- symbols = allSymbols.getProjectedSymbols();
- }
- projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS,
allSymbols.getSymbols());
- projectPlanNode.addGroups(view.getGroups());
-
- groupClone.addAsParent(projectPlanNode);
-
- if (hadIntermediateView) {
- //drill down to the possible access node
- planNode = planNode.getFirstChild().getFirstChild();
- }
- if (planNode.getType() == NodeConstants.Types.ACCESS) {
- //TODO: temporarily remove the access node so that the inline view could be
removed if possible
- while (RuleRaiseAccess.raiseAccessNode(planNode, planNode, metadata, capFinder,
true, null) != null) {
- //continue to raise
- }
- }
+ addUnionGroupBy(groupingExpressions, aggregates,
+ parentMap, metadata, capFinder, cc, group, first,
+ planNode, false);
+ first = false;
}
+ List<SingleElementSymbol> symbols = (List<SingleElementSymbol>)
NodeEditor.findNodePreOrder(sourceNode,
NodeConstants.Types.PROJECT).getProperty(Info.PROJECT_COLS);
GroupSymbol modifiedGroup = group.clone();
SymbolMap symbolMap = createSymbolMap(modifiedGroup, symbols, sourceNode, metadata);
sourceNode.setProperty(Info.SYMBOL_MAP, symbolMap);
+
+ //map from the anon group to the updated inline view group
+ SymbolMap map = (SymbolMap)groupNode.getProperty(Info.SYMBOL_MAP);
+ Map<Expression, ElementSymbol> inverse = map.inserseMapping();
+ SymbolMap newMapping = (SymbolMap) NodeEditor.findNodePreOrder(sourceNode,
NodeConstants.Types.GROUP).getProperty(Info.SYMBOL_MAP);
- FrameUtil.convertFrame(sourceNode, group, Collections.singleton(modifiedGroup),
symbolMap.inserseMapping(), metadata);
+ GroupSymbol oldGroup = null;
+ Map<ElementSymbol, ElementSymbol> updatedMapping = new HashMap<ElementSymbol,
ElementSymbol>();
+ for (Map.Entry<ElementSymbol, Expression> entry : symbolMap.asMap().entrySet())
{
+ Expression ex = newMapping.getMappedExpression((ElementSymbol) entry.getValue());
+ ElementSymbol orig = inverse.get(ex);
+ oldGroup = orig.getGroupSymbol();
+ updatedMapping.put(orig, entry.getKey());
+ }
+ FrameUtil.convertFrame(sourceNode, oldGroup, Collections.singleton(modifiedGroup),
updatedMapping, metadata);
}
+ private void addUnionGroupBy(
+ List<Expression> groupingExpressions,
+ LinkedHashSet<AggregateSymbol> aggregates, SymbolMap parentMap,
+ QueryMetadataInterface metadata, CapabilitiesFinder capFinder,
+ CommandContext cc, GroupSymbol group, boolean first, PlanNode planNode, boolean
viewOnly)
+ throws QueryMetadataException, TeiidComponentException,
+ QueryPlannerException, QueryResolverException {
+ List<Expression> groupingColumns =
LanguageObject.Util.deepClone(groupingExpressions, Expression.class);
+
+ //branches other than the first need to have their projected column names updated
+ if (!first) {
+ PlanNode sortNode = NodeEditor.findNodePreOrder(planNode, NodeConstants.Types.SORT,
NodeConstants.Types.SOURCE);
+ List<SingleElementSymbol> sortOrder = null;
+ OrderBy orderBy = null;
+ if (sortNode != null) {
+ orderBy = (OrderBy)sortNode.getProperty(Info.SORT_ORDER);
+ sortOrder = orderBy.getSortKeys();
+ }
+ List<SingleElementSymbol> projectCols = FrameUtil.findTopCols(planNode);
+ List<ElementSymbol> virtualElements = parentMap.getKeys();
+ for (int i = 0; i < virtualElements.size(); i++) {
+ ElementSymbol virtualElem = virtualElements.get(i);
+ SingleElementSymbol projectedSymbol = projectCols.get(i);
+ if
(!projectedSymbol.getShortCanonicalName().equals(virtualElem.getShortCanonicalName())) {
+ if (sortOrder != null) {
+ int sortIndex = sortOrder.indexOf(projectedSymbol);
+ if (sortIndex > -1) {
+ updateSymbolName(sortOrder, sortIndex, virtualElem, sortOrder.get(sortIndex));
+ orderBy.getOrderByItems().get(sortIndex).setSymbol(sortOrder.get(sortIndex));
+ }
+ }
+ updateSymbolName(projectCols, i, virtualElem, projectedSymbol);
+ }
+ }
+ }
+
+ PlanNode view = RuleDecomposeJoin.createSource(group, planNode, parentMap);
+
+ PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
+
+ Select allSymbols = new Select();
+ for (Expression expr : groupingColumns) {
+ allSymbols.addSymbol(new ExpressionSymbol("expr", expr)); //$NON-NLS-1$
+ }
+ if (viewOnly) {
+ for (AggregateSymbol agg : aggregates) {
+ agg = (AggregateSymbol)agg.clone();
+ if (agg.getAggregateFunction() == Type.COUNT) {
+ if (agg.getExpression() == null) {
+ allSymbols.addSymbol(new ExpressionSymbol("stagedAgg", new
Constant(1))); //$NON-NLS-1$
+ } else {
+ SearchedCaseExpression count = new SearchedCaseExpression(Arrays.asList(new
IsNullCriteria(agg.getExpression())), Arrays.asList(new Constant(Integer.valueOf(0))));
+ count.setElseExpression(new Constant(Integer.valueOf(1)));
+ count.setType(DataTypeManager.DefaultDataClasses.INTEGER);
+ allSymbols.addSymbol(new ExpressionSymbol("stagedAgg", count));
//$NON-NLS-1$
+ }
+ } else { //min, max, sum
+ Expression ex = agg.getExpression();
+ ex = ResolverUtil.convertExpression(ex,
DataTypeManager.getDataTypeName(agg.getType()), metadata);
+ allSymbols.addSymbol(new ExpressionSymbol("stagedAgg", ex));
//$NON-NLS-1$
+ }
+ }
+ } else {
+ allSymbols.addSymbols(aggregates);
+ }
+ if (first) {
+ QueryRewriter.makeSelectUnique(allSymbols, false);
+ }
+ projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS, allSymbols.getSymbols());
+ projectPlanNode.addGroups(view.getGroups());
+
+ view.addAsParent(projectPlanNode);
+
+ if (!viewOnly) {
+ addGroupBy(cc, view, groupingColumns, aggregates, metadata,
projectPlanNode.getParent());
+ }
+
+ if (planNode.getType() == NodeConstants.Types.ACCESS) {
+ //TODO: temporarily remove the access node so that the inline view could be removed if
possible
+ while (RuleRaiseAccess.raiseAccessNode(planNode, planNode, metadata, capFinder,
true, null) != null) {
+ //continue to raise
+ }
+ }
+ }
+
+ private void updateSymbolName(List<SingleElementSymbol> projectCols, int i,
+ ElementSymbol virtualElem, SingleElementSymbol projectedSymbol) {
+ if (projectedSymbol instanceof AliasSymbol) {
+ ((AliasSymbol)projectedSymbol).setShortName(virtualElem.getShortCanonicalName());
+ } else {
+ projectCols.set(i, new AliasSymbol(virtualElem.getShortCanonicalName(),
projectedSymbol));
+ }
+ }
+
private boolean canPushGroupByToUnionChild(QueryMetadataInterface metadata,
CapabilitiesFinder capFinder,
- List<SingleElementSymbol> groupingExpressions,
+ List<Expression> groupingExpressions,
LinkedHashSet<AggregateSymbol> aggregates, PlanNode planNode, AnalysisRecord
record)
throws QueryMetadataException, TeiidComponentException {
if (planNode.getType() != NodeConstants.Types.ACCESS) {
@@ -422,16 +479,16 @@
return false;
}
for (AggregateSymbol aggregate : aggregates) {
- if (!CapabilitiesUtil.supportsAggregateFunction(modelId, aggregate, metadata,
capFinder)) {
- return false;
- }
+ if(! CriteriaCapabilityValidatorVisitor.canPushLanguageObject(aggregate, modelId,
metadata, capFinder, record)) {
+ return false;
+ }
}
- if ((groupingExpressions == null || groupingExpressions.isEmpty())) {
+ if (groupingExpressions.isEmpty()) {
if (!CapabilitiesUtil.supports(Capability.QUERY_AGGREGATES_COUNT_STAR, modelId,
metadata, capFinder)) {
return false;
}
} else {
- for (SingleElementSymbol ses : groupingExpressions) {
+ for (Expression ses : groupingExpressions) {
if(! CriteriaCapabilityValidatorVisitor.canPushLanguageObject(ses, modelId, metadata,
capFinder, record)) {
return false;
}
@@ -466,109 +523,7 @@
return null;
}
- public void addView(PlanNode root, PlanNode unionSource, boolean pushdown, GroupSymbol
group, List<SingleElementSymbol> groupingExpressions,
- Set<AggregateSymbol> aggregates, List<ElementSymbol> virtualElements,
- QueryMetadataInterface metadata, CapabilitiesFinder capFinder,
List<SingleElementSymbol> actualProject)
- throws TeiidComponentException, QueryPlannerException, QueryResolverException {
- PlanNode accessNode = null;
- if (pushdown) {
- accessNode = NodeEditor.findNodePreOrder(unionSource, NodeConstants.Types.ACCESS);
- }
- //branches other than the first need to have their projected column names updated
- PlanNode sortNode = NodeEditor.findNodePreOrder(unionSource, NodeConstants.Types.SORT,
NodeConstants.Types.SOURCE);
- List<SingleElementSymbol> sortOrder = null;
- OrderBy orderBy = null;
- if (sortNode != null) {
- orderBy = (OrderBy)sortNode.getProperty(Info.SORT_ORDER);
- sortOrder = orderBy.getSortKeys();
- }
- List<SingleElementSymbol> projectCols = FrameUtil.findTopCols(unionSource);
- for (int i = 0; i < virtualElements.size(); i++) {
- ElementSymbol virtualElem = virtualElements.get(i);
- SingleElementSymbol projectedSymbol = projectCols.get(i);
- if
(!projectedSymbol.getShortCanonicalName().equals(virtualElem.getShortCanonicalName())) {
- if (sortOrder != null) {
- int sortIndex = sortOrder.indexOf(projectedSymbol);
- if (sortIndex > -1) {
- updateSymbolName(sortOrder, sortIndex, virtualElem, sortOrder.get(sortIndex));
- orderBy.getOrderByItems().get(sortIndex).setSymbol(sortOrder.get(sortIndex));
- }
- }
- updateSymbolName(projectCols, i, virtualElem, projectedSymbol);
- }
- }
- PlanNode intermediateView = createView(group, virtualElements, unionSource, metadata);
- SymbolMap symbolMap = (SymbolMap)intermediateView.getProperty(Info.SYMBOL_MAP);
- unionSource = intermediateView;
-
- Set<SingleElementSymbol> newGroupingExpressions = Collections.emptySet();
- if (groupingExpressions != null) {
- newGroupingExpressions = new HashSet<SingleElementSymbol>();
- for (SingleElementSymbol singleElementSymbol : groupingExpressions) {
- newGroupingExpressions.add(symbolMap.getKeys().get(virtualElements.indexOf(singleElementSymbol)).clone());
- }
- }
-
- List<SingleElementSymbol> projectedViewSymbols =
Util.deepClone(symbolMap.getKeys(), SingleElementSymbol.class);
-
- PlanNode parent = NodeEditor.findParent(unionSource,
NodeConstants.Types.SOURCE);
- SymbolMap parentMap = (SymbolMap)
parent.getProperty(NodeConstants.Info.SYMBOL_MAP);
- SymbolMap viewMapping = SymbolMap.createSymbolMap(parentMap.getKeys(),
projectedViewSymbols);
- for (AggregateSymbol agg : aggregates) {
- agg = (AggregateSymbol)agg.clone();
- ExpressionMappingVisitor.mapExpressions(agg, viewMapping.asMap());
- if (pushdown) {
- projectedViewSymbols.add(agg);
- } else {
- if (agg.getAggregateFunction() == Type.COUNT) {
- if (agg.getExpression() == null) {
- projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", new
Constant(1))); //$NON-NLS-1$
- } else {
- SearchedCaseExpression count = new SearchedCaseExpression(Arrays.asList(new
IsNullCriteria(agg.getExpression())), Arrays.asList(new Constant(Integer.valueOf(0))));
- count.setElseExpression(new Constant(Integer.valueOf(1)));
- count.setType(DataTypeManager.DefaultDataClasses.INTEGER);
- projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", count));
//$NON-NLS-1$
- }
- } else { //min, max, sum
- Expression ex = agg.getExpression();
- ex = ResolverUtil.convertExpression(ex,
DataTypeManager.getDataTypeName(agg.getType()), metadata);
- projectedViewSymbols.add(new ExpressionSymbol("stagedAgg", ex));
//$NON-NLS-1$
- }
- }
- }
-
- if (pushdown) {
- unionSource = addGroupBy(unionSource, newGroupingExpressions, new
LinkedList<AggregateSymbol>());
- }
-
- PlanNode projectPlanNode = NodeFactory.getNewNode(NodeConstants.Types.PROJECT);
- unionSource.addAsParent(projectPlanNode);
- unionSource = projectPlanNode;
-
- //create proper names for the aggregate symbols
- Select select = null;
- if (actualProject == null) {
- select = new Select(projectedViewSymbols);
- } else {
- select = new Select(actualProject);
- }
- QueryRewriter.makeSelectUnique(select, false);
- projectedViewSymbols = select.getProjectedSymbols();
- projectPlanNode.setProperty(NodeConstants.Info.PROJECT_COLS,
projectedViewSymbols);
- projectPlanNode.addGroup(group);
- if (pushdown) {
- while (RuleRaiseAccess.raiseAccessNode(root, accessNode, metadata, capFinder,
true, null) != null) {
- //continue to raise
- }
- }
- }
-
- static PlanNode createView(GroupSymbol group, List<? extends SingleElementSymbol>
virtualElements, PlanNode child, QueryMetadataInterface metadata) throws
TeiidComponentException {
- SymbolMap symbolMap = createSymbolMap(group, virtualElements, child, metadata);
- return RuleDecomposeJoin.createSource(group, child, symbolMap);
- }
-
- private static SymbolMap createSymbolMap(GroupSymbol group,
+ static SymbolMap createSymbolMap(GroupSymbol group,
List<? extends SingleElementSymbol> virtualElements,
PlanNode child, QueryMetadataInterface metadata)
throws TeiidComponentException, QueryMetadataException {
@@ -585,15 +540,6 @@
return symbolMap;
}
- private void updateSymbolName(List<SingleElementSymbol> projectCols, int i,
- ElementSymbol virtualElem, SingleElementSymbol projectedSymbol) {
- if (projectedSymbol instanceof AliasSymbol) {
- ((AliasSymbol)projectedSymbol).setShortName(virtualElem.getShortCanonicalName());
- } else {
- projectCols.set(i, new AliasSymbol(virtualElem.getShortCanonicalName(),
projectedSymbol));
- }
- }
-
/**
* Walk up the plan from the GROUP node. Should encounter only (optionally) a SELECT
and can stop at the PROJECT node. Need to
* collect any AggregateSymbols used in the select criteria or projected columns.
@@ -605,23 +551,34 @@
static LinkedHashSet<AggregateSymbol> collectAggregates(PlanNode groupNode) {
LinkedHashSet<AggregateSymbol> aggregates = new
LinkedHashSet<AggregateSymbol>();
PlanNode currentNode = groupNode.getParent();
+ SymbolMap symbolMap = (SymbolMap)
groupNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+
while (currentNode != null) {
if (currentNode.getType() == NodeConstants.Types.PROJECT) {
List<SingleElementSymbol> projectedSymbols =
(List<SingleElementSymbol>)currentNode.getProperty(NodeConstants.Info.PROJECT_COLS);
for (SingleElementSymbol symbol : projectedSymbols) {
-
aggregates.addAll(AggregateSymbolCollectorVisitor.getAggregates(symbol, true));
+ mapAggregates(ElementCollectorVisitor.getAggregates(symbol, true),
symbolMap, aggregates);
}
break;
}
if (currentNode.getType() == NodeConstants.Types.SELECT) {
Criteria crit =
(Criteria)currentNode.getProperty(NodeConstants.Info.SELECT_CRITERIA);
- aggregates.addAll(AggregateSymbolCollectorVisitor.getAggregates(crit,
true));
+ mapAggregates(ElementCollectorVisitor.getAggregates(crit, true),
symbolMap, aggregates);
}
currentNode = currentNode.getParent();
}
return aggregates;
}
+
+ static void mapAggregates(Collection<ElementSymbol> symbols, SymbolMap map,
Collection<? super AggregateSymbol> aggs) {
+ for (ElementSymbol es : symbols) {
+ Expression ex = map.getMappedExpression(es);
+ if (ex instanceof AggregateSymbol) {
+ aggs.add((AggregateSymbol) ex);
+ }
+ }
+ }
/**
* Attempt to push the group node below one or more joins, manipulating the parent
plan as necessary. This may involve
@@ -631,32 +588,39 @@
* @since 4.2
*/
private void pushGroupNode(PlanNode groupNode,
- List<SingleElementSymbol> groupingExpressions,
+ List<Expression> groupingExpressions,
Set<AggregateSymbol> allAggregates,
QueryMetadataInterface metadata,
- CapabilitiesFinder capFinder) throws
TeiidComponentException,
+ CapabilitiesFinder capFinder, CommandContext cc) throws
TeiidComponentException,
QueryMetadataException,
QueryPlannerException {
Map<PlanNode, List<AggregateSymbol>> aggregateMap =
createNodeMapping(groupNode, allAggregates, true);
if (aggregateMap == null) {
return;
}
- Map<PlanNode, List<SingleElementSymbol>> groupingMap =
createNodeMapping(groupNode, groupingExpressions, false);
+ Map<PlanNode, List<Expression>> groupingMap =
createNodeMapping(groupNode, groupingExpressions, false);
Set<PlanNode> possibleTargetNodes = new
LinkedHashSet<PlanNode>(aggregateMap.keySet());
possibleTargetNodes.addAll(groupingMap.keySet());
-
+ for (Map.Entry<PlanNode, List<AggregateSymbol>> entry :
aggregateMap.entrySet()) {
+ if (AggregateSymbol.areAggregatesCardinalityDependent(entry.getValue())) {
+ //can't change the cardinality on the other side of the join -
+ //unless it's a 1-1 join, in which case this optimization isn't needed
+ //TODO: make a better choice if there are multiple targets
+ possibleTargetNodes.clear();
+ possibleTargetNodes.add(entry.getKey());
+ break;
+ }
+ }
for (PlanNode planNode : possibleTargetNodes) {
- Set<SingleElementSymbol> stagedGroupingSymbols = new
LinkedHashSet<SingleElementSymbol>();
- List<AggregateSymbol> aggregates = aggregateMap.get(planNode);
+ Set<Expression> stagedGroupingSymbols = new
LinkedHashSet<Expression>();
+ Collection<AggregateSymbol> aggregates = aggregateMap.get(planNode);
if (!canPush(groupNode, stagedGroupingSymbols, planNode)) {
continue;
}
- if (groupingExpressions != null) {
- filterJoinColumns(stagedGroupingSymbols, planNode.getGroups(),
groupingExpressions);
- }
+ filterJoinColumns(stagedGroupingSymbols, planNode.getGroups(),
groupingExpressions);
collectSymbolsFromOtherAggregates(allAggregates, aggregates, planNode,
stagedGroupingSymbols);
@@ -668,7 +632,7 @@
}
if (aggregates != null) {
- stageAggregates(groupNode, metadata, stagedGroupingSymbols, aggregates);
+ aggregates = stageAggregates(groupNode, metadata, stagedGroupingSymbols,
aggregates, cc);
} else {
aggregates = new ArrayList<AggregateSymbol>(1);
}
@@ -678,12 +642,15 @@
}
//TODO: if aggregates is empty, then could insert a dup remove node instead
- PlanNode stageGroup = addGroupBy(planNode, stagedGroupingSymbols,
aggregates);
-
+ PlanNode stageGroup = addGroupBy(cc, planNode, new
ArrayList<Expression>(stagedGroupingSymbols), aggregates, metadata,
groupNode.getParent());
+
//check for push down
- if (stageGroup.getFirstChild().getType() == NodeConstants.Types.ACCESS
- && RuleRaiseAccess.canRaiseOverGroupBy(stageGroup,
stageGroup.getFirstChild(), aggregates, metadata, capFinder, null)) {
- RuleRaiseAccess.performRaise(null, stageGroup.getFirstChild(),
stageGroup);
+ PlanNode accessNode = stageGroup.getFirstChild();
+ if (accessNode.getType() == NodeConstants.Types.ACCESS
+ && RuleRaiseAccess.canRaiseOverGroupBy(stageGroup,
accessNode, aggregates, metadata, capFinder, null)) {
+ accessNode.getGroups().clear();
+ accessNode.getGroups().addAll(stageGroup.getGroups());
+ RuleRaiseAccess.performRaise(null, accessNode, stageGroup);
if (stagedGroupingSymbols.isEmpty()) {
RuleRaiseAccess.performRaise(null, stageGroup.getParent(),
stageGroup.getParent().getParent());
}
@@ -691,16 +658,14 @@
}
}
- private PlanNode addGroupBy(PlanNode planNode,
- Collection<SingleElementSymbol> stagedGroupingSymbols,
- Collection<AggregateSymbol> aggregates) {
+ private PlanNode addGroupBy(CommandContext cc,
+ PlanNode child, List<Expression> stagedGroupingSymbols,
+ Collection<AggregateSymbol> aggregates, QueryMetadataInterface metadata,
PlanNode endNode) throws QueryMetadataException,
+ TeiidComponentException, QueryPlannerException {
PlanNode stageGroup = NodeFactory.getNewNode(NodeConstants.Types.GROUP);
- planNode.addAsParent(stageGroup);
-
- if (!stagedGroupingSymbols.isEmpty()) {
- stageGroup.setProperty(NodeConstants.Info.GROUP_COLS, new
ArrayList<SingleElementSymbol>(stagedGroupingSymbols));
-
stageGroup.addGroups(GroupsUsedByElementsVisitor.getGroups(stagedGroupingSymbols));
- } else {
+ child.addAsParent(stageGroup);
+ aggregates = new LinkedHashSet<AggregateSymbol>(aggregates);
+ if (stagedGroupingSymbols.isEmpty()) {
// if the source has no rows we need to insert a select node with criteria
count(*)>0
PlanNode selectNode = NodeFactory.getNewNode(NodeConstants.Types.SELECT);
AggregateSymbol count = new AggregateSymbol("stagedAgg",
NonReserved.COUNT, false, null); //$NON-NLS-1$
@@ -710,48 +675,60 @@
selectNode.setProperty(NodeConstants.Info.IS_HAVING, Boolean.TRUE);
stageGroup.addAsParent(selectNode);
}
+
+ Map<Expression, ElementSymbol> reverseMapping =
RelationalPlanner.buildGroupingNode(aggregates, stagedGroupingSymbols, stageGroup, cc,
idGenerator).inserseMapping();
+ GroupSymbol newGroup = reverseMapping.values().iterator().next().getGroupSymbol();
+ PlanNode node = stageGroup.getParent();
+ while (node != endNode) {
+ if (node.getType() == NodeConstants.Types.JOIN) {
+ node.getGroups().removeAll(FrameUtil.findJoinSourceNode(stageGroup.getFirstChild()).getGroups());
+ node.getGroups().add(newGroup);
+ }
+ FrameUtil.convertNode(node, null, null, reverseMapping, metadata, false);
+ if (node.getType() == NodeConstants.Types.JOIN) {
+ //reset the left/right/non-equi join criteria
+ RuleChooseJoinStrategy.chooseJoinStrategy(node, metadata);
+ }
+ node = node.getParent();
+ }
return stageGroup;
}
- static void stageAggregates(PlanNode groupNode,
+ Set<AggregateSymbol> stageAggregates(PlanNode groupNode,
QueryMetadataInterface metadata,
- Collection<SingleElementSymbol>
stagedGroupingSymbols,
- Collection<AggregateSymbol> aggregates) throws
TeiidComponentException, QueryPlannerException {
+ Set<Expression> stagedGroupingSymbols,
+ Collection<AggregateSymbol> aggregates,
CommandContext context) throws TeiidComponentException, QueryPlannerException {
//remove any aggregates that are computed over a group by column
- Set<Expression> expressions = new HashSet<Expression>();
- for (SingleElementSymbol expression : stagedGroupingSymbols) {
- expressions.add(SymbolMap.getExpression(expression));
- }
-
for (final Iterator<AggregateSymbol> iterator = aggregates.iterator();
iterator.hasNext();) {
final AggregateSymbol symbol = iterator.next();
Expression expr = symbol.getExpression();
if (expr == null) {
continue;
}
- if (expressions.contains(expr)) {
+ if (stagedGroupingSymbols.contains(expr)) {
iterator.remove();
}
}
- if (!aggregates.isEmpty()) {
- // Fix any aggregate expressions so they correctly recombine the staged
aggregates
- try {
- Set<AggregateSymbol> newAggs = new
HashSet<AggregateSymbol>();
- Map<AggregateSymbol, Expression> aggMap =
buildAggregateMap(aggregates, metadata, newAggs);
- mapExpressions(groupNode.getParent(), aggMap, metadata);
- aggregates.clear();
- aggregates.addAll(newAggs);
- } catch (QueryResolverException err) {
- throw new TeiidComponentException(err);
- }
- }
+ if (aggregates.isEmpty()) {
+ return Collections.emptySet();
+ }
+ // Fix any aggregate expressions so they correctly recombine the staged
aggregates
+ Set<AggregateSymbol> newAggs = new HashSet<AggregateSymbol>();
+ Map<AggregateSymbol, Expression> aggMap;
+ try {
+ aggMap = buildAggregateMap(aggregates, metadata, newAggs);
+ } catch (QueryResolverException e) {
+ throw new QueryPlannerException(e, e.getMessage());
+ }
+ updateParentAggs(groupNode, context, aggMap, metadata);
+ return newAggs;
}
private void collectSymbolsFromOtherAggregates(Collection<AggregateSymbol>
allAggregates,
Collection<AggregateSymbol>
aggregates,
PlanNode current,
- Set<SingleElementSymbol>
stagedGroupingSymbols) {
+ Set<Expression>
stagedGroupingSymbols) {
Set<AggregateSymbol> otherAggs = new
HashSet<AggregateSymbol>(allAggregates);
if (aggregates != null) {
otherAggs.removeAll(aggregates);
@@ -772,7 +749,7 @@
* Ensures that we are only pushing through inner equi joins or cross joins. Also
collects the necessary staged grouping symbols
*/
private boolean canPush(PlanNode groupNode,
- Set<SingleElementSymbol> stagedGroupingSymbols,
+ Set<Expression> stagedGroupingSymbols,
PlanNode planNode) {
PlanNode parentJoin = planNode.getParent();
@@ -786,12 +763,12 @@
}
if (planNode == parentJoin.getFirstChild()) {
- if (parentJoin.hasCollectionProperty(NodeConstants.Info.LEFT_EXPRESSIONS)
&& !filterJoinColumns(stagedGroupingSymbols, groups,
(List<SingleElementSymbol>)parentJoin.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS)))
{
- return false;
+ if
(parentJoin.hasCollectionProperty(NodeConstants.Info.LEFT_EXPRESSIONS)) {
+ filterJoinColumns(stagedGroupingSymbols, groups,
(List<SingleElementSymbol>)parentJoin.getProperty(NodeConstants.Info.LEFT_EXPRESSIONS));
}
} else {
- if
(parentJoin.hasCollectionProperty(NodeConstants.Info.RIGHT_EXPRESSIONS) &&
!filterJoinColumns(stagedGroupingSymbols, groups,
(List<SingleElementSymbol>)parentJoin.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS)))
{
- return false;
+ if
(parentJoin.hasCollectionProperty(NodeConstants.Info.RIGHT_EXPRESSIONS)) {
+ filterJoinColumns(stagedGroupingSymbols, groups,
(List<SingleElementSymbol>)parentJoin.getProperty(NodeConstants.Info.RIGHT_EXPRESSIONS));
}
}
@@ -801,21 +778,17 @@
return true;
}
- private boolean filterJoinColumns(Set<SingleElementSymbol>
stagedGroupingSymbols,
+ private void filterJoinColumns(Set<Expression> stagedGroupingSymbols,
Set<GroupSymbol> groups,
- List<SingleElementSymbol> symbols) {
- for (SingleElementSymbol singleElementSymbol : symbols) {
- if (!(singleElementSymbol instanceof ElementSymbol)) {
- return false;
+ List<? extends Expression> symbols) {
+ for (Expression ex : symbols) {
+ if (groups.containsAll(GroupsUsedByElementsVisitor.getGroups(ex))) {
+ stagedGroupingSymbols.add(SymbolMap.getExpression(ex));
}
- if (groups.contains(((ElementSymbol)singleElementSymbol).getGroupSymbol()))
{
- stagedGroupingSymbols.add(singleElementSymbol);
- }
}
- return true;
}
- private <T extends SingleElementSymbol> Map<PlanNode, List<T>>
createNodeMapping(PlanNode groupNode,
+ private <T extends Expression> Map<PlanNode, List<T>>
createNodeMapping(PlanNode groupNode,
Collection<T> expressions, boolean aggs) {
Map<PlanNode, List<T>> result = new LinkedHashMap<PlanNode,
List<T>>();
if (expressions == null) {
@@ -825,11 +798,14 @@
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
}
+ if (aggs && !((AggregateSymbol)aggregateSymbol).canStage()) {
+ continue;
+ }
Set<GroupSymbol> groups =
GroupsUsedByElementsVisitor.getGroups(aggregateSymbol);
if (groups.isEmpty()) {
continue;
}
- PlanNode originatingNode = FrameUtil.findOriginatingNode(groupNode, groups);
+ PlanNode originatingNode =
FrameUtil.findOriginatingNode(groupNode.getFirstChild(), groups);
if (originatingNode == null) {
if (aggs) {
return null; //should never happen
@@ -855,6 +831,10 @@
continue;
}
+ if (originatingNode.getType() != NodeConstants.Types.ACCESS) {
+ continue; //don't perform intermediate grouping
+ }
+
if (aggs && ((AggregateSymbol)aggregateSymbol).isDistinct()) {
//TODO: support distinct
continue;
@@ -873,7 +853,7 @@
private static Map<AggregateSymbol, Expression>
buildAggregateMap(Collection<? extends SingleElementSymbol> aggregateExpressions,
QueryMetadataInterface metadata, Set<AggregateSymbol> nestedAggregates) throws
QueryResolverException,
TeiidComponentException {
- Map<AggregateSymbol, Expression> aggMap = new HashMap<AggregateSymbol,
Expression>();
+ Map<AggregateSymbol, Expression> aggMap = new
LinkedHashMap<AggregateSymbol, Expression>();
for (SingleElementSymbol symbol : aggregateExpressions) {
AggregateSymbol partitionAgg = (AggregateSymbol)symbol;
@@ -883,7 +863,6 @@
if (aggFunction == Type.COUNT) {
//COUNT(x) -> CONVERT(SUM(COUNT(x)), INTEGER)
AggregateSymbol newAgg = new AggregateSymbol("stagedAgg",
NonReserved.SUM, false, partitionAgg); //$NON-NLS-1$
-
// Build conversion function to convert SUM (which returns LONG) back to
INTEGER
Function convertFunc = new Function(FunctionLibrary.CONVERT, new
Expression[] {newAgg, new
Constant(DataTypeManager.getDataTypeName(partitionAgg.getType()))});
ResolverVisitor.resolveLanguageObject(convertFunc, metadata);
@@ -945,10 +924,7 @@
nestedAggregates.add(countAgg);
nestedAggregates.add(sumAgg);
nestedAggregates.add(sumSqAgg);
- } else if (aggFunction == Type.TEXTAGG) {
- continue;
- }
- else {
+ } else {
//AGG(X) -> AGG(AGG(X))
newExpression = new AggregateSymbol("stagedAgg",
aggFunction.name(), false, partitionAgg); //$NON-NLS-1$
nestedAggregates.add(partitionAgg);
@@ -959,22 +935,6 @@
return aggMap;
}
- static void mapExpressions(PlanNode node, Map<? extends Expression, ? extends
Expression> exprMap, QueryMetadataInterface metadata)
- throws QueryPlannerException {
-
- while (node != null) {
- FrameUtil.convertNode(node, null, null, exprMap, metadata, true);
-
- switch (node.getType()) {
- case NodeConstants.Types.SOURCE:
- case NodeConstants.Types.GROUP:
- return;
- }
-
- node = node.getParent();
- }
- }
-
/**
* @see java.lang.Object#toString()
* @since 4.2
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RulePushSelectCriteria.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -43,6 +43,7 @@
import org.teiid.query.optimizer.relational.plantree.NodeEditor;
import org.teiid.query.optimizer.relational.plantree.NodeFactory;
import org.teiid.query.optimizer.relational.plantree.PlanNode;
+import org.teiid.query.optimizer.relational.plantree.NodeConstants.Info;
import org.teiid.query.resolver.util.AccessPattern;
import org.teiid.query.sql.lang.CompoundCriteria;
import org.teiid.query.sql.lang.Criteria;
@@ -52,7 +53,6 @@
import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.util.SymbolMap;
-import org.teiid.query.sql.visitor.AggregateSymbolCollectorVisitor;
import org.teiid.query.sql.visitor.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.ValueIteratorProviderCollectorVisitor;
import org.teiid.query.util.CommandContext;
@@ -113,7 +113,7 @@
boolean moved = false;
- if((critNode.getGroups().isEmpty() &&
critNode.getSubqueryContainers().isEmpty()) || !atBoundary(critNode, sourceNode)) {
+ if(critNode.hasBooleanProperty(Info.IS_PUSHED) ||
(critNode.getGroups().isEmpty() && critNode.getSubqueryContainers().isEmpty()) ||
!atBoundary(critNode, sourceNode)) {
deadNodes.add(critNode);
continue;
}
@@ -132,6 +132,16 @@
break;
}
}
+ case NodeConstants.Types.GROUP:
+ {
+ if (!critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
+ SymbolMap symbolMap = (SymbolMap)
sourceNode.getProperty(NodeConstants.Info.SYMBOL_MAP);
+ FrameUtil.convertNode(critNode, null, null, symbolMap.asMap(),
metadata, true);
+ NodeEditor.removeChildNode(critNode.getParent(), critNode);
+ sourceNode.getFirstChild().addAsParent(critNode);
+ moved = true;
+ }
+ }
}
if (!moved) {
@@ -333,8 +343,6 @@
satisfyAccessPatterns(critNode, currentNode);
} else if (FrameUtil.isOrderedLimit(currentNode)) {
return currentNode;
- } else if (currentNode.getType() == NodeConstants.Types.GROUP &&
critNode.hasBooleanProperty(NodeConstants.Info.IS_HAVING)) {
- return currentNode;
}
}
@@ -598,7 +606,7 @@
return false;
}
- if (!AggregateSymbolCollectorVisitor.getAggregates(converted,
false).isEmpty()) {
+ if (!ElementCollectorVisitor.getAggregates(converted, false).isEmpty()) {
result = Boolean.TRUE;
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseAccess.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -163,6 +163,8 @@
{
Set<AggregateSymbol> aggregates =
RulePushAggregates.collectAggregates(parentNode);
if (canRaiseOverGroupBy(parentNode, accessNode, aggregates, metadata,
capFinder, record)) {
+ accessNode.getGroups().clear();
+ accessNode.getGroups().addAll(parentNode.getGroups());
return performRaise(rootNode, accessNode, parentNode);
}
return null;
@@ -302,14 +304,14 @@
if(modelID == null) {
return false;
}
- List<SingleElementSymbol> groupCols =
(List<SingleElementSymbol>)groupNode.getProperty(NodeConstants.Info.GROUP_COLS);
+ List<Expression> groupCols =
(List<Expression>)groupNode.getProperty(NodeConstants.Info.GROUP_COLS);
if(!CapabilitiesUtil.supportsAggregates(groupCols, modelID, metadata, capFinder))
{
recordDebug("cannot push group by, since group by is not supported by
source", groupNode, record); //$NON-NLS-1$
return false;
}
if (groupCols != null) {
- for (SingleElementSymbol singleElementSymbol : groupCols) {
- if (!canPushSymbol(singleElementSymbol, false, modelID, metadata,
capFinder, record)) {
+ for (Expression expr : groupCols) {
+ if (!canPushSymbol(expr, false, modelID, metadata, capFinder, record)) {
return false;
}
}
@@ -467,7 +469,7 @@
* @throws QueryMetadataException
* @since 4.1.2
*/
- private static boolean canPushSymbol(SingleElementSymbol symbol, boolean
inSelectClause, Object modelID,
+ private static boolean canPushSymbol(Expression symbol, boolean inSelectClause,
Object modelID,
QueryMetadataInterface metadata, CapabilitiesFinder capFinder, AnalysisRecord
record)
throws TeiidComponentException, QueryMetadataException {
Modified:
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseNull.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseNull.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/optimizer/relational/rules/RuleRaiseNull.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -44,6 +44,8 @@
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.lang.SetQuery;
import org.teiid.query.sql.symbol.AliasSymbol;
+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.GroupSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
@@ -277,7 +279,7 @@
NodeEditor.removeChildNode(joinNode.getParent(), joinNode);
for (GroupSymbol group : nullNode.getGroups()) {
- Map nullSymbolMap = FrameUtil.buildSymbolMap(group, null, metadata);
+ Map<ElementSymbol, Expression> nullSymbolMap =
FrameUtil.buildSymbolMap(group, null, metadata);
FrameUtil.convertFrame(frameStart, group, null, nullSymbolMap, metadata);
}
Modified: trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/parser/ParseInfo.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -37,9 +37,6 @@
public int referenceCount = 0;
- // This gets set according to the current clause
- public boolean aggregatesAllowed = false;
-
// treat a double quoted variable as variable instead of string
public boolean
ansiQuotedIdentifiers=Boolean.valueOf(System.getProperty("org.teiid.ansiQuotedIdentifiers",
Boolean.TRUE.toString())).booleanValue(); //$NON-NLS-1$
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/DependentCriteriaProcessor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -51,6 +51,7 @@
import org.teiid.query.sql.lang.SetCriteria;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.util.ValueIterator;
@@ -90,11 +91,11 @@
DependentValueSource originalVs =
(DependentValueSource)dependentNode.getContext().getVariableContext().getGlobalValue(valueSource);
if (!originalVs.isDistinct()) {
if (sortUtility == null) {
- List<Expression> sortSymbols = new
ArrayList<Expression>(dependentSetStates.size());
+ List<SingleElementSymbol> sortSymbols = new
ArrayList<SingleElementSymbol>(dependentSetStates.size());
List<Boolean> sortDirection = new
ArrayList<Boolean>(sortSymbols.size());
for (int i = 0; i < dependentSetStates.size(); i++) {
sortDirection.add(Boolean.valueOf(OrderBy.ASC));
- sortSymbols.add(dependentSetStates.get(i).valueExpression);
+
sortSymbols.add((SingleElementSymbol)dependentSetStates.get(i).valueExpression);
}
this.sortUtility = new
SortUtility(originalVs.getTupleBuffer().createIndexedTupleSource(), sortSymbols,
sortDirection, Mode.DUP_REMOVE, dependentNode.getBufferManager(),
dependentNode.getConnectionID(), originalVs.getTupleBuffer().getSchema());
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -22,8 +22,7 @@
package org.teiid.query.processor.relational;
-import static org.teiid.query.analysis.AnalysisRecord.PROP_GROUP_COLS;
-import static org.teiid.query.analysis.AnalysisRecord.PROP_SORT_MODE;
+import static org.teiid.query.analysis.AnalysisRecord.*;
import java.util.ArrayList;
import java.util.Arrays;
@@ -62,18 +61,19 @@
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.symbol.TextLine;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+import org.teiid.query.sql.util.SymbolMap;
import org.teiid.query.util.CommandContext;
public class GroupingNode extends RelationalNode {
// Grouping columns set by the planner
- private List sortElements;
- private List sortTypes;
+ private List<Expression> sortElements;
+ private List<Boolean> sortTypes;
private boolean removeDuplicates;
+ private SymbolMap outputMapping;
// Collection phase
private int phase = COLLECTION;
@@ -87,8 +87,10 @@
// Group phase
private AggregateFunction[] functions;
+ private int[] conditions;
private List lastRow;
private List currentGroupTuple;
+ private Evaluator eval;
private static final int COLLECTION = 1;
private static final int SORT = 2;
@@ -127,12 +129,16 @@
* @param groupingElements
* @since 4.2
*/
- public void setGroupingElements(List groupingElements) {
+ public void setGroupingElements(List<Expression> groupingElements) {
this.sortElements = groupingElements;
if(groupingElements != null) {
sortTypes = Collections.nCopies(groupingElements.size(),
Boolean.valueOf(OrderBy.ASC));
}
}
+
+ public void setOutputMapping(SymbolMap outputMapping) {
+ this.outputMapping = outputMapping;
+ }
@Override
public void initialize(CommandContext context, BufferManager bufferManager,
@@ -157,13 +163,20 @@
// Construct aggregate function state accumulators
functions = new AggregateFunction[getElements().size()];
+ conditions = new int[getElements().size()];
for(int i=0; i<getElements().size(); i++) {
- SingleElementSymbol symbol = (SingleElementSymbol)getElements().get(i);
+ Expression symbol = (Expression) getElements().get(i);
+ if (this.outputMapping != null) {
+ symbol = outputMapping.getMappedExpression((ElementSymbol)symbol);
+ }
Class<?> outputType = symbol.getType();
Class<?> inputType = symbol.getType();
+ conditions[i] = -1;
if(symbol instanceof AggregateSymbol) {
AggregateSymbol aggSymbol = (AggregateSymbol) symbol;
-
+ if (aggSymbol.getCondition() != null) {
+ conditions[i] = collectExpression(aggSymbol.getCondition());
+ }
if(aggSymbol.getExpression() == null) {
functions[i] = new Count();
} else {
@@ -198,7 +211,6 @@
break;
default:
functions[i] = new StatsFunction(function);
-
}
if(aggSymbol.isDistinct() &&
!function.equals(NonReserved.MIN) && !function.equals(NonReserved.MAX)) {
@@ -281,8 +293,6 @@
return new BatchCollector.BatchProducerTupleSource(sourceNode) {
- Evaluator eval = new Evaluator(elementMap, getDataManager(), getContext());
-
@Override
protected List updateTuple(List tuple) throws ExpressionEvaluationException,
BlockedException, TeiidComponentException {
int columns = collectedExpressions.size();
@@ -300,14 +310,20 @@
}
private void collectionPhase() {
+ eval = new Evaluator(elementMap, getDataManager(), getContext());
if(this.sortElements == null) {
// No need to sort
this.groupTupleSource = getCollectionTupleSource();
this.phase = GROUP;
} else {
- this.sortUtility = new SortUtility(getCollectionTupleSource(), sortElements,
+ //create a temporary positional schema
+ List<ElementSymbol> schema = new ArrayList<ElementSymbol>();
+ for (int i = 0; i < collectedExpressions.size(); i++) {
+ schema.add(new ElementSymbol(String.valueOf(i)));
+ }
+ this.sortUtility = new SortUtility(getCollectionTupleSource(),
schema.subList(0, sortElements.size()),
sortTypes,
removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, getBufferManager(),
- getConnectionID(),
collectedExpressions);
+ getConnectionID(), schema);
this.phase = SORT;
}
}
@@ -357,7 +373,7 @@
}
if(lastRow != null || sortElements == null) {
// Close last group
- List row = new ArrayList(functions.length);
+ List<Object> row = new ArrayList<Object>(functions.length);
for(int i=0; i<functions.length; i++) {
row.add( functions[i].getResult() );
}
@@ -397,10 +413,13 @@
return true;
}
- private void updateAggregates(List tuple)
+ private void updateAggregates(List<?> tuple)
throws TeiidComponentException, TeiidProcessingException {
for(int i=0; i<functions.length; i++) {
+ if (conditions[i] != -1 &&
!Boolean.TRUE.equals(tuple.get(conditions[i]))) {
+ continue;
+ }
functions[i].addInput(tuple);
}
}
@@ -415,6 +434,9 @@
protected void getNodeString(StringBuffer str) {
super.getNodeString(str);
str.append(sortElements);
+ if (outputMapping != null) {
+ str.append(outputMapping);
+ }
}
public Object clone(){
@@ -423,6 +445,7 @@
clonedNode.sortElements = sortElements;
clonedNode.sortTypes = sortTypes;
clonedNode.removeDuplicates = removeDuplicates;
+ clonedNode.outputMapping = outputMapping;
return clonedNode;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -45,6 +45,7 @@
import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.symbol.Expression;
+import org.teiid.query.sql.symbol.SingleElementSymbol;
/**
@@ -152,7 +153,7 @@
this.comparator.setNullOrdering(nullOrderings);
}
- public SortUtility(TupleSource ts, List expressions, List<Boolean> types,
+ public SortUtility(TupleSource ts, List<? extends SingleElementSymbol>
expressions, List<Boolean> types,
Mode mode, BufferManager bufferManager, String connectionID, List schema) {
this(ts, new OrderBy(expressions, types).getOrderByItems(), mode, bufferManager,
connectionID, schema);
}
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverUtil.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -333,7 +333,7 @@
List<SingleElementSymbol> knownElements =
command.getProjectedQuery().getSelect().getProjectedSymbols();
boolean isSimpleQuery = false;
- List fromClauseGroups = Collections.emptyList();
+ List<GroupSymbol> fromClauseGroups = Collections.emptyList();
if (command instanceof Query) {
Query query = (Query)command;
Modified: trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -57,6 +57,7 @@
import org.teiid.query.sql.lang.SubqueryCompareCriteria;
import org.teiid.query.sql.lang.SubquerySetCriteria;
import org.teiid.query.sql.navigator.PostOrderNavigator;
+import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.CaseExpression;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.DerivedColumn;
@@ -423,6 +424,17 @@
handleException(e);
}
}
+
+ @Override
+ public void visit(AggregateSymbol obj) {
+ if (obj.getCondition() != null) {
+ try {
+ obj.setCondition(ResolverUtil.convertExpression(obj.getCondition(),
DataTypeManager.DefaultDataTypes.BOOLEAN, metadata));
+ } catch (QueryResolverException e) {
+ handleException(e);
+ }
+ }
+ }
public TeiidComponentException getComponentException() {
return this.componentException;
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -148,6 +148,7 @@
import org.teiid.query.sql.symbol.Reference;
import org.teiid.query.sql.symbol.ScalarSubquery;
import org.teiid.query.sql.symbol.SearchedCaseExpression;
+import org.teiid.query.sql.symbol.SelectSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.util.SymbolMap;
@@ -759,83 +760,17 @@
* Converts a group by with expressions into a group by with only element symbols and an
inline view
* @param query
* @return
- * @throws QueryValidatorException
+ * @throws TeiidProcessingException
+ * @throws TeiidComponentException
*/
- private Query rewriteGroupBy(Query query) throws TeiidComponentException,
TeiidProcessingException{
+ private Query rewriteGroupBy(Query query) throws TeiidComponentException,
TeiidProcessingException {
if (query.getGroupBy() == null) {
return query;
}
if (isDistinctWithGroupBy(query)) {
query.getSelect().setDistinct(false);
}
- // we check for group by expressions here to create an ANSI SQL plan
- boolean hasExpression = false;
- for (final Iterator iterator = query.getGroupBy().getSymbols().iterator();
!hasExpression && iterator.hasNext();) {
- hasExpression = iterator.next() instanceof ExpressionSymbol;
- }
- if (!hasExpression) {
- return query;
- }
- Select select = query.getSelect();
- GroupBy groupBy = query.getGroupBy();
- query.setGroupBy(null);
- Criteria having = query.getHaving();
- query.setHaving(null);
- OrderBy orderBy = query.getOrderBy();
- query.setOrderBy(null);
- Limit limit = query.getLimit();
- query.setLimit(null);
- Into into = query.getInto();
- query.setInto(null);
- Set<Expression> newSelectColumns = new HashSet<Expression>();
- for (final Iterator iterator = groupBy.getSymbols().iterator();
iterator.hasNext();) {
-
newSelectColumns.add(SymbolMap.getExpression((SingleElementSymbol)iterator.next()));
- }
- Set<AggregateSymbol> aggs = new HashSet<AggregateSymbol>();
- aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(select, true));
- if (having != null) {
- aggs.addAll(AggregateSymbolCollectorVisitor.getAggregates(having, true));
- }
- for (AggregateSymbol aggregateSymbol : aggs) {
- if (aggregateSymbol.getExpression() != null) {
- Expression expr = aggregateSymbol.getExpression();
- newSelectColumns.add(SymbolMap.getExpression(expr));
- }
- }
- Select innerSelect = new Select();
- int index = 0;
- for (Expression expr : newSelectColumns) {
- if (expr instanceof SingleElementSymbol) {
- innerSelect.addSymbol((SingleElementSymbol)expr);
- } else {
- innerSelect.addSymbol(new ExpressionSymbol("EXPR" + index++ ,
expr)); //$NON-NLS-1$
- }
- }
- query.setSelect(innerSelect);
- Query outerQuery = null;
- try {
- outerQuery = QueryRewriter.createInlineViewQuery(new
GroupSymbol("X"), query, metadata, query.getSelect().getProjectedSymbols());
//$NON-NLS-1$
- } catch (TeiidException err) {
- throw new TeiidRuntimeException(err);
- }
- Iterator<SingleElementSymbol> iter =
outerQuery.getSelect().getProjectedSymbols().iterator();
- HashMap<Expression, SingleElementSymbol> expressionMap = new
HashMap<Expression, SingleElementSymbol>();
- for (SingleElementSymbol symbol : query.getSelect().getProjectedSymbols()) {
- expressionMap.put(SymbolMap.getExpression(symbol), iter.next());
- }
- ExpressionMappingVisitor.mapExpressions(groupBy, expressionMap);
- outerQuery.setGroupBy(groupBy);
- ExpressionMappingVisitor.mapExpressions(having, expressionMap);
- outerQuery.setHaving(having);
- ExpressionMappingVisitor.mapExpressions(orderBy, expressionMap);
- outerQuery.setOrderBy(orderBy);
- outerQuery.setLimit(limit);
- ExpressionMappingVisitor.mapExpressions(select, expressionMap);
- outerQuery.setSelect(select);
- outerQuery.setInto(into);
- outerQuery.setOption(query.getOption());
- query = outerQuery;
- rewriteExpressions(innerSelect);
+ rewriteExpressions(query.getGroupBy());
return query;
}
@@ -848,7 +783,7 @@
for (SingleElementSymbol selectExpr : query.getSelect().getProjectedSymbols()) {
selectExpressions.add(SymbolMap.getExpression(selectExpr));
}
- for (SingleElementSymbol groupByExpr :
(List<SingleElementSymbol>)groupBy.getSymbols()) {
+ for (Expression groupByExpr : groupBy.getSymbols()) {
if (!selectExpressions.contains(groupByExpr)) {
return false;
}
@@ -2311,6 +2246,17 @@
expression.setAggregateFunction(Type.MAX);
}
}
+ if (expression.getExpression() != null && expression.getCondition() != null
&& !expression.respectsNulls()) {
+ Expression cond = expression.getCondition();
+ Expression ex = expression.getExpression();
+ if (!(cond instanceof Criteria)) {
+ cond = new ExpressionCriteria(cond);
+ }
+ SearchedCaseExpression sce = new SearchedCaseExpression(Arrays.asList(cond),
Arrays.asList(ex));
+ sce.setType(ex.getType());
+ expression.setCondition(null);
+ expression.setExpression(sce);
+ }
return expression;
}
@@ -2756,7 +2702,7 @@
select.setSymbols(select.getProjectedSymbols());
- List symbols = select.getSymbols();
+ List<SelectSymbol> symbols = select.getSymbols();
HashSet<String> uniqueNames = new HashSet<String>();
Modified: trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/LanguageVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -97,6 +97,7 @@
import org.teiid.query.sql.symbol.ScalarSubquery;
import org.teiid.query.sql.symbol.SearchedCaseExpression;
import org.teiid.query.sql.symbol.TextLine;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.symbol.XMLAttributes;
import org.teiid.query.sql.symbol.XMLElement;
import org.teiid.query.sql.symbol.XMLForest;
@@ -223,4 +224,6 @@
public void visit(AlterView obj) {}
public void visit(AlterProcedure obj) {}
public void visit(AlterTrigger obj) {}
+
+ public void visit(WindowFunction windowFunction) {}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/GroupBy.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/GroupBy.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/GroupBy.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -23,13 +23,10 @@
package org.teiid.query.sql.lang;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
import java.util.List;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
-import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.LanguageObject;
import org.teiid.query.sql.LanguageVisitor;
import org.teiid.query.sql.symbol.Expression;
@@ -46,7 +43,7 @@
public class GroupBy implements LanguageObject {
/** The set of expressions for the data elements to be group. */
- private List symbols; // List<Expression>
+ private List<Expression> symbols;
// =========================================================================
// C O N S T R U C T O R S
@@ -56,15 +53,15 @@
* Constructs a default instance of this class.
*/
public GroupBy() {
- symbols = new ArrayList();
+ symbols = new ArrayList<Expression>();
}
/**
* Constructs an instance of this class from an ordered set of symbols.
* @param symbols The ordered list of {@link
org.teiid.query.sql.symbol.ElementSymbol}s
*/
- public GroupBy( List symbols ) {
- this.symbols = new ArrayList( symbols );
+ public GroupBy( List<? extends Expression> symbols ) {
+ this.symbols = new ArrayList<Expression>( symbols );
}
// =========================================================================
@@ -83,7 +80,7 @@
* Returns an ordered list of the symbols in the GROUP BY
* @return List of {@link org.teiid.query.sql.symbol.ElementSymbol}s
*/
- public List getSymbols() {
+ public List<Expression> getSymbols() {
return symbols;
}
@@ -97,19 +94,6 @@
}
}
- /**
- * Replaces the existing set of symbols with a new collection of symbols
- * @param symbols Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}s
- * to replace current symbols with
- */
- public void replaceSymbols( Collection symbols ) {
- if(symbols == null) {
- throw new
IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0003"));
//$NON-NLS-1$
- }
-
- this.symbols = new ArrayList(symbols);
- }
-
public void acceptVisitor(LanguageVisitor visitor) {
visitor.visit(this);
}
@@ -123,15 +107,7 @@
* @return Deep copy of object
*/
public Object clone() {
- List thisSymbols = getSymbols();
- List copySymbols = new ArrayList(thisSymbols.size());
- Iterator iter = thisSymbols.iterator();
- while(iter.hasNext()) {
- Expression es = (Expression) iter.next();
- copySymbols.add(es.clone());
- }
-
- return new GroupBy(copySymbols);
+ return new GroupBy(LanguageObject.Util.deepClone(this.symbols, Expression.class));
}
/**
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -102,6 +102,7 @@
import org.teiid.query.sql.symbol.ScalarSubquery;
import org.teiid.query.sql.symbol.SearchedCaseExpression;
import org.teiid.query.sql.symbol.TextLine;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.symbol.XMLAttributes;
import org.teiid.query.sql.symbol.XMLElement;
import org.teiid.query.sql.symbol.XMLForest;
@@ -140,12 +141,12 @@
visitVisitor(obj);
}
}
-
public void visit(AggregateSymbol obj) {
preVisitVisitor(obj);
visitNode(obj.getExpression());
visitNode(obj.getOrderBy());
+ visitNode(obj.getCondition());
postVisitVisitor(obj);
}
public void visit(AliasSymbol obj) {
@@ -700,6 +701,15 @@
postVisitVisitor(obj);
}
+ @Override
+ public void visit(WindowFunction obj) {
+ preVisitVisitor(obj);
+ visitNode(obj.getFunction());
+ visitNodes(obj.getPartition());
+ visitNode(obj.getOrderBy());
+ postVisitVisitor(obj);
+ }
+
public static void doVisit(LanguageObject object, LanguageVisitor visitor, boolean
order) {
doVisit(object, visitor, order, false);
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -34,14 +34,7 @@
/**
- * <p>An aggregate symbol represents an aggregate function in the SELECT or HAVING
clauses. It
- * extends ExpressionSymbol as they have many things in common. The aggregate symbol is
- * typically something like <code>SUM(stock.quantity * 2)</code>. There are
five supported
- * aggregate functions: COUNT, SUM, AVG, MIN, and MAX. Aggregate functions contain an
expression -
- * this data is managed by the super class, ExpressionSymbol. Aggregate functions may
also
- * specify a DISTINCT flag to indicate that duplicates should be ignored. The DISTINCT
flag
- * may be set for all five aggregate functions but is ignored for the computation of MIN
and MAX.
- * One special use of an aggregate symbol is for the symbol
<code>COUNT(*)</code>. The * expression
+ * <p>An aggregate symbol represents an aggregate function. The * expression
* is encoded by setting the expression to null. This may ONLY be used with the COUNT
function.</p>
*
* <p>The type of an aggregate symbol depends on the function and the type of the
underlying
@@ -69,12 +62,16 @@
STDDEV_POP,
STDDEV_SAMP,
VAR_POP,
- VAR_SAMP;
+ VAR_SAMP,
+ RANK,
+ DENSE_RANK,
+ ROW_NUMBER;
}
private Type aggregate;
private boolean distinct;
private OrderBy orderBy;
+ private Expression condition;
private static final Class<Integer> COUNT_TYPE =
DataTypeManager.DefaultDataClasses.INTEGER;
private static final Map<Class<?>, Class<?>> SUM_TYPES;
@@ -179,6 +176,8 @@
return DataTypeManager.DefaultDataClasses.DOUBLE;
} else if (this.aggregate == Type.ARRAY_AGG) {
return DataTypeManager.DefaultDataClasses.OBJECT;
+ } else if (this.aggregate == Type.RANK || this.aggregate == Type.ROW_NUMBER ||
this.aggregate == Type.DENSE_RANK){
+ return DataTypeManager.DefaultDataClasses.INTEGER;
} else {
return this.getExpression().getType();
}
@@ -222,6 +221,9 @@
if (orderBy != null) {
copy.setOrderBy(orderBy.clone());
}
+ if (condition != null) {
+ copy.setCondition((Expression) condition.clone());
+ }
return copy;
}
@@ -246,6 +248,7 @@
return this.aggregate.equals(other.aggregate)
&& this.distinct == other.distinct
&& EquivalenceUtil.areEqual(this.getExpression(),
other.getExpression())
+ && EquivalenceUtil.areEqual(this.condition, other.condition)
&& EquivalenceUtil.areEqual(this.getOrderBy(), other.getOrderBy());
}
@@ -261,10 +264,19 @@
case VAR_POP:
case VAR_SAMP:
case SUM:
+ case ARRAY_AGG:
return true;
}
return false;
}
+
+ public Expression getCondition() {
+ return condition;
+ }
+
+ public void setCondition(Expression condition) {
+ this.condition = condition;
+ }
public static boolean
areAggregatesCardinalityDependent(Collection<AggregateSymbol> aggs) {
for (AggregateSymbol aggregateSymbol : aggs) {
@@ -274,5 +286,21 @@
}
return false;
}
+
+ public boolean respectsNulls() {
+ return this.aggregate == Type.ARRAY_AGG;
+ }
+
+ public boolean canStage() {
+ switch (this.aggregate) {
+ case TEXTAGG:
+ return false;
+ case ARRAY_AGG:
+ return false;
+ case XMLAGG:
+ return orderBy == null;
+ }
+ return true;
+ }
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/AliasSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/AliasSymbol.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AliasSymbol.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -82,7 +82,7 @@
* Get the type of the symbol
* @return Type of the symbol
*/
- public Class getType() {
+ public Class<?> getType() {
return this.symbol.getType();
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ElementSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ElementSymbol.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ElementSymbol.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -46,7 +46,8 @@
private GroupSymbol groupSymbol;
private Object metadataID;
private Class<?> type;
- private boolean isExternalReference = false;
+ private boolean isExternalReference;
+ private boolean isAggregate;
private DisplayMode displayMode = DisplayMode.OUTPUT_NAME;
@@ -262,7 +263,16 @@
copy.setIsExternalReference(isExternalReference());
copy.outputName = this.outputName;
copy.setDisplayMode(this.getDisplayMode());
+ copy.isAggregate = isAggregate;
return copy;
}
+ public boolean isAggregate() {
+ return isAggregate;
+ }
+
+ public void setAggregate(boolean isAggregate) {
+ this.isAggregate = isAggregate;
+ }
+
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/symbol/ExpressionSymbol.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/ExpressionSymbol.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/ExpressionSymbol.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -34,7 +34,6 @@
*/
public class ExpressionSymbol extends SingleElementSymbol {
private Expression expression;
- private boolean derivedExpression;
/**
* Constructor used for cloning
@@ -101,19 +100,9 @@
clonedExpr = (Expression) getExpression().clone();
}
ExpressionSymbol copy = new ExpressionSymbol(getName(), getCanonical(),
clonedExpr);
- copy.setDerivedExpression(this.derivedExpression);
return copy;
}
- public boolean isDerivedExpression() {
- return this.derivedExpression;
- }
-
- public void setDerivedExpression(boolean derivedExpression) {
- this.derivedExpression = derivedExpression;
- }
-
-
/**
* @see org.teiid.query.sql.symbol.Symbol#hashCode()
*/
Added: trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+ package org.teiid.query.sql.symbol;
+
+import java.util.List;
+
+import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.core.util.HashCodeUtil;
+import org.teiid.query.sql.LanguageObject;
+import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.lang.OrderBy;
+
+public class WindowFunction implements Expression {
+
+ private AggregateSymbol function;
+ private List<Expression> partition;
+ private OrderBy orderBy;
+
+ public WindowFunction() {
+
+ }
+
+ public AggregateSymbol getFunction() {
+ return function;
+ }
+
+ public void setFunction(AggregateSymbol expression) {
+ this.function = expression;
+ }
+
+ public List<Expression> getPartition() {
+ return partition;
+ }
+
+ public void setPartition(List<Expression> grouping) {
+ this.partition = grouping;
+ }
+
+ public OrderBy getOrderBy() {
+ return orderBy;
+ }
+
+ public void setOrderBy(OrderBy orderBy) {
+ this.orderBy = orderBy;
+ }
+
+ @Override
+ public Class<?> getType() {
+ return function.getType();
+ }
+
+ @Override
+ public boolean isResolved() {
+ return function.isResolved();
+ }
+
+ @Override
+ public void acceptVisitor(LanguageVisitor visitor) {
+ visitor.visit(this);
+ }
+
+ @Override
+ public int hashCode() {
+ return HashCodeUtil.hashCode(function.hashCode(), partition, orderBy);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof WindowFunction)) {
+ return false;
+ }
+ WindowFunction other = (WindowFunction)obj;
+ return EquivalenceUtil.areEqual(this.function, other.function) &&
+ EquivalenceUtil.areEqual(this.partition, other.partition) &&
+ EquivalenceUtil.areEqual(this.orderBy, other.orderBy);
+ }
+
+ @Override
+ public WindowFunction clone() {
+ WindowFunction clone = new WindowFunction();
+ clone.setFunction((AggregateSymbol) this.function.clone());
+ if (this.partition != null) {
+ clone.setPartition(LanguageObject.Util.deepClone(this.partition, Expression.class));
+ }
+ if (this.orderBy != null) {
+ clone.setOrderBy(this.orderBy.clone());
+ }
+ return clone;
+ }
+
+}
Property changes on:
trunk/engine/src/main/java/org/teiid/query/sql/symbol/WindowFunction.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -32,7 +32,6 @@
import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.ElementSymbol;
-import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
@@ -50,25 +49,12 @@
postVisitVisitor(obj);
}
- /**
- * @see
org.teiid.query.sql.navigator.PreOrPostOrderNavigator#visit(org.teiid.query.sql.symbol.ExpressionSymbol)
- */
- @Override
- public void visit(ExpressionSymbol obj) {
- if (obj.isDerivedExpression()) {
- preVisitVisitor(obj);
- postVisitVisitor(obj);
- } else {
- super.visit(obj);
- }
- }
-
}
- private Collection<AggregateSymbol> aggregates;
- private Collection<SingleElementSymbol> groupingSymbols;
+ private Collection<? super AggregateSymbol> aggregates;
+ private Collection<? super SingleElementSymbol> groupingSymbols;
- public AggregateSymbolCollectorVisitor(Collection<AggregateSymbol> aggregates,
Collection<SingleElementSymbol> elements) {
+ public AggregateSymbolCollectorVisitor(Collection<? super AggregateSymbol>
aggregates, Collection<? super SingleElementSymbol> elements) {
this.aggregates = aggregates;
this.groupingSymbols = elements;
}
@@ -79,23 +65,16 @@
}
}
- public void visit(ExpressionSymbol obj) {
- if (this.groupingSymbols != null && obj.isDerivedExpression()) {
- this.groupingSymbols.add(obj);
- }
- }
-
public void visit(ElementSymbol obj) {
if (this.groupingSymbols != null) {
this.groupingSymbols.add(obj);
}
}
- public static final void getAggregates(LanguageObject obj,
Collection<SingleElementSymbol> aggregates, Collection<SingleElementSymbol>
elements) {
- AggregateSymbolCollectorVisitor visitor = new AggregateSymbolCollectorVisitor(new
ArrayList<AggregateSymbol>(), elements);
+ public static final void getAggregates(LanguageObject obj, Collection<? super
AggregateSymbol> aggregates, Collection<SingleElementSymbol> elements) {
+ AggregateSymbolCollectorVisitor visitor = new
AggregateSymbolCollectorVisitor(aggregates, elements);
AggregateStopNavigator asn = new AggregateStopNavigator(visitor);
obj.acceptVisitor(asn);
- aggregates.addAll(visitor.aggregates);
}
public static final Collection<AggregateSymbol> getAggregates(LanguageObject
obj, boolean removeDuplicates) {
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ElementCollectorVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ElementCollectorVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ElementCollectorVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -49,7 +49,8 @@
*/
public class ElementCollectorVisitor extends LanguageVisitor {
- private Collection<ElementSymbol> elements;
+ private Collection<? super ElementSymbol> elements;
+ private boolean aggsOnly;
/**
* Construct a new visitor with the specified collection, which should
@@ -57,7 +58,7 @@
* @param elements Collection to use for elements
* @throws IllegalArgumentException If elements is null
*/
- public ElementCollectorVisitor(Collection<ElementSymbol> elements) {
+ public ElementCollectorVisitor(Collection<? super ElementSymbol> elements) {
if(elements == null) {
throw new
IllegalArgumentException(QueryPlugin.Util.getString("ERR.015.010.0021"));
//$NON-NLS-1$
}
@@ -65,21 +66,14 @@
}
/**
- * Get the elements collected by the visitor. This should best be called
- * after the visitor has been run on the language object tree.
- * @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
- */
- public Collection<ElementSymbol> getElements() {
- return this.elements;
- }
-
- /**
* Visit a language object and collect symbols. This method should
<b>NOT</b> be
* called directly.
* @param obj Language object
*/
public void visit(ElementSymbol obj) {
- this.elements.add(obj);
+ if (!aggsOnly || obj.isAggregate()) {
+ this.elements.add(obj);
+ }
}
/**
@@ -109,7 +103,7 @@
* @param obj Language object
* @param elements Collection to collect elements in
*/
- public static final void getElements(LanguageObject obj,
Collection<ElementSymbol> elements) {
+ public static final void getElements(LanguageObject obj, Collection<? super
ElementSymbol> elements) {
if(obj == null) {
return;
}
@@ -150,6 +144,10 @@
* @return Collection of {@link org.teiid.query.sql.symbol.ElementSymbol}
*/
public static final Collection<ElementSymbol> getElements(LanguageObject obj,
boolean removeDuplicates, boolean useDeepIteration) {
+ return getElements(obj, removeDuplicates, useDeepIteration, false);
+ }
+
+ public static final Collection<ElementSymbol> getElements(LanguageObject obj,
boolean removeDuplicates, boolean useDeepIteration, boolean aggsOnly) {
if(obj == null) {
return Collections.emptyList();
}
@@ -159,16 +157,20 @@
} else {
elements = new ArrayList<ElementSymbol>();
}
- ElementCollectorVisitor visitor = null;
+ ElementCollectorVisitor visitor = new ElementCollectorVisitor(elements);
+ visitor.aggsOnly = aggsOnly;
if (useDeepIteration){
- visitor = new ElementCollectorVisitor(elements);
DeepPreOrderNavigator.doVisit(obj, visitor);
} else {
- visitor = new ElementCollectorVisitor(elements);
PreOrderNavigator.doVisit(obj, visitor);
}
return elements;
}
+
+ public static final Collection<ElementSymbol> getAggregates(LanguageObject obj,
boolean removeDuplicates) {
+ return getElements(obj, removeDuplicates, false, true);
+ }
+
}
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/ExpressionMappingVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -24,6 +24,7 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -52,6 +53,7 @@
import org.teiid.query.sql.lang.SubquerySetCriteria;
import org.teiid.query.sql.lang.XMLTable;
import org.teiid.query.sql.lang.XMLTable.XMLColumn;
+import org.teiid.query.sql.navigator.PreOrPostOrderNavigator;
import org.teiid.query.sql.navigator.PreOrderNavigator;
import org.teiid.query.sql.proc.AssignmentStatement;
import org.teiid.query.sql.symbol.AggregateSymbol;
@@ -78,6 +80,7 @@
private Map symbolMap;
private boolean clone = true;
+ private boolean elementSymbolsOnly;
/**
* Constructor for ExpressionMappingVisitor.
@@ -251,7 +254,7 @@
public void visit(SearchedCaseExpression obj) {
int whenCount = obj.getWhenCount();
- ArrayList thens = new ArrayList(whenCount);
+ ArrayList<Expression> thens = new ArrayList<Expression>(whenCount);
for (int i = 0; i < whenCount; i++) {
thens.add(replaceExpression(obj.getThenExpression(i)));
}
@@ -299,6 +302,9 @@
}
public Expression replaceExpression(Expression element) {
+ if (elementSymbolsOnly && !(element instanceof ElementSymbol)) {
+ return element;
+ }
Expression mapped = (Expression) this.symbolMap.get(element);
if(mapped != null) {
if (clone) {
@@ -310,17 +316,20 @@
}
public void visit(StoredProcedure obj) {
- for (Iterator paramIter = obj.getInputParameters().iterator(); paramIter.hasNext();)
{
- SPParameter param = (SPParameter) paramIter.next();
+ for (Iterator<SPParameter> paramIter = obj.getInputParameters().iterator();
paramIter.hasNext();) {
+ SPParameter param = paramIter.next();
Expression expr = param.getExpression();
param.setExpression(replaceExpression(expr));
}
}
public void visit(AggregateSymbol obj) {
- if (obj.getExpression() != null) { //account for count(*) - TODO: clean this up
+ if (obj.getExpression() != null) {
obj.setExpression(replaceExpression(obj.getExpression()));
}
+ if (obj.getCondition() != null) {
+ obj.setCondition(replaceExpression(obj.getCondition()));
+ }
}
/**
@@ -328,7 +337,11 @@
* @param obj Object to remap
*/
public void visit(GroupBy obj) {
- replaceSymbols(obj.getSymbols(), false);
+ List<Expression> symbols = obj.getSymbols();
+ for (int i = 0; i < symbols.size(); i++) {
+ Expression symbol = symbols.get(i);
+ symbols.set(i, replaceExpression(symbol));
+ }
}
@Override
@@ -371,21 +384,35 @@
* @param obj Language object
* @param exprMap Expression map, Expression to Expression
*/
- public static void mapExpressions(LanguageObject obj, Map exprMap) {
+ public static void mapExpressions(LanguageObject obj, Map<? extends Expression, ?
extends Expression> exprMap) {
if(obj == null || exprMap == null || exprMap.isEmpty()) {
return;
}
- final Set reverseSet = new HashSet(exprMap.values());
final ExpressionMappingVisitor visitor = new ExpressionMappingVisitor(exprMap);
- PreOrderNavigator pon = new PreOrderNavigator(visitor) {
- @Override
- protected void visitNode(LanguageObject obj) {
- if (!(obj instanceof Expression) || !reverseSet.contains(obj)) {
- super.visitNode(obj);
- }
+ visitor.elementSymbolsOnly = true;
+ for (Map.Entry<? extends Expression, ? extends Expression> entry :
exprMap.entrySet()) {
+ if (!(entry.getKey() instanceof ElementSymbol)) {
+ visitor.elementSymbolsOnly = false;
+ break;
}
- };
- obj.acceptVisitor(pon);
+ }
+ boolean useReverseMapping =
!Collections.disjoint(GroupsUsedByElementsVisitor.getGroups(exprMap.keySet()),
+ GroupsUsedByElementsVisitor.getGroups(exprMap.values()));
+
+ if (useReverseMapping) {
+ final Set<Expression> reverseSet = new
HashSet<Expression>(exprMap.values());
+ PreOrderNavigator pon = new PreOrderNavigator(visitor) {
+ @Override
+ protected void visitNode(LanguageObject obj) {
+ if (!(obj instanceof Expression) || !reverseSet.contains(obj)) {
+ super.visitNode(obj);
+ }
+ }
+ };
+ obj.acceptVisitor(pon);
+ } else {
+ PreOrPostOrderNavigator.doVisit(obj, visitor, PreOrPostOrderNavigator.PRE_ORDER,
false);
+ }
}
protected void setVariableValues(Map variableValues) {
Modified:
trunk/engine/src/main/java/org/teiid/query/sql/visitor/GroupsUsedByElementsVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/GroupsUsedByElementsVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/GroupsUsedByElementsVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -42,7 +42,9 @@
Collection<ElementSymbol> elements =
ElementCollectorVisitor.getElements(obj, true);
for (ElementSymbol elementSymbol : elements) {
- groups.add(elementSymbol.getGroupSymbol());
+ if (elementSymbol.getGroupSymbol() != null) {
+ groups.add(elementSymbol.getGroupSymbol());
+ }
}
}
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -126,6 +126,7 @@
import org.teiid.query.sql.symbol.SelectSymbol;
import org.teiid.query.sql.symbol.SingleElementSymbol;
import org.teiid.query.sql.symbol.TextLine;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.symbol.XMLAttributes;
import org.teiid.query.sql.symbol.XMLElement;
import org.teiid.query.sql.symbol.XMLForest;
@@ -133,6 +134,7 @@
import org.teiid.query.sql.symbol.XMLParse;
import org.teiid.query.sql.symbol.XMLQuery;
import org.teiid.query.sql.symbol.XMLSerialize;
+import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.symbol.XMLNamespaces.NamespaceItem;
import org.teiid.translator.SourceSystemFunctions;
@@ -1123,7 +1125,9 @@
}
if (obj.getExpression() == null) {
- append(Tokens.ALL_COLS);
+ if (obj.getAggregateFunction() == Type.COUNT) {
+ append(Tokens.ALL_COLS);
+ }
} else {
visitNode(obj.getExpression());
}
@@ -1133,6 +1137,16 @@
visitNode(obj.getOrderBy());
}
append(")"); //$NON-NLS-1$
+
+ if (obj.getCondition() != null) {
+ append(SPACE);
+ append(FILTER);
+ append(Tokens.LPAREN);
+ append(WHERE);
+ append(SPACE);
+ append(obj.getCondition());
+ append(Tokens.RPAREN);
+ }
}
public void visit( AliasSymbol obj ) {
@@ -2034,6 +2048,31 @@
addTabs(0);
append(alterView.getDefinition());
}
+
+ @Override
+ public void visit(WindowFunction windowFunction) {
+ append(windowFunction.getFunction());
+ append(SPACE);
+ append(OVER);
+ append(SPACE);
+ append(Tokens.LPAREN);
+ boolean needsSpace = false;
+ if (windowFunction.getPartition() != null) {
+ append(PARTITION);
+ append(SPACE);
+ append(BY);
+ append(SPACE);
+ registerNodes(windowFunction.getPartition(), 0);
+ needsSpace = true;
+ }
+ if (windowFunction.getOrderBy() != null) {
+ if (needsSpace) {
+ append(SPACE);
+ }
+ append(windowFunction.getOrderBy());
+ }
+ append(Tokens.RPAREN);
+ }
public static String escapeSinglePart( String part ) {
if (isReservedWord(part)) {
Modified: trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/util/CommandContext.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -434,13 +434,12 @@
}
public Set<String> getGroups() {
+ if (globalState.groups == null) {
+ globalState.groups = new HashSet<String>();
+ }
return globalState.groups;
}
- public void setGroups(Set<String> groups) {
- this.globalState.groups = groups;
- }
-
public long getTimeSliceEnd() {
return globalState.timeSliceEnd;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -59,13 +59,9 @@
public void visit(AggregateSymbol obj) {
Expression aggExp = obj.getExpression();
- // Check for any nested aggregates (which are not allowed)
- if(aggExp != null) {
- Collection<AggregateSymbol> nestedAggs =
AggregateSymbolCollectorVisitor.getAggregates(aggExp, true);
- if(nestedAggs.size() > 0) {
-
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0039",
nestedAggs), nestedAggs); //$NON-NLS-1$
- }
- }
+ validateNoNestedAggs(aggExp);
+ validateNoNestedAggs(obj.getOrderBy());
+ validateNoNestedAggs(obj.getCondition());
// Verify data type of aggregate expression
Type aggregateFunction = obj.getAggregateFunction();
@@ -91,6 +87,16 @@
}
validateBelow = false;
}
+
+ private void validateNoNestedAggs(LanguageObject aggExp) {
+ // Check for any nested aggregates (which are not allowed)
+ if(aggExp != null) {
+ Collection<AggregateSymbol> nestedAggs =
AggregateSymbolCollectorVisitor.getAggregates(aggExp, true);
+ if(nestedAggs.size() > 0) {
+
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0039",
nestedAggs), nestedAggs); //$NON-NLS-1$
+ }
+ }
+ }
public void visit(ElementSymbol obj) {
validateExpression(obj);
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -114,7 +114,6 @@
import org.teiid.query.sql.symbol.DerivedColumn;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
-import org.teiid.query.sql.symbol.ExpressionSymbol;
import org.teiid.query.sql.symbol.Function;
import org.teiid.query.sql.symbol.GroupSymbol;
import org.teiid.query.sql.symbol.QueryString;
@@ -129,7 +128,6 @@
import org.teiid.query.sql.symbol.XMLParse;
import org.teiid.query.sql.symbol.XMLQuery;
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.ElementCollectorVisitor;
import org.teiid.query.sql.visitor.EvaluatableVisitor;
@@ -208,18 +206,12 @@
public void visit(GroupBy obj) {
// Get list of all group by IDs
- List groupBySymbols = obj.getSymbols();
+ List<Expression> groupBySymbols = obj.getSymbols();
validateSortable(groupBySymbols);
- Iterator symbolIter = groupBySymbols.iterator();
- while(symbolIter.hasNext()) {
- SingleElementSymbol symbol = (SingleElementSymbol)symbolIter.next();
- if(symbol instanceof ExpressionSymbol) {
- ExpressionSymbol exprSymbol = (ExpressionSymbol) symbol;
- Expression expr = exprSymbol.getExpression();
- if
(!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr).isEmpty() || expr
instanceof Constant || expr instanceof Reference) {
-
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.groupby_subquery",
expr), expr); //$NON-NLS-1$
- }
- }
+ for (Expression expr : groupBySymbols) {
+ if
(!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(expr).isEmpty() || expr
instanceof Constant || expr instanceof Reference) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.groupby_subquery",
expr), expr); //$NON-NLS-1$
+ }
}
}
@@ -666,15 +658,13 @@
* and ORDER BY.
* @param symbols List of SingleElementSymbol
*/
- protected void validateSortable(List symbols) {
- Iterator iter = symbols.iterator();
- while(iter.hasNext()) {
- SingleElementSymbol symbol = (SingleElementSymbol) iter.next();
- validateSortable(symbol);
+ protected void validateSortable(List<? extends Expression> symbols) {
+ for (Expression expression : symbols) {
+ validateSortable(expression);
}
}
- private void validateSortable(SingleElementSymbol symbol) {
+ private void validateSortable(Expression symbol) {
if (isNonComparable(symbol)) {
handleValidationError(QueryPlugin.Util.getString("ERR.015.012.0026",
symbol), symbol); //$NON-NLS-1$
}
@@ -759,13 +749,16 @@
Select select = query.getSelect();
GroupBy groupBy = query.getGroupBy();
Criteria having = query.getHaving();
+ validateNoAggsInClause(groupBy);
+ validateNoAggsInClause(query.getCriteria());
+ validateNoAggsInClause(query.getFrom());
if(groupBy != null || having != null ||
!AggregateSymbolCollectorVisitor.getAggregates(select, false).isEmpty()) {
Set<Expression> groupSymbols = null;
if(groupBy != null) {
groupSymbols = new HashSet<Expression>();
- for (final Iterator iterator = groupBy.getSymbols().iterator();
iterator.hasNext();) {
- final SingleElementSymbol element =
(SingleElementSymbol)iterator.next();
- groupSymbols.add(SymbolMap.getExpression(element));
+ for (final Iterator<Expression> iterator =
groupBy.getSymbols().iterator(); iterator.hasNext();) {
+ final Expression element = iterator.next();
+ groupSymbols.add(element);
}
}
@@ -783,10 +776,20 @@
// Move items to this report
ValidatorReport report = visitor.getReport();
- Collection items = report.getItems();
+ Collection<ValidatorFailure> items = report.getItems();
super.getReport().addItems(items);
}
}
+
+ private void validateNoAggsInClause(LanguageObject clause) {
+ if (clause == null) {
+ return;
+ }
+ Collection<AggregateSymbol> aggs =
AggregateSymbolCollectorVisitor.getAggregates(clause, false);
+ if (!aggs.isEmpty()) {
+ handleValidationError(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level",
aggs), aggs);
+ }
+ }
protected void validateInsert(Insert obj) {
Collection<ElementSymbol> vars = obj.getVariables();
@@ -1202,6 +1205,17 @@
@Override
public void visit(AggregateSymbol obj) {
+ if (obj.getCondition() != null) {
+ Expression condition = obj.getCondition();
+ if
(!ValueIteratorProviderCollectorVisitor.getValueIteratorProviders(condition).isEmpty()) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.filter_subquery",
condition), condition); //$NON-NLS-1$
+ }
+ for (ElementSymbol es : ElementCollectorVisitor.getElements(condition, false)) {
+ if (es.isExternalReference()) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.filter_subquery",
es), es); //$NON-NLS-1$
+ }
+ }
+ }
if (obj.getAggregateFunction() != Type.TEXTAGG) {
return;
}
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2011-07-20 03:27:02
UTC (rev 3317)
@@ -897,7 +897,7 @@
CriteriaSelector critSelector = new CriteriaSelector();
String element = null;
- List elements = new ArrayList();
+ List elements = new ArrayList(2);
Token operator = null;
}
{
@@ -1110,7 +1110,7 @@
[<WITH>
{
- critList = new ArrayList();
+ critList = new ArrayList(2);
}
<LPAREN>
element = id()
@@ -1481,8 +1481,9 @@
}]
(
- ( <VALUES>
- values = rowValues(info)
+ ( <VALUES> <LPAREN>
+ values = expressionList(info)
+ <RPAREN>
{
// Store each row of values
insert.setValues(values);
@@ -1544,13 +1545,12 @@
* @return List of values, never null
* @throws ParseException if parsing failed
*/
-List rowValues(ParseInfo info) :
+ArrayList<Expression> expressionList(ParseInfo info) :
{
- List rowVals = new ArrayList();
+ ArrayList<Expression> rowVals = new ArrayList<Expression>(4);
Expression value = null;
}
{
- <LPAREN>
value = expression(info)
{
rowVals.add(value);
@@ -1561,8 +1561,6 @@
rowVals.add(value);
}
)*
- <RPAREN>
-
{
return rowVals;
}
@@ -1822,7 +1820,6 @@
boolean isDistinct = false; // unless DISTINCT keyword in SELECT
SelectSymbol symbol = null;
Select select = new Select();
- info.aggregatesAllowed = true;
}
{
<SELECT>
@@ -1839,7 +1836,6 @@
)
)
{
- info.aggregatesAllowed = false;
select.setDistinct(isDistinct);
return select;
}
@@ -1924,55 +1920,30 @@
}
}
-AggregateSymbol xmlAgg(ParseInfo info) :
+AggregateSymbol orderedAgg(ParseInfo info) :
{
+ Token t = null;
Expression expression = null;
OrderBy orderBy = null;
+ Expression condition = null;
}
{
- <XMLAGG> <LPAREN>
+ (t=<XMLAGG>|t=<ARRAY_AGG>)
+ <LPAREN>
expression = expression(info)
- [
- orderBy = orderby(info)
- ]
+ [ orderBy = orderby(info) ]
<RPAREN>
+ condition = filterClause(info)
{
- if(! info.aggregatesAllowed) {
- throw new
ParseException(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level"));
//$NON-NLS-1$
- }
-
- String name = generateFunctionName(info, "XMLAGG");
- AggregateSymbol agg = new AggregateSymbol(name, "XMLAGG", false,
expression);
+ String aggName = t.image.toUpperCase();
+ String name = generateFunctionName(info, aggName);
+ AggregateSymbol agg = new AggregateSymbol(name, aggName, false, expression);
agg.setOrderBy(orderBy);
+ agg.setCondition(condition);
return agg;
}
}
-AggregateSymbol arrayAgg(ParseInfo info) :
-{
- Expression expression = null;
- OrderBy orderBy = null;
-}
-{
- <ARRAY_AGG> <LPAREN>
- expression = expression(info)
- [
- orderBy = orderby(info)
- ]
- <RPAREN>
- {
- if(! info.aggregatesAllowed) {
- throw new
ParseException(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level"));
//$NON-NLS-1$
- }
-
- String name = generateFunctionName(info, "ARRAY_AGG");
- AggregateSymbol agg = new AggregateSymbol(name, "ARRAY_AGG", false,
expression);
- agg.setOrderBy(orderBy);
- return agg;
- }
-}
-
-
AggregateSymbol textAgg(ParseInfo info) :
{
DerivedColumn expression = null;
@@ -1982,6 +1953,7 @@
List<DerivedColumn> expressions = new ArrayList<DerivedColumn>();
OrderBy orderBy = null;
String encoding = null;
+ Expression condition = null;
}
{
nonReserved("TEXTAGG") <LPAREN>
@@ -2015,20 +1987,18 @@
orderBy = orderby(info)
]
<RPAREN>
+ condition = filterClause(info)
{
- if(! info.aggregatesAllowed) {
- throw new
ParseException(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level"));
//$NON-NLS-1$
- }
-
TextLine tf = new TextLine();
tf.setDelimiter(delimiter);
tf.setQuote(quote);
tf.setIncludeHeader(header);
tf.setExpressions(expressions);
tf.setEncoding(encoding);
- String name = generateFunctionName(info, "TEXTAGG");
+ String name = generateFunctionName(info, "TEXTAGG");
AggregateSymbol agg = new AggregateSymbol(name, "TEXTAGG", false, tf);
agg.setOrderBy(orderBy);
+ agg.setCondition(condition);
return agg;
}
}
@@ -2040,16 +2010,18 @@
AggregateSymbol agg = null;
boolean isDistinct = false;
Expression expression = null;
+ Expression condition = null;
}
{
(
// COUNT(*)
- LOOKAHEAD(3) (
+ (LOOKAHEAD(3) (
func = nonReserved("COUNT")
<LPAREN>
starToken = <STAR>
<RPAREN> ) |
-
+ LOOKAHEAD(<ID>, {matchesAny(getToken(1).image, "rank",
"dense_rank", "row_number") != null}) (func =
nonReserved("row_number", "rank", "dense_rank",
"percent_rank", "cume_dist")
+ <LPAREN> <RPAREN>) |
// Remaining aggregates
( (func = nonReserved("COUNT", "SUM", "AVG",
"MIN", "MAX", "EVERY", "STDDEV_POP",
"STDDEV_SAMP", "VAR_SAMP", "VAR_POP")
|
@@ -2061,12 +2033,10 @@
[ <DISTINCT> {isDistinct=true;} | <ALL>]
expression = expression(info)
<RPAREN>
- )
+ ))
+ condition = filterClause(info)
)
{
- if(! info.aggregatesAllowed) {
- throw new
ParseException(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level"));
//$NON-NLS-1$
- }
func = func.toUpperCase();
String name = generateFunctionName(info, func);
if(starToken == null) {
@@ -2076,10 +2046,22 @@
// COUNT(*)
agg = new AggregateSymbol(name, func, false, null);
}
+ agg.setCondition(condition);
return agg;
}
}
+Expression filterClause(ParseInfo info) :
+{
+ Expression condition = null;
+}
+{
+ [ <FILTER> <LPAREN> <WHERE> condition = booleanPrimary(info)
<RPAREN> ]
+ {
+ return condition;
+ }
+}
+
/**
* <p>Parse a FROM. The from must handle groups, aliased groups or
* joined groups. This also handles JDBC escape processinf syntax for outer
joins.</p>
@@ -2631,7 +2613,7 @@
*/
Criteria compoundCritOr(ParseInfo info) :
{
- ArrayList logicList = new ArrayList();
+ ArrayList logicList = new ArrayList(2);
Criteria logicPart = null;
}
{
@@ -2654,7 +2636,7 @@
*/
Criteria compoundCritAnd(ParseInfo info) :
{
- ArrayList logicList = new ArrayList();
+ ArrayList logicList = new ArrayList(2);
Criteria logicPart = null;
}
{
@@ -2677,14 +2659,20 @@
*/
Criteria notCrit(ParseInfo info) :
{
- Criteria crit = null;
+ Expression ex = null;
boolean isNot = false;
}
{
[<NOT> {isNot=true;}]
- crit=booleanPrimary(info)
+ ex=booleanPrimary(info)
{
+ Criteria crit = null;
+ if (ex instanceof Criteria) {
+ crit = (Criteria)ex;
+ } else {
+ crit = new ExpressionCriteria(ex);
+ }
if(isNot) {
return new NotCriteria(crit);
} else {
@@ -2698,38 +2686,30 @@
* @return criteria
* @throws ParseException if parsing failed
*/
-Criteria booleanPrimary(ParseInfo info) :
+Expression booleanPrimary(ParseInfo info) :
{
Expression ex = null;
- Criteria crit = null;
}
{
(
- LOOKAHEAD(2) crit = translateCriteria(info)
+ LOOKAHEAD(2) ex = translateCriteria(info)
|
(ex = commonValueExpression(info)
- {
- if (ex instanceof Criteria) {
- crit = (Criteria)ex;
- } else {
- crit = new ExpressionCriteria(ex);
- }
- }
[(
- LOOKAHEAD(2) crit=betweenCrit(info, ex) |
- LOOKAHEAD(2) crit=matchCrit(info, ex) |
- crit=setCrit(info, ex) |
- crit=isNullCrit(info, ex) |
- LOOKAHEAD(operator() (<ANY>|<SOME>|<ALL>) subquery(info))
crit=subqueryCompareCriteria(info, ex) |
- crit=compareCrit(info, ex)
+ LOOKAHEAD(2) ex=betweenCrit(info, ex) |
+ LOOKAHEAD(2) ex=matchCrit(info, ex) |
+ ex=setCrit(info, ex) |
+ ex=isNullCrit(info, ex) |
+ LOOKAHEAD(operator() (<ANY>|<SOME>|<ALL>) subquery(info))
ex=subqueryCompareCriteria(info, ex) |
+ ex=compareCrit(info, ex)
)]
)
|
- crit=existsCriteria(info) |
- crit = hasCriteria()
+ ex=existsCriteria(info) |
+ ex = hasCriteria()
)
{
- return crit;
+ return ex;
}
}
@@ -3018,53 +2998,17 @@
*/
GroupBy groupBy(ParseInfo info) :
{
- GroupBy groupBy = new GroupBy();
- SingleElementSymbol symbol = null;
+ List<Expression> expressions = null;
}
{
<GROUP> <BY>
- ( symbol = groupByItem(info)
- {
- groupBy.addSymbol(symbol);
- }
-
- (<COMMA> symbol = groupByItem(info)
- {
- groupBy.addSymbol(symbol);
- }
- )*
- )
+ expressions = expressionList(info)
{
- return groupBy;
+ return new GroupBy(expressions);
}
}
/**
- * <p>Parse a GROUP BY list item. </p>
- * @return Parsed group by item
- * @throws ParseException if parsing failed
- */
-SingleElementSymbol groupByItem(ParseInfo info) :
-{
- Expression expr = null;
- SingleElementSymbol symbol = null;
-}
-{
- expr = expression(info)
- {
- if(expr instanceof ElementSymbol) {
- symbol = (ElementSymbol) expr;
- } else {
- String exprName = generateFunctionName(info, null);
- symbol = new ExpressionSymbol(exprName, expr);
- }
- }
- {
- return symbol;
- }
-}
-
-/**
* <p>Parse a HAVING clause. </p>
* @return Parsed having
* @throws ParseException if parsing failed
@@ -3072,14 +3016,11 @@
Criteria having(ParseInfo info) :
{
Criteria criteria = null;
- info.aggregatesAllowed = true;
}
{
<HAVING>
criteria = criteria(info)
-
{
- info.aggregatesAllowed = false;
return criteria;
}
}
@@ -3438,19 +3379,20 @@
<RBRACE>
)
|
- LOOKAHEAD(<ID> <LPAREN> <FOR>) (expression=textAgg(info))
+ LOOKAHEAD(<ID> <LPAREN>, {matchesAny(getToken(1).image,
"textagg") != null})
+ (expression=textAgg(info) [expression = windowSpecification(expression, info)])
|
// Aggregate function
- LOOKAHEAD(<ID>, {matchesAny(getToken(1).image, "count",
"min", "max", "sum", "avg", "every",
"STDDEV_POP", "STDDEV_SAMP", "VAR_SAMP",
"VAR_POP") != null}) (expression=aggregateSymbol(info))
+ LOOKAHEAD(<ID> <LPAREN>, {matchesAny(getToken(1).image, "count",
"min", "max", "sum", "avg", "every",
"STDDEV_POP", "STDDEV_SAMP", "VAR_SAMP",
"VAR_POP") != null})
+ (expression=aggregateSymbol(info) [expression = windowSpecification(expression,
info)])
|
- LOOKAHEAD(<ANY>) (expression=aggregateSymbol(info))
+ LOOKAHEAD(<ANY>|<SOME>) (expression=aggregateSymbol(info) [expression =
windowSpecification(expression, info)])
|
- LOOKAHEAD(<SOME>) (expression=aggregateSymbol(info))
+ expression=orderedAgg(info) [expression = windowSpecification(expression, info)]
|
- (expression=xmlAgg(info))
+ LOOKAHEAD(<ID> <LPAREN>, {matchesAny(getToken(1).image, "rank",
"dense_rank", "row_number") != null})
+ (expression=aggregateSymbol(info) expression = windowSpecification(expression, info))
|
- (expression=arrayAgg(info))
- |
// Function
LOOKAHEAD(2) (expression=function(info))
|
@@ -3501,6 +3443,26 @@
}
}
+Expression windowSpecification(Expression agg, ParseInfo info) :
+{
+ List<Expression> partitionList = null;
+ OrderBy orderBy = null;
+}
+{
+ <OVER>
+ <LPAREN>
+ [<PARTITION> <BY> partitionList = expressionList(info)]
+ [orderBy = orderby(info)]
+ <RPAREN>
+ {
+ WindowFunction result = new WindowFunction();
+ result.setFunction((AggregateSymbol)agg);
+ result.setPartition(partitionList);
+ result.setOrderBy(orderBy);
+ return result;
+ }
+}
+
/**
* Parse a non-searched CASE expression.
* @return CaseExpression
@@ -3509,8 +3471,8 @@
CaseExpression caseExpression(ParseInfo info) :
{
Expression expression = null, whenExpression = null, thenExpression = null,
elseExpression = null;
- ArrayList whenExpressions = new ArrayList();
- ArrayList thenExpressions = new ArrayList();
+ ArrayList whenExpressions = new ArrayList(2);
+ ArrayList thenExpressions = new ArrayList(2);
}
{
<CASE>
@@ -3543,8 +3505,8 @@
{
Expression thenExpression = null, elseExpression = null;
Criteria whenCriteria = null;
- ArrayList whenCriteriaList = new ArrayList();
- ArrayList thenExpressions = new ArrayList();
+ ArrayList whenCriteriaList = new ArrayList(2);
+ ArrayList thenExpressions = new ArrayList(2);
}
{
<CASE>
@@ -3578,7 +3540,7 @@
String funcName = null;
Expression expression = null;
- ArrayList args = new ArrayList();
+ ArrayList args = new ArrayList(2);
Token funcToken = null;
}
{
@@ -3665,62 +3627,16 @@
| funcToken = <YEAR> | funcToken = <MONTH> | funcToken
= <HOUR>
| funcToken = <MINUTE> | funcToken = <SECOND> |
funcToken = <XMLCONCAT>
| funcToken = <XMLCOMMENT>)
- <LPAREN>
- [
- expression = expression(info)
- {
- args.add(expression);
- expression = null;
- }
-
- (<COMMA> expression=expression(info)
- {
- args.add(expression);
- expression = null;
- }
- )*
- ]
+ <LPAREN>
+ [args = expressionList(info)]
<RPAREN>
)
|
- LOOKAHEAD(<INSERT> <LPAREN>) (
- (funcToken = <INSERT>)
+ LOOKAHEAD(<TRANSLATE>|<INSERT> <LPAREN>) (
+ (funcToken = <TRANSLATE> | funcToken = <INSERT>)
<LPAREN>
- [
- expression = expression(info)
- {
- args.add(expression);
- expression = null;
- }
-
- (<COMMA> expression=expression(info)
- {
- args.add(expression);
- expression = null;
- }
- )*
- ]
+ [args = expressionList(info)]
<RPAREN>
- )
- |
- LOOKAHEAD(<TRANSLATE> <LPAREN>) (
- (funcToken = <TRANSLATE>)
- <LPAREN>
- [
- expression = expression(info)
- {
- args.add(expression);
- expression = null;
- }
-
- (<COMMA> expression=expression(info)
- {
- args.add(expression);
- expression = null;
- }
- )*
- ]
- <RPAREN>
)
| expression = xmlParse(info)
{
@@ -3765,20 +3681,7 @@
|
( funcName = id()
<LPAREN>
- [
- expression = expression(info)
- {
- args.add(expression);
- expression = null;
- }
-
- (<COMMA> expression=expression(info)
- {
- args.add(expression);
- expression = null;
- }
- )*
- ]
+ [ args = expressionList(info) ]
<RPAREN>
))
{
@@ -3830,7 +3733,7 @@
{
Expression path = null;
DerivedColumn arg = null;
- ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>();
+ ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>(2);
}
{
nonReserved("QUERYSTRING") <LPAREN>
@@ -3850,7 +3753,7 @@
XMLElement xmlElement(ParseInfo info) :
{
String name = null;
- ArrayList content = new ArrayList();
+ ArrayList content = new ArrayList(2);
XMLNamespaces xmlNamespaces = null;
XMLAttributes xmlAttributes = null;
Expression expression = null;
@@ -3886,7 +3789,7 @@
XMLAttributes xmlAttributes(ParseInfo info) :
{
DerivedColumn expression = null;
- ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>();
+ ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>(2);
}
{
<XMLATTRIBUTES> <LPAREN>
@@ -3911,7 +3814,7 @@
{
DerivedColumn expression = null;
XMLNamespaces xmlNamespaces = null;
- ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>();
+ ArrayList<DerivedColumn> args = new ArrayList<DerivedColumn>(2);
}
{
<XMLFOREST> <LPAREN>
@@ -3939,7 +3842,7 @@
XMLNamespaces xmlNamespaces(ParseInfo info) :
{
- ArrayList namespaces = new ArrayList();
+ ArrayList namespaces = new ArrayList(2);
XMLNamespaces.NamespaceItem item = null;
}
{
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2011-07-20 03:27:02
UTC (rev 3317)
@@ -259,7 +259,7 @@
SQLParser.Unknown_join_type=Unknown join type: {0}
-SQLParser.Aggregate_only_top_level=Aggregate expressions are allowed only as top level
functions in the SELECT and HAVING clauses.
+SQLParser.Aggregate_only_top_level=Aggregate functions are not allowed in the
FROM/WHERE/GROUP BY clauses: {0}
SQLParser.Unknown_agg_func=Unknown aggregate function: {0}
SQLParser.Invalid_func=Invalid function name: [{0}]
SQLParser.Integer_parse=Unable to parse integer literal: {0}
@@ -677,7 +677,8 @@
SimpleQueryResolver.procedure_cache_used=Procedure caching will be used for {0}.
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.groupby_subquery=Expressions used in a GROUP BY clause cannot be
constant and must not contain subqueries: "{0}".
+ValidationVisitor.filter_subquery=Expressions used in a FILTER clause must not contain
subqueries nor outer references: "{0}".
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
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-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/process/multisource/TestMultiSourcePlanToProcessConverter.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -35,7 +35,6 @@
import org.teiid.adminapi.impl.VDBMetaData;
import org.teiid.common.buffer.TupleSource;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerIDFactory;
import org.teiid.dqp.internal.process.DQPWorkContext;
import org.teiid.query.analysis.AnalysisRecord;
import org.teiid.query.metadata.QueryMetadataInterface;
@@ -113,7 +112,6 @@
CapabilitiesFinder finder = new MultiSourceCapabilitiesFinder(fakeFinder,
multiSourceModels);
IDGenerator idGenerator = new IDGenerator();
- idGenerator.setDefaultFactory(new IntegerIDFactory());
Properties props = new Properties();
CommandContext context = new CommandContext("0", "test",
"user", null, vdb.getName(), vdb.getVersion(), props, false); //$NON-NLS-1$
//$NON-NLS-2$ //$NON-NLS-3$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestAggregatePushdown.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -69,7 +69,7 @@
String sql = "SELECT a12.intkey AS REGION_NBR, SUM(a11.intnum) AS WJXBFS1
FROM bqt1.smalla AS a11 INNER JOIN bqt2.smalla AS a12 ON a11.stringkey = a12.stringkey
WHERE a11.stringkey = 0 GROUP BY a12.intkey"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.exampleBQTCached(), null, capFinder,
- new String[] {"SELECT SUM(a11.intnum) FROM
bqt1.smalla AS a11 WHERE a11.stringkey = '0' HAVING COUNT(*) > 0",
"SELECT a12.intkey FROM bqt2.smalla AS a12 WHERE a12.stringkey = '0' group by
a12.intkey"}, TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT SUM(a11.intnum) FROM
bqt1.smalla AS a11 WHERE a11.stringkey = '0' HAVING COUNT(*) > 0",
"SELECT a12.intkey FROM bqt2.smalla AS a12 WHERE a12.stringkey = '0'"},
TestOptimizer.SHOULD_SUCCEED); //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -203,7 +203,7 @@
String sql = "select sum(a11.intnum) Profit, (sum(a11.intnum) /
sum(a11.floatnum)) WJXBFS2 from bqt1.smalla a11 join bqt2.smallb a12 on
a11.intkey=a12.intkey group by a12.intkey"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.exampleBQTCached(), null, capFinder,
- new String[] {"SELECT g_0.intkey,
SUM(g_0.intnum), SUM(g_0.floatnum) FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey",
"SELECT g_0.intkey FROM bqt2.smallb AS g_0 GROUP BY g_0.intkey"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.intkey,
SUM(g_0.intnum), SUM(g_0.floatnum) FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey",
"SELECT g_0.intkey FROM bqt2.smallb AS g_0"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -298,7 +298,7 @@
String sql = "SELECT avg(y.e2) from pm1.g1 x, pm2.g1 y where x.e3 = y.e3
group by x.e2, y.e1"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), null, capFinder,
- new String[] {"SELECT g_0.e3, g_0.e2 FROM
pm1.g1 AS g_0 GROUP BY g_0.e3, g_0.e2", "SELECT g_0.e3, g_0.e1, SUM(g_0.e2),
COUNT(g_0.e2) FROM pm2.g1 AS g_0 GROUP BY g_0.e3, g_0.e1"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.e3, g_0.e2 FROM
pm1.g1 AS g_0", "SELECT g_0.e3, g_0.e1, SUM(g_0.e2), COUNT(g_0.e2) FROM pm2.g1
AS g_0 GROUP BY g_0.e3, g_0.e1"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);
//$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -317,7 +317,71 @@
0 // UnionAll
});
}
+
+ @Test public void testAvgAggregateFiltered() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.QUERY_ORDERBY, false);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+ capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+
+ String sql = "SELECT avg(y.e2) filter (where y.e1 = 1) from pm1.g1 x, pm2.g1
y where x.e3 = y.e3 group by x.e2, y.e1"; //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), null, capFinder,
+ new String[] {"SELECT g_0.e3, g_0.e2 FROM
pm1.g1 AS g_0",
+ "SELECT g_0.e3, g_0.e1, g_0.e2 FROM pm2.g1 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
+ 2, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 1, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 0 // UnionAll
+ });
+ }
+ /**
+ * Agg can only be computed after the join
+ */
+ @Test public void testAvgAggregateFiltered1() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.ADVANCED_OLAP, true);
+ caps.setCapabilitySupport(Capability.QUERY_ORDERBY, false);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+ capFinder.addCapabilities("pm2", caps); //$NON-NLS-1$
+
+ String sql = "SELECT avg(y.e2) filter (where x.e1 = 1) from pm1.g1 x, pm2.g1
y where x.e3 = y.e3 group by x.e2, y.e1"; //$NON-NLS-1$
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), null, capFinder,
+ new String[] {"SELECT g_0.e3, g_0.e2, g_0.e1 FROM pm1.g1 AS g_0",
+ "SELECT g_0.e3, g_0.e1, g_0.e2 FROM pm2.g1 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
+ });
+ }
+
@Test public void testStddevAggregate() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = getAggregateCapabilities();
@@ -328,7 +392,7 @@
String sql = "SELECT stddev_pop(y.e2) from pm1.g1 x, pm2.g1 y where x.e3 =
y.e3 group by x.e2, y.e1"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), null, capFinder,
- new String[] {"SELECT g_0.e3 AS c_0, g_0.e1 AS
c_1, COUNT(g_0.e2) AS c_2, SUM(power(g_0.e2, 2)) AS c_3, SUM(g_0.e2) AS c_4 FROM pm2.g1 AS
g_0 GROUP BY g_0.e3, g_0.e1 ORDER BY c_0", "SELECT g_0.e3 AS c_0, g_0.e2 AS c_1
FROM pm1.g1 AS g_0 GROUP BY g_0.e3, g_0.e2 ORDER BY c_0"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.e3 AS c_0, g_0.e1 AS
c_1, COUNT(g_0.e2) AS c_2, SUM(power(g_0.e2, 2)) AS c_3, SUM(g_0.e2) AS c_4 FROM pm2.g1 AS
g_0 GROUP BY g_0.e3, g_0.e1 ORDER BY c_0", "SELECT g_0.e3 AS c_0, g_0.e2 AS c_1
FROM pm1.g1 AS g_0 ORDER BY c_0"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -357,7 +421,7 @@
String sql = "SELECT count(y.e2) from pm1.g1 x, pm2.g1 y where x.e3 = y.e3
group by x.e2, y.e1"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), null, capFinder,
- new String[] {"SELECT g_0.e3, g_0.e2 FROM
pm1.g1 AS g_0 GROUP BY g_0.e3, g_0.e2", "SELECT g_0.e3, g_0.e1, COUNT(g_0.e2)
FROM pm2.g1 AS g_0 GROUP BY g_0.e3, g_0.e1"},
TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$ //$NON-NLS-2$
+ new String[] {"SELECT g_0.e3, g_0.e2 FROM
pm1.g1 AS g_0", "SELECT g_0.e3, g_0.e1, COUNT(g_0.e2) FROM pm2.g1 AS g_0 GROUP
BY g_0.e3, g_0.e1"}, TestOptimizer.ComparisonMode.EXACT_COMMAND_STRING);
//$NON-NLS-1$ //$NON-NLS-2$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -767,8 +831,8 @@
ProcessorPlan plan = helpPlan(sql,
metadata,
null, capFinder,
- new String[] {"SELECT c2, c1, c0 FROM
db2model.DB2TABLE", //$NON-NLS-1$
- "SELECT DISTINCT b2, sum(b0)
FROM oraclemodel.OraTable GROUP BY b2 ORDER BY b2"}, //$NON-NLS-1$
+ new String[] {"SELECT g_0.c2, g_0.c1, g_0.c0
FROM db2model.DB2TABLE AS g_0", //$NON-NLS-1$
+ "SELECT g_0.b2 AS c_0, g_0.b0 AS
c_1 FROM oraclemodel.OraTable AS g_0 ORDER BY c_0"}, //$NON-NLS-1$
SHOULD_SUCCEED );
checkNodeTypes(plan, new int[] {
@@ -777,12 +841,12 @@
0, // DependentSelect
0, // DependentProject
0, // DupRemove
- 1, // Grouping
+ 2, // Grouping
0, // NestedLoopJoinStrategy
1, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -815,6 +879,90 @@
});
}
+ /**
+ * olap not supported
+ */
+ @Test public void testPushDownOverUnionFiltered() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ ProcessorPlan plan = TestOptimizer.helpPlan("select e1, count(*) filter
(where e3) from (select e1, e2, e3 from pm1.g1 union all select e1, e2, e3 from pm1.g2) y
group by e1", RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
+ new String[]{"SELECT g_0.e1, g_0.e3 FROM pm1.g1 AS g_0",
"SELECT g_0.e1, g_0.e3 FROM pm1.g2 AS g_0"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+
+ @Test public void testPushDownOverUnionFiltered1() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.ADVANCED_OLAP, true);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ ProcessorPlan plan = TestOptimizer.helpPlan("select e1, count(*) filter
(where e3) from (select e1, e2, e3 from pm1.g1 union all select e1, e2, e3 from pm1.g2) y
group by e1", RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
+ new String[]{"SELECT v_0.c_0, COUNT(*) FILTER(WHERE v_0.c_1) FROM
(SELECT g_0.e1 AS c_0, g_0.e3 AS c_1 FROM pm1.g1 AS g_0) AS v_0 GROUP BY v_0.c_0",
+ "SELECT v_0.c_0, COUNT(*) FILTER(WHERE v_0.c_1) FROM (SELECT g_0.e1 AS c_0,
g_0.e3 AS c_1 FROM pm1.g2 AS g_0) AS v_0 GROUP BY v_0.c_0"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+
+ /**
+ * rand pushdown not supported
+ */
+ @Test public void testPushDownOverUnionFiltered3() throws Exception {
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = getAggregateCapabilities();
+ caps.setCapabilitySupport(Capability.ADVANCED_OLAP, true);
+ capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
+
+ ProcessorPlan plan = TestOptimizer.helpPlan("select e1, count(*) filter
(where e3 > rand()) from (select e1, e2, e3 from pm1.g1 union all select e1, e2, e3
from pm1.g2) y group by e1", RealMetadataFactory.example1Cached(), null, capFinder,
//$NON-NLS-1$
+ new String[]{"SELECT g_0.e1, g_0.e3 FROM pm1.g1 AS g_0", "SELECT
g_0.e1, g_0.e3 FROM pm1.g2 AS g_0"}, ComparisonMode.EXACT_COMMAND_STRING);
//$NON-NLS-1$
+ TestOptimizer.checkNodeTypes(plan, new int[] {
+ 2, // Access
+ 0, // DependentAccess
+ 0, // DependentSelect
+ 0, // DependentProject
+ 0, // DupRemove
+ 1, // Grouping
+ 0, // NestedLoopJoinStrategy
+ 0, // MergeJoinStrategy
+ 0, // Null
+ 0, // PlanExecution
+ 1, // Project
+ 0, // Select
+ 0, // Sort
+ 1 // UnionAll
+ });
+ }
+
@Test public void testPushDownOverUnion1() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = getAggregateCapabilities();
@@ -908,7 +1056,7 @@
capFinder.addCapabilities("pm2", getAggregateCapabilities());
//$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan("select max(e2), case when e1 is
null then 0 else 1 end from (select e1, e2 from pm1.g1 union all select e1, e2 from
pm2.g2) z group by case when e1 is null then 0 else 1 end",
RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
- new String[]{"SELECT v_1.c_0, MAX(v_1.c_1) FROM (SELECT CASE WHEN
v_0.c_0 IS NULL THEN 0 ELSE 1 END AS c_0, v_0.c_1 FROM (SELECT g_0.e1 AS c_0, g_0.e2 AS
c_1 FROM pm1.g1 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_0", //$NON-NLS-1$
+ new String[]{"SELECT v_1.c_1, MAX(v_1.c_0) FROM (SELECT v_0.c_1 AS c_0,
CASE WHEN v_0.c_0 IS NULL THEN 0 ELSE 1 END AS c_1 FROM (SELECT g_0.e1 AS c_0, g_0.e2 AS
c_1 FROM pm1.g1 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_1", //$NON-NLS-1$
"SELECT g_0.e1, g_0.e2 FROM pm2.g2 AS g_0"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
@@ -921,7 +1069,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 3, // Project
+ 2, // Project
0, // Select
0, // Sort
1 // UnionAll
@@ -935,8 +1083,8 @@
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan("select max(e2), case when e1 is
null then 0 else 1 end from (select e1, e2, 1 as part from pm1.g1 union all select e1, e2,
2 as part from pm1.g2) z group by case when e1 is null then 0 else 1 end, part",
RealMetadataFactory.example1Cached(), null, capFinder, //$NON-NLS-1$
- new String[]{"SELECT MAX(v_1.c_2), v_1.c_0 FROM (SELECT CASE WHEN
v_0.c_0 IS NULL THEN 0 ELSE 1 END AS c_0, v_0.c_1, v_0.c_2 FROM (SELECT g_0.e1 AS c_0, 2
AS c_1, g_0.e2 AS c_2 FROM pm1.g2 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_0, v_1.c_1",
- "SELECT MAX(v_1.c_2), v_1.c_0 FROM (SELECT CASE WHEN v_0.c_0 IS NULL THEN 0
ELSE 1 END AS c_0, v_0.c_1, v_0.c_2 FROM (SELECT g_0.e1 AS c_0, 1 AS c_1, g_0.e2 AS c_2
FROM pm1.g1 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_0, v_1.c_1"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+ new String[]{"SELECT MAX(v_1.c_0), v_1.c_1 FROM (SELECT v_0.c_2 AS c_0,
CASE WHEN v_0.c_0 IS NULL THEN 0 ELSE 1 END AS c_1, v_0.c_1 AS c_2 FROM (SELECT g_0.e1 AS
c_0, 1 AS c_1, g_0.e2 AS c_2 FROM pm1.g1 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_1,
v_1.c_2",
+ "SELECT MAX(v_1.c_0), v_1.c_1 FROM (SELECT v_0.c_2 AS c_0, CASE WHEN v_0.c_0
IS NULL THEN 0 ELSE 1 END AS c_1, v_0.c_1 AS c_2 FROM (SELECT g_0.e1 AS c_0, 2 AS c_1,
g_0.e2 AS c_2 FROM pm1.g2 AS g_0) AS v_0) AS v_1 GROUP BY v_1.c_1, v_1.c_2"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, new int[] {
2, // Access
0, // DependentAccess
Modified:
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/TestExpressionsInGroupBy.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -32,10 +32,7 @@
/**
- * expressions in group use lacks robust support in MySQL, PostGres, and Derby
Expressions and it's nothing more than syntactic sugar for an inline view,
- * a new approach was taken to use inline views rather than a non ANSI group by
construct.
- *
- * Later we can add a connector binding property to support non-select expressions in
group by.
+ * expressions in group use lacks robust support in MySQL, PostGres, and Derby, so a
compensation step must be taken to create an inline view
*/
public class TestExpressionsInGroupBy {
@@ -57,7 +54,7 @@
// Plan query
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.exampleBQTCached(),
null, capFinder,
- new String[] { "SELECT convert(TimestampValue, date), COUNT(*) FROM
bqt1.smalla GROUP BY convert(TimestampValue, date)" }, //$NON-NLS-1$
+ new String[] { "SELECT v_0.c_0, COUNT(*) FROM (SELECT
convert(g_0.TimestampValue, date) AS c_0 FROM bqt1.smalla AS g_0) AS v_0 GROUP BY
v_0.c_0" }, //$NON-NLS-1$
true);
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
@@ -81,7 +78,7 @@
// Plan query
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.exampleBQTCached(),
null, capFinder,
- new String[] { "SELECT convert(TimestampValue, date), COUNT(*) FROM
bqt1.smalla GROUP BY convert(TimestampValue, date)" }, //$NON-NLS-1$
+ new String[] { "SELECT v_0.c_0, COUNT(*) FROM (SELECT
convert(g_0.TimestampValue, date) AS c_0 FROM bqt1.smalla AS g_0) AS v_0 GROUP BY
v_0.c_0" }, //$NON-NLS-1$
true);
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}
@@ -105,7 +102,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -143,7 +140,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -181,7 +178,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -213,7 +210,7 @@
}
/**
- * Without inline view support the agg is not pushed down
+ * Without inline view support or functions in group by the agg is not pushed down
*/
@Test public void testFunctionInGroupBy() {
String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
@@ -226,6 +223,7 @@
caps.setCapabilitySupport(Capability.QUERY_CASE, true);
caps.setCapabilitySupport(Capability.QUERY_SEARCHED_CASE, true);
caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_SUM, true);
+ caps.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, true);
caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
@@ -233,7 +231,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.exampleBQTCached(),
null, capFinder,
- new String[] {"SELECT CASE WHEN
BQT1.SmallA.IntKey >= 5000 THEN '5000 +' ELSE '0-999' END,
BQT1.SmallA.IntKey FROM BQT1.SmallA"}, //$NON-NLS-1$
+ new String[] {"SELECT BQT1.SmallA.IntKey FROM
BQT1.SmallA"}, //$NON-NLS-1$
TestOptimizer.SHOULD_SUCCEED );
TestOptimizer.checkNodeTypes(plan, new int[] {
@@ -254,6 +252,60 @@
});
}
+ @Test public void testFunctionInGroupBy1() {
+ String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
+ "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000
+' else '0-999' end"; //$NON-NLS-1$
+
+ // Plan query
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
+ caps.setCapabilitySupport(Capability.QUERY_CASE, true);
+ caps.setCapabilitySupport(Capability.QUERY_SEARCHED_CASE, true);
+ caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_SUM, true);
+ caps.setCapabilitySupport(Capability.QUERY_FUNCTIONS_IN_GROUP_BY, true);
+ caps.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
+ caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, true);
+ caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
+ capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
+
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
+ RealMetadataFactory.exampleBQTCached(),
+ null, capFinder,
+ new String[] {"SELECT SUM(BQT1.SmallA.IntKey),
CASE WHEN BQT1.SmallA.IntKey >= 5000 THEN '5000 +' ELSE '0-999' END
FROM BQT1.SmallA GROUP BY CASE WHEN BQT1.SmallA.IntKey >= 5000 THEN '5000 +'
ELSE '0-999' END"}, //$NON-NLS-1$
+ TestOptimizer.SHOULD_SUCCEED );
+
+ TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
+ }
+
+ @Test public void testFunctionInGroupBy2() {
+ String sql = "SELECT sum (IntKey), case when IntKey>=5000 then '5000
+' else '0-999' end " + //$NON-NLS-1$
+ "FROM BQT1.SmallA GROUP BY case when IntKey>=5000 then '5000
+' else '0-999' end"; //$NON-NLS-1$
+
+ // Plan query
+ FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
+ BasicSourceCapabilities caps = new BasicSourceCapabilities();
+ caps.setCapabilitySupport(Capability.QUERY_SELECT_EXPRESSION, true);
+ caps.setCapabilitySupport(Capability.QUERY_CASE, true);
+ caps.setCapabilitySupport(Capability.QUERY_SEARCHED_CASE, true);
+ caps.setCapabilitySupport(Capability.QUERY_AGGREGATES_SUM, true);
+ caps.setCapabilitySupport(Capability.QUERY_FROM_INLINE_VIEWS, true);
+ caps.setCapabilitySupport(Capability.QUERY_GROUP_BY, true);
+ caps.setCapabilitySupport(Capability.QUERY_FROM_GROUP_ALIAS, true);
+ caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_ORDERED, true);
+ caps.setCapabilitySupport(Capability.CRITERIA_COMPARE_EQ, true);
+ capFinder.addCapabilities("BQT1", caps); //$NON-NLS-1$
+
+ ProcessorPlan plan = TestOptimizer.helpPlan(sql,
+ RealMetadataFactory.exampleBQTCached(),
+ null, capFinder,
+ new String[] {"SELECT SUM(v_0.c_1), v_0.c_0
FROM (SELECT CASE WHEN g_0.IntKey >= 5000 THEN '5000 +' ELSE '0-999'
END AS c_0, g_0.IntKey AS c_1 FROM BQT1.SmallA AS g_0) AS v_0 GROUP BY v_0.c_0"},
//$NON-NLS-1$
+ TestOptimizer.SHOULD_SUCCEED );
+
+ TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
+ }
+
+
/**
* Test what happens when we have a CASE in the GROUP BY and source has aggregate
capability but
* does not have CASE capability. Should not be able to push down GROUP BY.
@@ -291,7 +343,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -336,7 +388,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
1, // Select
0, // Sort
0 // UnionAll
@@ -378,7 +430,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
@@ -410,7 +462,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
1, // Select
0, // Sort
0 // UnionAll
@@ -442,7 +494,7 @@
0, // MergeJoinStrategy
0, // Null
0, // PlanExecution
- 2, // Project
+ 1, // Project
0, // Select
0, // Sort
0 // UnionAll
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestInlineView.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestInlineView.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestInlineView.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -25,6 +25,7 @@
import static org.teiid.query.optimizer.TestOptimizer.*;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -94,10 +95,8 @@
String userQuery = "select q1.a from (select count(bqt1.smalla.intkey) as a,
bqt1.smalla.intkey from bqt1.smalla group by bqt1.smalla.intkey) q1 left outer join
bqt1.smallb on q1.a = bqt1.smallb.intkey where q1.intkey = 1"; //$NON-NLS-1$
String optimizedQuery = "SELECT v_0.c_0 FROM (SELECT COUNT(g_0.intkey) AS c_0 FROM
bqt1.smalla AS g_0 WHERE g_0.intkey = 1 GROUP BY g_0.intkey) AS v_0 LEFT OUTER JOIN
bqt1.smallb AS g_1 ON v_0.c_0 = g_1.intkey"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -116,10 +115,8 @@
"where
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.intkey
= 1 and
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
= bqt1.smallb.intkey"; //$NON-NLS-1$
String optimizedQuery = "SELECT v_0.c_0 FROM (SELECT COUNT(g_0.intkey) AS c_0 FROM
bqt1.smalla AS g_0 WHERE g_0.intkey = 1 GROUP BY g_0.intkey) AS v_0, bqt1.smallb AS g_1
WHERE v_0.c_0 = g_1.intkey"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -134,12 +131,10 @@
public static InlineViewCase createInlineViewWithDistinctAndOrderBy() throws Exception
{
String userQuery = "select Q1.a from (select distinct count(bqt1.smalla.intkey) as
a, bqt1.smalla.intkey from bqt1.smalla group by bqt1.smalla.intkey order by
bqt1.smalla.intkey) q1 inner join bqt1.smallb as q2 on q1.intkey = q2.intkey where q1.a =
1 and q1.a + q1.intkey = 2"; //$NON-NLS-1$
- String optimizedQuery = "SELECT v_0.c_1 FROM (SELECT g_0.intkey AS c_0,
COUNT(g_0.intkey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey HAVING
((COUNT(g_0.intkey) + g_0.intkey) = 2) AND (COUNT(g_0.intkey) = 1)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey"; //$NON-NLS-1$
+ String optimizedQuery = "SELECT v_0.c_1 FROM (SELECT g_0.intkey AS c_0,
COUNT(g_0.intkey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey HAVING
(COUNT(g_0.intkey) = 1) AND ((COUNT(g_0.intkey) + g_0.intkey) = 2)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
+ List<List<?>> expectedResults = new
ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -157,7 +152,7 @@
String userQuery = "select q1.A from (select count(intkey) as a, intkey, stringkey
from vqt.smalla group by intkey, stringkey) q1 inner join vqt.smallb as q2 on q1.intkey =
q2.a12345 where q1.a = 2"; //$NON-NLS-1$
String optimizedQuery = "SELECT v_0.c_1 FROM (SELECT g_0.IntKey AS c_0,
COUNT(g_0.IntKey) AS c_1 FROM BQT1.SmallA AS g_0 GROUP BY g_0.IntKey, g_0.StringKey HAVING
COUNT(g_0.IntKey) = 2) AS v_0, BQT1.SmallA AS g_1 WHERE v_0.c_0 = Concat(g_1.StringKey,
g_1.StringNum)"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -172,12 +167,10 @@
public static InlineViewCase createInlineViewWithOuterOrderAndGroup() throws Exception
{
String userQuery = "select count(Q1.a) b from (select distinct
count(bqt1.smalla.intkey) as a, bqt1.smalla.intkey from bqt1.smalla group by
bqt1.smalla.intkey order by bqt1.smalla.intkey) q1 inner join bqt1.smallb as q2 on
q1.intkey = q2.intkey where q1.a = 1 and q1.a + q1.intkey = 2 group by Q1.a order by
b"; //$NON-NLS-1$
- String optimizedQuery = "SELECT COUNT(v_0.c_1) AS c_0 FROM (SELECT g_0.intkey AS
c_0, COUNT(g_0.intkey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey HAVING
((COUNT(g_0.intkey) + g_0.intkey) = 2) AND (COUNT(g_0.intkey) = 1)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1 ORDER BY c_0"; //$NON-NLS-1$
+ String optimizedQuery = "SELECT COUNT(v_0.c_1) AS c_0 FROM (SELECT g_0.intkey AS
c_0, COUNT(g_0.intkey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.intkey HAVING
(COUNT(g_0.intkey) = 1) AND ((COUNT(g_0.intkey) + g_0.intkey) = 2)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1 ORDER BY c_0"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -192,15 +185,11 @@
public static InlineViewCase crateInlineViewsInUnions() throws Exception {
String userQuery = "select q1.a from (select count(bqt1.smalla.intkey) as a,
bqt1.smalla.intkey from bqt1.smalla group by bqt1.smalla.intkey) q1 left outer join
bqt1.smallb on q1.a = bqt1.smallb.intkey where q1.intkey = 1 union all (select count(Q1.a)
b from (select distinct count(bqt1.smalla.intkey) as a, bqt1.smalla.intkey from
bqt1.smalla group by bqt1.smalla.intkey order by bqt1.smalla.intkey) q1 inner join
bqt1.smallb as q2 on q1.intkey = q2.intkey where q1.a = 1 and q1.a + q1.intkey = 2 group
by Q1.a order by b)"; //$NON-NLS-1$
- String optimizedQuery = "SELECT v_1.c_0 FROM (SELECT COUNT(g_2.intkey) AS c_0 FROM
bqt1.smalla AS g_2 WHERE g_2.intkey = 1 GROUP BY g_2.intkey) AS v_1 LEFT OUTER JOIN
bqt1.smallb AS g_3 ON v_1.c_0 = g_3.intkey UNION ALL SELECT COUNT(v_0.c_1) AS c_0 FROM
(SELECT g_0.IntKey AS c_0, COUNT(g_0.IntKey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY
g_0.IntKey HAVING ((COUNT(g_0.IntKey) + g_0.IntKey) = 2) AND (COUNT(g_0.IntKey) = 1)) AS
v_0, bqt1.smallb AS g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1"; //$NON-NLS-1$
+ String optimizedQuery = "SELECT v_1.c_0 FROM (SELECT COUNT(g_2.intkey) AS c_0 FROM
bqt1.smalla AS g_2 WHERE g_2.intkey = 1 GROUP BY g_2.intkey) AS v_1 LEFT OUTER JOIN
bqt1.smallb AS g_3 ON v_1.c_0 = g_3.intkey UNION ALL SELECT COUNT(v_0.c_1) AS c_0 FROM
(SELECT g_0.IntKey AS c_0, COUNT(g_0.IntKey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY
g_0.IntKey HAVING (COUNT(g_0.IntKey) = 1) AND ((COUNT(g_0.IntKey) + g_0.IntKey) = 2)) AS
v_0, bqt1.smallb AS g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
- List row2 = new ArrayList();
- row2.add(new Integer(1));
- expectedResults.add(row2);
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
+ expectedResults.add(Arrays.asList(2));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
@@ -217,15 +206,11 @@
public static InlineViewCase createUnionInInlineView() throws Exception{
String userQuery = "select t1.intkey from (select case when q1.a=1 then 2 else
1 end as a from (select count(bqt1.smalla.intkey) as a, bqt1.smalla.intkey from
bqt1.smalla group by bqt1.smalla.intkey) q1 left outer join bqt1.smallb on q1.a =
bqt1.smallb.intkey where q1.intkey = 1 union all (select count(Q1.a) b from (select
distinct count(bqt1.smalla.intkey) as a, bqt1.smalla.intkey from bqt1.smalla group by
bqt1.smalla.intkey order by bqt1.smalla.intkey) q1 inner join bqt1.smallb as q2 on
q1.intkey = q2.intkey where q1.a = 1 and q1.a + q1.intkey = 2 group by Q1.a order by b))
as q3, bqt1.smallb as t1 where q3.a = t1.intkey order by t1.intkey"; //$NON-NLS-1$
- String optimizedQuery = "SELECT g_4.intkey AS c_0 FROM (SELECT CASE WHEN v_1.c_0 =
1 THEN 2 ELSE 1 END AS c_0 FROM (SELECT COUNT(g_2.intkey) AS c_0 FROM bqt1.smalla AS g_2
WHERE g_2.intkey = 1 GROUP BY g_2.intkey) AS v_1 LEFT OUTER JOIN bqt1.smallb AS g_3 ON
v_1.c_0 = g_3.intkey UNION ALL SELECT COUNT(v_0.c_1) AS c_0 FROM (SELECT g_0.IntKey AS
c_0, COUNT(g_0.IntKey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.IntKey HAVING
((COUNT(g_0.IntKey) + g_0.IntKey) = 2) AND (COUNT(g_0.IntKey) = 1)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1) AS v_2, bqt1.smallb AS g_4 WHERE v_2.c_0
= g_4.intkey ORDER BY c_0"; //$NON-NLS-1$
+ String optimizedQuery = "SELECT g_4.intkey AS c_0 FROM (SELECT CASE WHEN v_1.c_0 =
1 THEN 2 ELSE 1 END AS c_0 FROM (SELECT COUNT(g_2.intkey) AS c_0 FROM bqt1.smalla AS g_2
WHERE g_2.intkey = 1 GROUP BY g_2.intkey) AS v_1 LEFT OUTER JOIN bqt1.smallb AS g_3 ON
v_1.c_0 = g_3.intkey UNION ALL SELECT COUNT(v_0.c_1) AS c_0 FROM (SELECT g_0.IntKey AS
c_0, COUNT(g_0.IntKey) AS c_1 FROM bqt1.smalla AS g_0 GROUP BY g_0.IntKey HAVING
(COUNT(g_0.IntKey) = 1) AND ((COUNT(g_0.IntKey) + g_0.IntKey) = 2)) AS v_0, bqt1.smallb AS
g_1 WHERE v_0.c_0 = g_1.intkey GROUP BY v_0.c_1) AS v_2, bqt1.smallb AS g_4 WHERE v_2.c_0
= g_4.intkey ORDER BY c_0"; //$NON-NLS-1$
- List expectedResults = new ArrayList();
- List row1 = new ArrayList();
- row1.add(new Integer(1));
- expectedResults.add(row1);
- List row2 = new ArrayList();
- row2.add(new Integer(2));
- expectedResults.add(row2);
+ List<List<?>> expectedResults = new ArrayList<List<?>>();
+ expectedResults.add(Arrays.asList(1));
+ expectedResults.add(Arrays.asList(2));
Set<String> sourceQueries = new HashSet<String>();
sourceQueries.add("oracle"); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestLimit.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -25,8 +25,7 @@
import java.util.Arrays;
import java.util.List;
-import junit.framework.TestCase;
-
+import org.junit.Test;
import org.teiid.core.types.DataTypeManager;
import org.teiid.metadata.Column;
import org.teiid.metadata.MetadataStore;
@@ -59,7 +58,7 @@
import org.teiid.query.unittest.RealMetadataFactory;
@SuppressWarnings("nls")
-public class TestLimit extends TestCase {
+public class TestLimit {
private static final int[] FULL_PUSHDOWN = new int[] {
1, // Access
@@ -97,10 +96,6 @@
UnionAllNode.class
};
- public TestLimit(String name) {
- super(name);
- }
-
private static TransformationMetadata exampleMetadata() {
MetadataStore metadataStore = new MetadataStore();
// Create models
@@ -157,7 +152,7 @@
return RealMetadataFactory.createTransformationMetadata(metadataStore,
"example");
}
- public void testLimit() {
+ @Test public void testLimit() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
@@ -189,7 +184,7 @@
}, NODE_TYPES);
}
- public void testLimitPushdown() {
+ @Test public void testLimitPushdown() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -205,7 +200,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testLimitWithOffset() {
+ @Test public void testLimitWithOffset() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
@@ -236,7 +231,7 @@
}, NODE_TYPES);
}
- public void testPushedLimitWithOffset() throws Exception {
+ @Test public void testPushedLimitWithOffset() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -268,7 +263,7 @@
}, NODE_TYPES);
}
- public void testLimitWithOffsetFullyPushed() {
+ @Test public void testLimitWithOffsetFullyPushed() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -285,7 +280,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testSort() {
+ @Test public void testSort() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
@@ -316,7 +311,7 @@
}, NODE_TYPES);
}
- public void testSortPushed() {
+ @Test public void testSortPushed() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -349,7 +344,7 @@
}, NODE_TYPES);
}
- public void testSortPushedWithLimit() {
+ @Test public void testSortPushedWithLimit() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -367,7 +362,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testSortUnderLimitNotRemoved() {
+ @Test public void testSortUnderLimitNotRemoved() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
// pm3 model supports order by
@@ -400,7 +395,7 @@
}
//TODO: there is a redundent project node here
- public void testSortAboveLimitNotPushed() {
+ @Test public void testSortAboveLimitNotPushed() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -433,7 +428,7 @@
}, NODE_TYPES);
}
- public void testLimitNotPushedWithUnion() {
+ @Test public void testLimitNotPushedWithUnion() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -466,7 +461,7 @@
}, NODE_TYPES);
}
- public void testLimitNotPushedWithDupRemove() {
+ @Test public void testLimitNotPushedWithDupRemove() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -499,7 +494,7 @@
}, NODE_TYPES);
}
- public void testLimitPushedWithUnionAll() {
+ @Test public void testLimitPushedWithUnionAll() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -532,7 +527,7 @@
}, NODE_TYPES);
}
- public void testLimitWithOffsetPushedWithUnion() throws Exception {
+ @Test public void testLimitWithOffsetPushedWithUnion() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -567,7 +562,7 @@
}, NODE_TYPES);
}
- public void testLimitNotPushedWithUnionOrderBy() {
+ @Test public void testLimitNotPushedWithUnionOrderBy() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -601,7 +596,7 @@
TestOptimizer.checkNodeTypes(plan, new int[] {1}, new
Class[]{DupRemoveSortNode.class});
}
- public void testCombinedLimits() throws Exception {
+ @Test public void testCombinedLimits() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -635,7 +630,7 @@
}, NODE_TYPES);
}
- public void testCombinedLimitsWithOffset() throws Exception {
+ @Test public void testCombinedLimitsWithOffset() throws Exception {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -654,7 +649,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testInlineView() {
+ @Test public void testInlineView() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
//caps.setCapabilitySupport(SourceCapabilities.QUERY_ORDERBY, true);
@@ -682,7 +677,7 @@
*
* @since 4.3
*/
- public void testInlineViewAboveLimitNotMerged() {
+ @Test public void testInlineViewAboveLimitNotMerged() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_ORDERBY, true);
@@ -706,7 +701,7 @@
* since there is no order by with the nested limit, the criteria can be pushed
through
*
*/
- public void testCriteriaPushedUnderLimit() {
+ @Test public void testCriteriaPushedUnderLimit() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.ROW_LIMIT, true);
@@ -724,7 +719,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testInlineViewJoin() {
+ @Test public void testInlineViewJoin() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
caps.setCapabilitySupport(Capability.QUERY_UNION, true);
@@ -768,7 +763,7 @@
});
}
- public void testDontPushSelectWithOrderedLimit() {
+ @Test public void testDontPushSelectWithOrderedLimit() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
@@ -798,7 +793,7 @@
}, NODE_TYPES);
}
- public void testDontPushSelectWithOrderedLimit1() {
+ @Test public void testDontPushSelectWithOrderedLimit1() {
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = TestOptimizer.getTypicalCapabilities();
capFinder.addCapabilities("pm1", caps); //$NON-NLS-1$
@@ -828,7 +823,7 @@
}, NODE_TYPES);
}
- public void testLimitWithNoAccessNode() {
+ @Test public void testLimitWithNoAccessNode() {
String sql = "select 1 limit 1";//$NON-NLS-1$
String[] expectedSql = new String[] {};
@@ -856,7 +851,7 @@
/**
* Note here that the criteria made it to the having clause
*/
- public void testAggregateCriteriaOverUnSortedLimit() {
+ @Test public void testAggregateCriteriaOverUnSortedLimit() {
String sql = "select a from (SELECT MAX(e2) as a FROM pm1.g1 GROUP BY e2
LIMIT 1) x where a = 0"; //$NON-NLS-1$
FakeCapabilitiesFinder capFinder = new FakeCapabilitiesFinder();
BasicSourceCapabilities caps = new BasicSourceCapabilities();
@@ -874,7 +869,7 @@
TestOptimizer.checkNodeTypes(plan, FULL_PUSHDOWN, NODE_TYPES);
}
- public void testSortWithLimitInlineView() {
+ @Test public void testSortWithLimitInlineView() {
String sql = "select e1 from (select pm1.g1.e1, pm1.g1.e2 from pm1.g1 order
by pm1.g1.e1, pm1.g1.e2 limit 1) x"; //$NON-NLS-1$
ProcessorPlan plan = TestOptimizer.helpPlan(sql,
RealMetadataFactory.example1Cached(), new String[] {"SELECT g_0.e1 AS c_0 FROM pm1.g1
AS g_0 ORDER BY c_0, g_0.e2"}); //$NON-NLS-1$
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/optimizer/TestOptimizer.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -6286,7 +6286,7 @@
String sql = "select a.e1 from (select 1 e1) a, (select e1, 1 as a, x from
(select e1, CASE WHEN e1 = 'a' THEN e2 ELSE e3 END as x from pm1.g2) y group by
e1, x) b where a.e1 = b.x"; //$NON-NLS-1$
ProcessorPlan plan = helpPlan(sql, metadata, null, capFinder,
- new String[] {"SELECT v_1.c_0 FROM (SELECT
v_0.c_1 AS c_0 FROM (SELECT g_0.e1 AS c_0, CASE WHEN g_0.e1 = 'a' THEN g_0.e2 ELSE
g_0.e3 END AS c_1 FROM pm1.g2 AS g_0 WHERE CASE WHEN g_0.e1 = 'a' THEN g_0.e2 ELSE
g_0.e3 END IN (<dependent values>)) AS v_0 GROUP BY v_0.c_0, v_0.c_1) AS v_1 ORDER
BY c_0"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
+ new String[] {"SELECT v_0.c_0 FROM (SELECT
CASE WHEN g_0.e1 = 'a' THEN g_0.e2 ELSE g_0.e3 END AS c_0 FROM pm1.g2 AS g_0 GROUP
BY g_0.e1, CASE WHEN g_0.e1 = 'a' THEN g_0.e2 ELSE g_0.e3 END) AS v_0 WHERE
v_0.c_0 IN (<dependent values>) ORDER BY c_0"},
ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
checkNodeTypes(plan, new int[] {
0, // Access
Modified: trunk/engine/src/test/java/org/teiid/query/optimizer/xml/TestXMLPlanner.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/optimizer/xml/TestXMLPlanner.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/optimizer/xml/TestXMLPlanner.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -30,7 +30,6 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.id.IDGenerator;
-import org.teiid.core.id.IntegerIDFactory;
import org.teiid.core.types.DataTypeManager;
import org.teiid.metadata.MetadataStore;
import org.teiid.metadata.Schema;
@@ -689,7 +688,6 @@
public static XMLPlan preparePlan(Command command, QueryMetadataInterface metadata,
CapabilitiesFinder capFinder, CommandContext context)
throws QueryPlannerException, QueryMetadataException, TeiidComponentException {
IDGenerator idGenerator = new IDGenerator();
- idGenerator.setDefaultFactory(new IntegerIDFactory());
AnalysisRecord analysis = new AnalysisRecord(false, DEBUG);
try {
if (DEBUG) {
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-07-19 13:41:13
UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2011-07-20 03:27:02
UTC (rev 3317)
@@ -117,6 +117,7 @@
import org.teiid.query.sql.symbol.TestCaseExpression;
import org.teiid.query.sql.symbol.TestSearchedCaseExpression;
import org.teiid.query.sql.symbol.TextLine;
+import org.teiid.query.sql.symbol.WindowFunction;
import org.teiid.query.sql.symbol.XMLAttributes;
import org.teiid.query.sql.symbol.XMLElement;
import org.teiid.query.sql.symbol.XMLForest;
@@ -1413,28 +1414,12 @@
@Test public void testFailAliasInHaving() {
helpException("SELECT a FROM m.g GROUP BY a, b AS x"); //$NON-NLS-1$
}
-
- /** SELECT a FROM m.g GROUP BY count(a) */
- @Test public void testFailAggregateInGroupBy() {
- helpException("SELECT a FROM m.g GROUP BY count(a)"); //$NON-NLS-1$
- }
-
- @Test public void testExceptionLength() {
+ @Test(expected=QueryParserException.class) public void testExceptionLength() throws
Exception {
String sql = "SELECT * FROM Customer where Customer.Name = (select lastname
from CUSTOMER where acctid = 9"; ////$NON-NLS-1$
- try {
- QueryParser.getQueryParser().parseCommand(sql);
- fail("Expected exception for parsing " + sql); //$NON-NLS-1$
- } catch (TeiidException e) {
- //e.printStackTrace();
- //if (e.getMessage().length() > 1000) {
- // fail("Expected max length of message 1000; but received " +
e.getMessage().length()); //$NON-NLS-1$
- //}
- }
+ QueryParser.getQueryParser().parseCommand(sql);
}
-
-
@Test public void testFunctionOfAggregates() {
GroupSymbol g = new GroupSymbol("m.g"); //$NON-NLS-1$
From from = new From();
@@ -6425,14 +6410,6 @@
}
}
- @Test public void testExceptionMessageWithoutLocation() {
- try {
- QueryParser.getQueryParser().parseCommand("SELECT COUNT(*) FROM a WHERE
COUNT(*) > 1"); //$NON-NLS-1$
- } catch(QueryParserException e) {
- assertTrue(e.getMessage().startsWith("Parsing error: Aggregate
expressions are allowed only as top level functions in the SELECT and HAVING
clauses.")); //$NON-NLS-1$
- }
- }
-
@Test public void testEmptyOuterJoinCriteria() {
helpException("select a from b left outer join c on ()");
//$NON-NLS-1$
}
@@ -6852,5 +6829,34 @@
query.setSelect(new Select(Arrays.asList(new ExpressionSymbol("foo", new
Reference(0)))));
helpTest(sql, "SELECT ?", query);
}
+
+ @Test public void testNonReserved() throws Exception {
+ String sql = "select count";
+ Query query = new Query();
+ query.setSelect(new Select(Arrays.asList(new ElementSymbol("count"))));
+ helpTest(sql, "SELECT count", query);
+ }
+
+ @Test public void testAggFilter() throws Exception {
+ String sql = "select count(*) filter (where x = 1) from g";
+ Query query = new Query();
+ AggregateSymbol aggregateSymbol = new AggregateSymbol("count",
AggregateSymbol.Type.COUNT.name(), false, null);
+ aggregateSymbol.setCondition(new CompareCriteria(new ElementSymbol("x"),
CompareCriteria.EQ, new Constant(1)));
+ query.setSelect(new Select(Arrays.asList(aggregateSymbol)));
+ query.setFrom(new From(Arrays.asList(new UnaryFromClause(new
GroupSymbol("g")))));
+ helpTest(sql, "SELECT COUNT(*) FILTER(WHERE x = 1) FROM g", query);
+ }
+
+ @Test public void testWindowFunction() throws Exception {
+ String sql = "select row_number() over (partition by x order by y) from
g";
+ Query query = new Query();
+ WindowFunction wf = new WindowFunction();
+ wf.setFunction(new AggregateSymbol("expr", "ROW_NUMBER", false,
null));
+ wf.setPartition(new ArrayList<Expression>(Arrays.asList(new
ElementSymbol("x"))));
+ wf.setOrderBy(new OrderBy(Arrays.asList(new ElementSymbol("y"))));
+ query.setSelect(new Select(Arrays.asList(new ExpressionSymbol("x",
wf))));
+ query.setFrom(new From(Arrays.asList(new UnaryFromClause(new
GroupSymbol("g")))));
+ helpTest(sql, "SELECT ROW_NUMBER() OVER (PARTITION BY x ORDER BY y) FROM
g", query);
+ }
}
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestAggregateProcessing.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -266,12 +266,12 @@
capFinder.addCapabilities("pm2", bac); //$NON-NLS-1$
HardcodedDataManager dataManager = new HardcodedDataManager();
- dataManager.addData("SELECT v_0.c_1, v_0.c_0, COUNT(*), MAX(v_0.c_2) FROM
(SELECT g_0.e2 AS c_0, g_0.e1 AS c_1, g_0.e3 AS c_2 FROM pm1.g1 AS g_0) AS v_0 GROUP BY
v_0.c_0, v_0.c_1", //$NON-NLS-1$
+ dataManager.addData("SELECT v_0.c_0, v_0.c_1, COUNT(*), MAX(v_0.c_2) FROM
(SELECT g_0.e1 AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2 FROM pm1.g1 AS g_0) AS v_0 GROUP BY
v_0.c_0, v_0.c_1", //$NON-NLS-1$
new List[] {
Arrays.asList("2", Integer.valueOf(2), Integer.valueOf(2),
Boolean.FALSE), //$NON-NLS-1$
Arrays.asList("1", Integer.valueOf(1), Integer.valueOf(3),
Boolean.TRUE), //$NON-NLS-1$
});
- dataManager.addData("SELECT v_0.c_1, v_0.c_0, COUNT(*), MAX(v_0.c_2) FROM
(SELECT g_0.e2 AS c_0, convert(g_0.e2, string) AS c_1, g_0.e3 AS c_2 FROM pm2.g2 AS g_0
ORDER BY c_1 LIMIT 10) AS v_0 GROUP BY v_0.c_0, v_0.c_1", //$NON-NLS-1$
+ dataManager.addData("SELECT v_0.c_0, v_0.c_1, COUNT(*), MAX(v_0.c_2) FROM
(SELECT convert(g_0.e2, string) AS c_0, g_0.e2 AS c_1, g_0.e3 AS c_2 FROM pm2.g2 AS g_0
ORDER BY c_0 LIMIT 10) AS v_0 GROUP BY v_0.c_0, v_0.c_1", //$NON-NLS-1$
new List[] {
Arrays.asList("1", Integer.valueOf(1), Integer.valueOf(4),
Boolean.FALSE), //$NON-NLS-1$
});
@@ -360,9 +360,9 @@
List[] expected = new List[] {
Arrays.asList(null, "cc"),
Arrays.asList(0.0, "bb"),
- Arrays.asList(1.0, null),
- Arrays.asList(2.0, "aa"),
- Arrays.asList(7.0, "aa")
+ Arrays.asList(2.0, null),
+ Arrays.asList(21.0, "aa"),
+ Arrays.asList(24.0, "aa")
};
// Construct data manager with data
@@ -399,5 +399,25 @@
// Run query
helpProcess(plan, cc, dataManager, expected);
}
+
+ @Test public void testAggFilter() throws Exception {
+ // Create query
+ String sql = "SELECT e2, count(*) filter (where e3) from pm1.g1 group by e2 order
by e2"; //$NON-NLS-1$
+ // Create expected results
+ List[] expected = new List[] {
+ Arrays.asList(0, 0),
+ Arrays.asList(1, 1),
+ Arrays.asList(2, 0),
+ Arrays.asList(3, 1),
+ };
+
+ // Construct data manager with data
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached());
+ helpProcess(plan, dataManager, expected);
+ }
+
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/processor/TestProcessor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -360,7 +360,7 @@
Properties props = new Properties();
props.setProperty("soap_host", "my.host.com"); //$NON-NLS-1$
//$NON-NLS-2$
props.setProperty("soap_port", "12345"); //$NON-NLS-1$
//$NON-NLS-2$
- CommandContext context = new CommandContext("0", "test",
"user", null, "myvdb", 1, props, false); //$NON-NLS-1$ //$NON-NLS-2$
//$NON-NLS-3$ //$NON-NLS-4$
+ CommandContext context = new CommandContext("0", "test",
"user", null, "myvdb", 1, props, DEBUG); //$NON-NLS-1$ //$NON-NLS-2$
//$NON-NLS-3$ //$NON-NLS-4$
context.setProcessorBatchSize(BufferManager.DEFAULT_PROCESSOR_BATCH_SIZE);
context.setConnectorBatchSize(BufferManager.DEFAULT_CONNECTOR_BATCH_SIZE);
context.setBufferManager(BufferManagerFactory.getStandaloneBufferManager());
@@ -7570,5 +7570,24 @@
helpProcess(plan, dataManager, new List[] {Arrays.asList(1, 1)});
}
+ @Test public void testOrderByExpression() throws Exception {
+ String sql = "SELECT pm1.g1.e2 as y FROM pm1.g1 ORDER BY e3 || e1";
+
+ List[] expected = new List[] {
+ Arrays.asList(0),
+ Arrays.asList(1),
+ Arrays.asList(3),
+ Arrays.asList(1),
+ Arrays.asList(2),
+ Arrays.asList(0),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+ ProcessorPlan plan = helpGetPlan(sql, RealMetadataFactory.example1Cached(),
TestOptimizer.getGenericFinder());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
private static final boolean DEBUG = false;
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestVirtualDepJoin.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -364,7 +364,7 @@
List<String> expectedQueries = new ArrayList<String>(6);
for (int i = 0; i < 3; i++) {
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$
+ expectedQueries.add("SELECT g_0.id, g_0.amount FROM Europe.CustAccts AS g_0
WHERE g_0.id = 100"); //$NON-NLS-1$
}
assertEquals(expectedQueries, dataManager.getQueries());
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestSearchedCaseExpression.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestSearchedCaseExpression.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/sql/symbol/TestSearchedCaseExpression.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -25,16 +25,11 @@
import java.util.ArrayList;
import java.util.List;
+import junit.framework.TestCase;
+
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.sql.lang.CompareCriteria;
-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.SearchedCaseExpression;
-
-import junit.framework.TestCase;
-
public class TestSearchedCaseExpression extends TestCase {
/**
Modified:
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/engine/src/test/java/org/teiid/query/sql/visitor/TestExpressionMappingVisitor.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -45,7 +45,6 @@
import org.teiid.query.sql.symbol.SearchedCaseExpression;
import org.teiid.query.sql.symbol.TestCaseExpression;
import org.teiid.query.sql.symbol.TestSearchedCaseExpression;
-import org.teiid.query.sql.visitor.ExpressionMappingVisitor;
import org.teiid.translator.SourceSystemFunctions;
@@ -196,13 +195,13 @@
* a function.
*/
@Test public void testRecursionDetection() {
- ElementSymbol e1 = new ElementSymbol("e1"); //$NON-NLS-1$
+ ElementSymbol e1 = new ElementSymbol("g1.e1"); //$NON-NLS-1$
AggregateSymbol a1 = new AggregateSymbol("x", NonReserved.SUM, false, e1);
//$NON-NLS-1$
Function f = new Function(SourceSystemFunctions.ADD_OP, new Expression[] {a1, a1});
HashMap<AggregateSymbol, AggregateSymbol> map = new
HashMap<AggregateSymbol, AggregateSymbol>();
map.put(a1, new AggregateSymbol("x", NonReserved.SUM, false, a1));
//$NON-NLS-1$
ExpressionMappingVisitor.mapExpressions(f, map);
- assertEquals("(SUM(SUM(e1)) + SUM(SUM(e1)))", f.toString());
//$NON-NLS-1$
+ assertEquals("(SUM(SUM(g1.e1)) + SUM(SUM(g1.e1)))", f.toString());
//$NON-NLS-1$
}
}
Modified: trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-07-19
13:41:13 UTC (rev 3316)
+++ trunk/engine/src/test/java/org/teiid/query/validator/TestValidator.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -1839,5 +1839,25 @@
models.add("MultiModel");
helpValidate("exec MultiModel.proc('a', (select 1))", new
String[] {"MultiModel.proc.source_name"}, new
MultiSourceMetadataWrapper(RealMetadataFactory.exampleMultiBinding(), models));
//$NON-NLS-1$
}
+
+ @Test public void testFailAggregateInGroupBy() {
+ helpValidate("SELECT max(e1) FROM pm1.g1 GROUP BY count(e2)", new String[]
{"COUNT(e2)"}, RealMetadataFactory.example1Cached());
+ }
+
+ @Test public void testFailAggregateInWhere() {
+ helpValidate("SELECT e1 FROM pm1.g1 where count(e2) = 1", new String[]
{"COUNT(e2)"}, RealMetadataFactory.example1Cached());
+ }
+ @Test public void testFailAggregateInFrom() {
+ helpValidate("SELECT g2.e1 FROM pm1.g1 inner join pm1.g2 on (avg(g1.e2) =
g2.e2)", new String[] {"AVG(g1.e2)"},
RealMetadataFactory.example1Cached());
+ }
+
+ @Test public void testFailAggregateFilterSubquery() {
+ helpValidate("SELECT min(g1.e1) filter (where (select 1) = 1) from pm1.g1",
new String[] {"(SELECT 1) = 1"}, RealMetadataFactory.example1Cached());
+ }
+
+ @Test public void testNestedAgg() {
+ helpValidate("SELECT min(g1.e1) filter (where max(e2) = 1) from pm1.g1", new
String[] {"MAX(e2)"}, RealMetadataFactory.example1Cached());
+ }
+
}
Modified:
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java
===================================================================
---
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java 2011-07-19
13:41:13 UTC (rev 3316)
+++
trunk/test-integration/common/src/test/java/org/teiid/dqp/internal/process/TestTPCR.java 2011-07-20
03:27:02 UTC (rev 3317)
@@ -191,7 +191,7 @@
ProcessorPlan plan = TestOptimizer.helpPlan("SELECT custsale.cntrycode,
COUNT(*) AS numcust, SUM(c_acctbal) AS totacctbal FROM (SELECT left(C_PHONE, 2) AS
cntrycode, CUSTOMER.C_ACCTBAL FROM CUSTOMER WHERE (left(C_PHONE, 2) IN
('13','31','23','29','30','18','17'))
AND (CUSTOMER.C_ACCTBAL > (SELECT AVG(CUSTOMER.C_ACCTBAL) FROM CUSTOMER WHERE
(CUSTOMER.C_ACCTBAL > 0.0) AND (left(C_PHONE, 2) IN
('13','31','23','29','30','18','17'))))
AND (NOT (EXISTS (SELECT * FROM ORDERS WHERE O_CUSTKEY = C_CUSTKEY)))) AS custsale GROUP
BY custsale.cntrycode ORDER BY custsale.cntrycode", //$NON-NLS-1$
METADATA, null, finder,
- new String[] {"SELECT v_0.c_0, COUNT(*) AS c_1, SUM(v_0.c_1) AS c_2 FROM
(SELECT left(g_0.C_PHONE, 2) AS c_0, g_0.C_ACCTBAL AS c_1 FROM TPCR_Oracle_9i.CUSTOMER AS
g_0 WHERE (left(g_0.C_PHONE, 2) IN ('13', '31', '23',
'29', '30', '18', '17')) AND (g_0.C_ACCTBAL > (SELECT
AVG(g_1.C_ACCTBAL) FROM TPCR_Oracle_9i.CUSTOMER AS g_1 WHERE (g_1.C_ACCTBAL > 0E-15)
AND (left(g_1.C_PHONE, 2) IN ('13', '31', '23', '29',
'30', '18', '17')))) AND (NOT EXISTS (SELECT 1 FROM
TPCR_Oracle_9i.ORDERS AS g_2 WHERE g_2.O_CUSTKEY = g_0.C_CUSTKEY))) AS v_0 GROUP BY
v_0.c_0 ORDER BY c_0 NULLS FIRST"}, ComparisonMode.EXACT_COMMAND_STRING);
//$NON-NLS-1$
+ new String[] {"SELECT left(g_0.C_PHONE, 2) AS c_0, COUNT(*) AS c_1,
SUM(g_0.C_ACCTBAL) AS c_2 FROM TPCR_Oracle_9i.CUSTOMER AS g_0 WHERE (left(g_0.C_PHONE, 2)
IN ('13', '31', '23', '29', '30', '18',
'17')) AND (g_0.C_ACCTBAL > (SELECT AVG(g_1.C_ACCTBAL) FROM
TPCR_Oracle_9i.CUSTOMER AS g_1 WHERE (g_1.C_ACCTBAL > 0E-15) AND (left(g_1.C_PHONE, 2)
IN ('13', '31', '23', '29', '30', '18',
'17')))) AND (NOT EXISTS (SELECT 1 FROM TPCR_Oracle_9i.ORDERS AS g_2 WHERE
g_2.O_CUSTKEY = g_0.C_CUSTKEY)) GROUP BY left(g_0.C_PHONE, 2) ORDER BY c_0 NULLS
FIRST"}, ComparisonMode.EXACT_COMMAND_STRING); //$NON-NLS-1$
TestOptimizer.checkNodeTypes(plan, TestOptimizer.FULL_PUSHDOWN);
}