Author: shawkins
Date: 2010-05-18 16:54:34 -0400 (Tue, 18 May 2010)
New Revision: 2140
Added:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
Removed:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/NullFilter.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/DuplicateFilter.java
trunk/engine/src/test/java/org/teiid/common/log/
Modified:
trunk/engine/src/main/java/org/teiid/common/buffer/TupleSource.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Avg.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Count.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Max.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Min.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java
trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.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/ResolverVisitor.java
trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.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/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.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/datamgr/language/TestAggregateImpl.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
Log:
TEIID-171 adding support for xmlagg
Modified: trunk/engine/src/main/java/org/teiid/common/buffer/TupleSource.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/common/buffer/TupleSource.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/common/buffer/TupleSource.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -26,7 +26,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.sql.symbol.SingleElementSymbol;
+import org.teiid.query.sql.symbol.Expression;
/**
@@ -40,7 +40,7 @@
* Returns the List of ElementSymbol describing the Tuple Source
* @return the List of elements describing the Tuple Source
*/
- List<SingleElementSymbol> getSchema();
+ List<? extends Expression> getSchema();
/**
* Returns the next tuple
Modified:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,6 +22,8 @@
package org.teiid.query.function.aggregate;
+import java.util.List;
+
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
@@ -34,8 +36,13 @@
* being aggregated, then addInput() is called for every row in the group, then
* getResult() is called to retrieve the result.
*/
-public interface AggregateFunction {
+public abstract class AggregateFunction {
+ private int expressionIndex = -1;
+
+ public void setExpressionIndex(int expressionIndex) {
+ this.expressionIndex = expressionIndex;
+ }
/**
* Called to initialize the function. In the future this may expand
@@ -43,21 +50,36 @@
* @param dataType Data type of element begin aggregated
* @param inputType
*/
- public abstract void initialize(Class dataType, Class inputType);
+ public void initialize(Class<?> dataType, Class<?> inputType) {}
/**
* Called to reset the state of the function.
*/
public abstract void reset();
+ public void addInput(List<?> tuple) throws TeiidComponentException,
TeiidProcessingException {
+ if (expressionIndex == -1) {
+ addInputDirect(null, tuple);
+ return;
+ }
+ Object input = tuple.get(expressionIndex);
+ if (!filter(input)) {
+ addInputDirect(input, tuple);
+ }
+ }
+
+ boolean filter(Object value) {
+ return value == null;
+ }
+
/**
* Called for the element value in every row of a group.
* @param input Input value, may be null
+ * @param tuple
+ * @throws TeiidProcessingException
*/
- public abstract void addInput(Object input)
- throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException;
+ public abstract void addInputDirect(Object input, List<?> tuple) throws
TeiidComponentException, TeiidProcessingException;
-
/**
* Called after all values have been processed to get the result.
* @return Result value
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/Avg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/Avg.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Avg.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -23,6 +23,7 @@
package org.teiid.query.function.aggregate;
import java.math.BigDecimal;
+import java.util.List;
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
@@ -45,16 +46,9 @@
private int count = 0;
/**
- * Constructor for Avg.
- */
- public Avg() {
- super();
- }
-
- /**
* @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
*/
- public void initialize(Class dataType, Class inputType) {
+ public void initialize(Class<?> dataType, Class<?> inputType) {
if (dataType.equals(DataTypeManager.DefaultDataClasses.BIG_DECIMAL)) {
this.accumulatorType = BIG_DECIMAL;
} else {
@@ -68,12 +62,12 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object input)
+ public void addInputDirect(Object input, List<?> tuple)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
- super.addInput(input);
+ super.addInputDirect(input, tuple);
count++;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,6 +22,8 @@
package org.teiid.query.function.aggregate;
+import java.util.List;
+
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
@@ -29,31 +31,23 @@
/**
*/
-public class ConstantFunction implements AggregateFunction {
+public class ConstantFunction extends AggregateFunction {
private Object value;
- /**
- * Constructor for NoFunction.
- */
- public ConstantFunction() {
- super();
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- }
-
public void reset() {
this.value = null;
}
+
+ @Override
+ boolean filter(Object input) {
+ return false;
+ }
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object input)
+ public void addInputDirect(Object input, List<?> tuple)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
value = input;
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/Count.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/Count.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Count.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,34 +22,23 @@
package org.teiid.query.function.aggregate;
+import java.util.List;
+
/**
* Just a simple COUNT() implementation that counts every non-null row it sees.
*/
-public class Count implements AggregateFunction {
+public class Count extends AggregateFunction {
private int count = 0;
- /**
- * Constructor for Count.
- */
- public Count() {
- super();
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- }
-
public void reset() {
count = 0;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object input) {
+ public void addInputDirect(Object input, List<?> tuple) {
count++;
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/Max.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/Max.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Max.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,6 +22,8 @@
package org.teiid.query.function.aggregate;
+import java.util.List;
+
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
@@ -31,31 +33,18 @@
/**
*/
-public class Max implements AggregateFunction {
+public class Max extends AggregateFunction {
private Object maxValue;
- /**
- * Constructor for Min.
- */
- public Max() {
- super();
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- }
-
public void reset() {
maxValue = null;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object value)
+ public void addInputDirect(Object value, List<?> tuple)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if(maxValue == null) {
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/Min.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/Min.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Min.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,6 +22,8 @@
package org.teiid.query.function.aggregate;
+import java.util.List;
+
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
@@ -31,31 +33,18 @@
/**
*/
-public class Min implements AggregateFunction {
+public class Min extends AggregateFunction {
private Object minValue;
- /**
- * Constructor for Min.
- */
- public Min() {
- super();
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- }
-
public void reset() {
minValue = null;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object value)
+ public void addInputDirect(Object value, List<?> tuple)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if(minValue == null) {
Deleted: trunk/engine/src/main/java/org/teiid/query/function/aggregate/NullFilter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/NullFilter.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/NullFilter.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -1,84 +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.query.function.aggregate;
-
-import org.teiid.api.exception.query.ExpressionEvaluationException;
-import org.teiid.api.exception.query.FunctionExecutionException;
-import org.teiid.core.TeiidComponentException;
-import org.teiid.core.TeiidProcessingException;
-
-
-
-/**
- */
-public class NullFilter implements AggregateFunction {
-
- private AggregateFunction proxy;
-
- /**
- * Constructor for NullFilter.
- */
- public NullFilter(AggregateFunction proxy) {
- super();
-
- this.proxy = proxy;
- }
-
- public AggregateFunction getProxy() {
- return proxy;
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- this.proxy.initialize(dataType, inputType);
- }
-
- public void reset() {
- this.proxy.reset();
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
- */
- public void addInput(Object input)
- throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
-
- if(input != null) {
- this.proxy.addInput(input);
- }
- }
-
- /**
- * @throws TeiidProcessingException
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
- */
- public Object getResult()
- throws TeiidComponentException, TeiidProcessingException {
-
- return this.proxy.getResult();
- }
-
-
-}
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -24,6 +24,7 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.List;
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
@@ -36,7 +37,7 @@
* of a column. The type of the result varies depending on the type
* of the input {@see AggregateSymbol}
*/
-public class Sum implements AggregateFunction {
+public class Sum extends AggregateFunction {
// Various possible accumulators, depending on type
protected static final int LONG = 0;
@@ -49,12 +50,6 @@
private Object sum = null;
/**
- * Constructor for Sum.
- */
- public Sum() {
- }
-
- /**
* Allows subclasses to determine type of accumulator for the SUM.
* @return Type, as defined in constants
*/
@@ -65,7 +60,7 @@
/**
* @see org.teiid.query.function.aggregate.AggregateFunction#initialize(boolean,
String)
*/
- public void initialize(Class dataType, Class inputType) {
+ public void initialize(Class<?> dataType, Class<?> inputType) {
if(dataType.equals(DataTypeManager.DefaultDataClasses.LONG)) {
this.accumulatorType = LONG;
@@ -87,9 +82,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
*/
- public void addInput(Object input)
+ public void addInputDirect(Object input, List<?> tuple)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if (this.sum == null) {
Added: trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
(rev 0)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -0,0 +1,65 @@
+/*
+ * 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.function.aggregate;
+
+import java.util.List;
+
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.core.types.XMLType;
+import org.teiid.query.function.source.XMLSystemFunctions;
+import org.teiid.query.util.CommandContext;
+
+/**
+ * Aggregates XML entries
+ */
+public class XMLAgg extends AggregateFunction {
+
+ private XMLType result;
+ private CommandContext context;
+
+ public XMLAgg(CommandContext context) {
+ this.context = context;
+ }
+
+ public void reset() {
+ result = null;
+ }
+
+ /**
+ * @throws TeiidProcessingException
+ * @throws TeiidComponentException
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(Object,
List)
+ */
+ public void addInputDirect(Object input, List<?> tuple) throws
TeiidComponentException, TeiidProcessingException {
+ result = XMLSystemFunctions.xmlConcat(context, result, input);
+ }
+
+ /**
+ * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ */
+ public Object getResult() {
+ return result;
+ }
+
+}
Property changes on:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/parser/SQLParserUtil.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -248,6 +248,9 @@
} else if(functionType.equals(SQLReservedWords.MAX)) {
int num = info.anonMaxCount++;
return "max" + (num == 0 ? "" :
""+num);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } else if(functionType.equals(SQLReservedWords.XMLAGG)) {
+ int num = info.anonMaxCount++;
+ return "xmlagg" + (num == 0 ? "" :
""+num);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
} else {
Object[] params = new Object[] { functionType };
throw new
ParseException(QueryPlugin.Util.getString("SQLParser.Unknown_agg_func",
params)); //$NON-NLS-1$
Deleted:
trunk/engine/src/main/java/org/teiid/query/processor/relational/DuplicateFilter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/DuplicateFilter.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/DuplicateFilter.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -1,154 +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.query.processor.relational;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.teiid.api.exception.query.ExpressionEvaluationException;
-import org.teiid.api.exception.query.FunctionExecutionException;
-import org.teiid.common.buffer.BufferManager;
-import org.teiid.common.buffer.TupleBuffer;
-import org.teiid.common.buffer.TupleSource;
-import org.teiid.common.buffer.BufferManager.TupleSourceType;
-import org.teiid.core.TeiidComponentException;
-import org.teiid.core.TeiidProcessingException;
-import org.teiid.query.function.aggregate.AggregateFunction;
-import org.teiid.query.processor.relational.SortUtility.Mode;
-import org.teiid.query.sql.lang.OrderBy;
-import org.teiid.query.sql.symbol.ElementSymbol;
-
-
-/**
- */
-public class DuplicateFilter implements AggregateFunction {
-
- // Initial setup - can be reused
- private AggregateFunction proxy;
- private BufferManager mgr;
- private String groupName;
-
- // Derived and static - can be reused
- private List elements;
- private List sortTypes;
-
- // Temporary state - should be reset
- private TupleBuffer collectionBuffer;
- private SortUtility sortUtility;
-
- /**
- * Constructor for DuplicateFilter.
- */
- public DuplicateFilter(AggregateFunction proxy, BufferManager mgr, String groupName)
{
- super();
-
- this.proxy = proxy;
- this.mgr = mgr;
- this.groupName = groupName;
- }
-
- public List getElements() {
- return elements;
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
- */
- public void initialize(Class dataType, Class inputType) {
- this.proxy.initialize(dataType, inputType);
- // Set up schema
- ElementSymbol element = new ElementSymbol("val"); //$NON-NLS-1$
- element.setType(inputType);
- elements = new ArrayList();
- elements.add(element);
-
- sortTypes = new ArrayList();
- sortTypes.add(Boolean.valueOf(OrderBy.ASC));
- }
-
- public void reset() {
- this.proxy.reset();
- close();
- }
-
- private void close() {
- if (this.collectionBuffer != null) {
- collectionBuffer.remove();
- }
- this.collectionBuffer = null;
- this.sortUtility = null;
- }
-
- /**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInput(Object)
- */
- public void addInput(Object input)
- throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
-
- if(collectionBuffer == null) {
- collectionBuffer = mgr.createTupleBuffer(elements, groupName,
TupleSourceType.PROCESSOR);
- collectionBuffer.setForwardOnly(true);
- }
-
- List row = new ArrayList(1);
- row.add(input);
- this.collectionBuffer.addTuple(row);
- }
-
- /**
- * @throws TeiidProcessingException
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
- */
- public Object getResult()
- throws TeiidComponentException, TeiidProcessingException {
-
- if(collectionBuffer != null) {
- this.collectionBuffer.close();
-
- // Sort
- if (sortUtility == null) {
- sortUtility = new SortUtility(collectionBuffer.createIndexedTupleSource(),
elements, sortTypes, Mode.DUP_REMOVE_SORT, mgr, groupName);
- }
- TupleBuffer sorted = sortUtility.sort();
- sorted.setForwardOnly(true);
- try {
- // Add all input to proxy
- TupleSource sortedSource = sorted.createIndexedTupleSource();
- while(true) {
- List tuple = sortedSource.nextTuple();
- if(tuple == null) {
- break;
- }
- this.proxy.addInput(tuple.get(0));
- }
- } finally {
- sorted.remove();
- }
-
- close();
- }
-
- // Return
- return this.proxy.getResult();
- }
-}
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 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -28,9 +28,9 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
-import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.client.plan.PlanNode;
import org.teiid.common.buffer.BlockedException;
import org.teiid.common.buffer.BufferManager;
@@ -47,12 +47,14 @@
import org.teiid.query.function.aggregate.Count;
import org.teiid.query.function.aggregate.Max;
import org.teiid.query.function.aggregate.Min;
-import org.teiid.query.function.aggregate.NullFilter;
import org.teiid.query.function.aggregate.Sum;
+import org.teiid.query.function.aggregate.XMLAgg;
import org.teiid.query.processor.ProcessorDataManager;
import org.teiid.query.processor.relational.SortUtility.Mode;
import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.lang.OrderByItem;
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.util.CommandContext;
@@ -68,7 +70,7 @@
// Collection phase
private int phase = COLLECTION;
private Map elementMap; // Map of incoming symbol to index in
source elements
- private List collectedExpressions; // Collected Expressions
+ private List<Expression> collectedExpressions; // Collected
Expressions
// Sort phase
private SortUtility sortUtility;
@@ -77,7 +79,6 @@
// Group phase
private AggregateFunction[] functions;
- private int[] aggProjectionIndexes;
private List lastRow;
private List currentGroupTuple;
@@ -140,33 +141,28 @@
// List should contain all grouping columns / expressions as we need those for
sorting
if(this.sortElements != null) {
- this.collectedExpressions = new ArrayList(this.sortElements.size() +
getElements().size());
+ this.collectedExpressions = new
ArrayList<Expression>(this.sortElements.size() + getElements().size());
this.collectedExpressions.addAll(sortElements);
} else {
- this.collectedExpressions = new ArrayList(getElements().size());
+ this.collectedExpressions = new
ArrayList<Expression>(getElements().size());
}
// Construct aggregate function state accumulators
functions = new AggregateFunction[getElements().size()];
- aggProjectionIndexes = new int[getElements().size()];
- Arrays.fill(aggProjectionIndexes, -1);
for(int i=0; i<getElements().size(); i++) {
SingleElementSymbol symbol = (SingleElementSymbol)getElements().get(i);
Class<?> outputType = symbol.getType();
Class<?> inputType = symbol.getType();
if(symbol instanceof AggregateSymbol) {
AggregateSymbol aggSymbol = (AggregateSymbol) symbol;
-
+
if(aggSymbol.getExpression() == null) {
functions[i] = new Count();
} else {
- int index =
this.collectedExpressions.indexOf(aggSymbol.getExpression());
- if(index == -1) {
- index = this.collectedExpressions.size();
- this.collectedExpressions.add(aggSymbol.getExpression());
- }
- aggProjectionIndexes[i] = index;
- String function = aggSymbol.getAggregateFunction();
+ Expression ex = aggSymbol.getExpression();
+ inputType = ex.getType();
+ int index = collectExpression(ex);
+ String function = aggSymbol.getAggregateFunction();
if(function.equals(SQLReservedWords.COUNT)) {
functions[i] = new Count();
} else if(function.equals(SQLReservedWords.SUM)) {
@@ -175,24 +171,59 @@
functions[i] = new Avg();
} else if(function.equals(SQLReservedWords.MIN)) {
functions[i] = new Min();
+ } else if (function.equals(SQLReservedWords.MAX)){
+ functions[i] = new Max();
} else {
- functions[i] = new Max();
+ functions[i] = new XMLAgg(context);
}
if(aggSymbol.isDistinct() &&
!function.equals(SQLReservedWords.MIN) && !function.equals(SQLReservedWords.MAX))
{
- functions[i] = new DuplicateFilter(functions[i],
getBufferManager(), getConnectionID());
- }
-
- functions[i] = new NullFilter(functions[i]);
- inputType = aggSymbol.getExpression().getType();
+ SortingFilter filter = new SortingFilter(functions[i],
getBufferManager(), getConnectionID(), true);
+ ElementSymbol element = new ElementSymbol("val");
//$NON-NLS-1$
+ element.setType(inputType);
+ filter.setElements(Arrays.asList(element));
+ filter.setSortElements(filter.getElements());
+ functions[i] = filter;
+ } else if (aggSymbol.getOrderBy() != null) { //handle the xmlagg
case
+ int[] orderIndecies = new
int[aggSymbol.getOrderBy().getOrderByItems().size()];
+ List<Boolean> aggSortTypes = new
ArrayList<Boolean>(orderIndecies.length);
+ List<ElementSymbol> schema = new
ArrayList<ElementSymbol>(orderIndecies.length + 1);
+ ElementSymbol element = new ElementSymbol("val");
//$NON-NLS-1$
+ element.setType(inputType);
+ schema.add(element);
+ for (ListIterator<OrderByItem> iterator =
aggSymbol.getOrderBy().getOrderByItems().listIterator(); iterator.hasNext();) {
+ OrderByItem item = iterator.next();
+ orderIndecies[iterator.previousIndex()] =
collectExpression(item.getSymbol());
+ aggSortTypes.add(item.isAscending());
+ element = new
ElementSymbol(String.valueOf(iterator.previousIndex()));
+ element.setType(inputType);
+ schema.add(element);
+ }
+ SortingFilter filter = new SortingFilter(functions[i],
getBufferManager(), getConnectionID(), false);
+ filter.setSortTypes(aggSortTypes);
+ filter.setIndecies(orderIndecies);
+ filter.setElements(schema);
+ filter.setSortElements(schema.subList(1, schema.size()));
+ functions[i] = filter;
+ }
+ functions[i].setExpressionIndex(index);
}
} else {
functions[i] = new ConstantFunction();
- aggProjectionIndexes[i] = this.collectedExpressions.indexOf(symbol);
+
functions[i].setExpressionIndex(this.collectedExpressions.indexOf(symbol));
}
functions[i].initialize(outputType, inputType);
}
- }
+ }
+
+ private int collectExpression(Expression ex) {
+ int index = this.collectedExpressions.indexOf(ex);
+ if(index == -1) {
+ index = this.collectedExpressions.size();
+ this.collectedExpressions.add(ex);
+ }
+ return index;
+ }
AggregateFunction[] getFunctions() {
return functions;
@@ -246,7 +277,7 @@
for(int col = 0; col<columns; col++) {
// The following call may throw BlockedException, but all state to
this point
// is saved in class variables so we can start over on building
this tuple
- Object value = new Evaluator(elementMap, getDataManager(),
getContext()).evaluate((Expression) collectedExpressions.get(col), tuple);
+ Object value = new Evaluator(elementMap, getDataManager(),
getContext()).evaluate((Expression)collectedExpressions.get(col), tuple);
exprTuple.add(value);
}
sourceRow++;
@@ -263,7 +294,7 @@
}
@Override
- public List<SingleElementSymbol> getSchema() {
+ public List<Expression> getSchema() {
return collectedExpressions;
}
@@ -382,14 +413,10 @@
}
private void updateAggregates(List tuple)
- throws TeiidComponentException, ExpressionEvaluationException {
+ throws TeiidComponentException, TeiidProcessingException {
for(int i=0; i<functions.length; i++) {
- Object value = null;
- if(aggProjectionIndexes[i] != -1) {
- value = tuple.get(aggProjectionIndexes[i]);
- }
- functions[i].addInput(value);
+ functions[i].addInput(tuple);
}
}
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 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortUtility.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -42,6 +42,7 @@
import org.teiid.logging.LogManager;
import org.teiid.logging.MessageLevel;
import org.teiid.query.sql.lang.OrderBy;
+import org.teiid.query.sql.symbol.Expression;
import org.teiid.query.sql.symbol.SingleElementSymbol;
@@ -87,7 +88,7 @@
private Mode mode;
private BufferManager bufferManager;
private String groupName;
- private List<SingleElementSymbol> schema;
+ private List<? extends Expression> schema;
private int schemaSize;
private ListNestedSortComparator comparator;
@@ -120,7 +121,7 @@
sortTypes = Collections.nCopies(sortElements.size(), OrderBy.ASC);
} else if (sortElements.size() < schema.size()) {
sortElements = new ArrayList(sortElements);
- List<SingleElementSymbol> toAdd = new
ArrayList<SingleElementSymbol>(schema);
+ List<Expression> toAdd = new ArrayList<Expression>(schema);
toAdd.removeAll(sortElements);
sortElements.addAll(toAdd);
sortTypes = new ArrayList<Boolean>(sortTypes);
Copied: trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
(from rev 2137,
trunk/engine/src/main/java/org/teiid/query/processor/relational/DuplicateFilter.java)
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
(rev 0)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -0,0 +1,165 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA.
+ */
+
+package org.teiid.query.processor.relational;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.FunctionExecutionException;
+import org.teiid.common.buffer.BufferManager;
+import org.teiid.common.buffer.TupleBuffer;
+import org.teiid.common.buffer.TupleSource;
+import org.teiid.common.buffer.BufferManager.TupleSourceType;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.function.aggregate.AggregateFunction;
+import org.teiid.query.processor.relational.SortUtility.Mode;
+
+/**
+ */
+public class SortingFilter extends AggregateFunction {
+
+ private static final int[] NO_INDECIES = new int[0];
+ // Initial setup - can be reused
+ private AggregateFunction proxy;
+ private BufferManager mgr;
+ private String groupName;
+ private boolean removeDuplicates;
+
+ // Derived and static - can be reused
+ private List elements;
+ private List sortTypes;
+ private List sortElements;
+
+ private int[] indecies = NO_INDECIES;
+
+ // Temporary state - should be reset
+ private TupleBuffer collectionBuffer;
+ private SortUtility sortUtility;
+
+ /**
+ * Constructor for DuplicateFilter.
+ */
+ public SortingFilter(AggregateFunction proxy, BufferManager mgr, String groupName,
boolean removeDuplicates) {
+ super();
+
+ this.proxy = proxy;
+ this.mgr = mgr;
+ this.groupName = groupName;
+ this.removeDuplicates = removeDuplicates;
+ }
+
+ public List getElements() {
+ return elements;
+ }
+
+ public void setElements(List elements) {
+ this.elements = elements;
+ }
+
+ public void setSortTypes(List sortTypes) {
+ this.sortTypes = sortTypes;
+ }
+
+ public void setIndecies(int[] indecies) {
+ this.indecies = indecies;
+ }
+
+ public void setSortElements(List sortElements) {
+ this.sortElements = sortElements;
+ }
+
+ /**
+ * @see org.teiid.query.function.aggregate.AggregateFunction#initialize(String,
Class)
+ */
+ public void initialize(Class<?> dataType, Class<?> inputType) {
+ this.proxy.initialize(dataType, inputType);
+ }
+
+ public void reset() {
+ this.proxy.reset();
+ close();
+ }
+
+ private void close() {
+ if (this.collectionBuffer != null) {
+ collectionBuffer.remove();
+ }
+ this.collectionBuffer = null;
+ this.sortUtility = null;
+ }
+
+ @Override
+ public void addInputDirect(Object input, List<?> tuple)
+ throws FunctionExecutionException, ExpressionEvaluationException,
+ TeiidComponentException, TeiidProcessingException {
+ if(collectionBuffer == null) {
+ collectionBuffer = mgr.createTupleBuffer(elements, groupName,
TupleSourceType.PROCESSOR);
+ collectionBuffer.setForwardOnly(true);
+ }
+ List<Object> row = new ArrayList<Object>(1 + indecies.length);
+ row.add(input);
+ for (int i = 0; i < indecies.length; i++) {
+ row.add(tuple.get(indecies[i]));
+ }
+ this.collectionBuffer.addTuple(row);
+ }
+
+ /**
+ * @throws TeiidProcessingException
+ * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ */
+ public Object getResult()
+ throws TeiidComponentException, TeiidProcessingException {
+
+ if(collectionBuffer != null) {
+ this.collectionBuffer.close();
+
+ // Sort
+ if (sortUtility == null) {
+ sortUtility = new SortUtility(collectionBuffer.createIndexedTupleSource(),
sortElements, sortTypes, removeDuplicates?Mode.DUP_REMOVE_SORT:Mode.SORT, mgr,
groupName);
+ }
+ TupleBuffer sorted = sortUtility.sort();
+ sorted.setForwardOnly(true);
+ try {
+ // Add all input to proxy
+ TupleSource sortedSource = sorted.createIndexedTupleSource();
+ while(true) {
+ List tuple = sortedSource.nextTuple();
+ if(tuple == null) {
+ break;
+ }
+ this.proxy.addInputDirect(tuple.get(0), null);
+ }
+ } finally {
+ sorted.remove();
+ }
+
+ close();
+ }
+
+ // Return
+ return this.proxy.getResult();
+ }
+}
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 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -627,13 +627,11 @@
if (! type.equals(DataTypeManager.DefaultDataTypes.STRING) &&
! type.equals(DataTypeManager.DefaultDataTypes.CLOB)) {
- if(!(expr instanceof AggregateSymbol) &&
- ResolverUtil.canImplicitlyConvert(type,
DataTypeManager.DefaultDataTypes.STRING)) {
+ if(ResolverUtil.canImplicitlyConvert(type,
DataTypeManager.DefaultDataTypes.STRING)) {
result = ResolverUtil.convertExpression(expr, type,
DataTypeManager.DefaultDataTypes.STRING, metadata);
- } else if (!(expr instanceof AggregateSymbol) &&
- ResolverUtil.canImplicitlyConvert(type,
DataTypeManager.DefaultDataTypes.CLOB)){
+ } else if (ResolverUtil.canImplicitlyConvert(type,
DataTypeManager.DefaultDataTypes.CLOB)){
result = ResolverUtil.convertExpression(expr, type,
DataTypeManager.DefaultDataTypes.CLOB, metadata);
@@ -666,9 +664,6 @@
Expression value = (Expression) valIter.next();
setDesiredType(value, exprType, scrit);
if(! value.getType().equals(exprType)) {
- if(value instanceof AggregateSymbol) {
- throw new QueryResolverException(ErrorMessageKeys.RESOLVER_0031,
QueryPlugin.Util.getString(ErrorMessageKeys.RESOLVER_0031, scrit));
- }
// try to apply cast
String valTypeName = DataTypeManager.getDataTypeName(value.getType());
if(ResolverUtil.canImplicitlyConvert(valTypeName, exprTypeName)) {
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -759,7 +759,7 @@
* @param query
* @throws TeiidComponentException, MetaMatrixProcessingException
*/
- public QueryCommand rewriteOrderBy(QueryCommand queryCommand) throws
TeiidComponentException, TeiidProcessingException{
+ public QueryCommand rewriteOrderBy(QueryCommand queryCommand) throws
TeiidComponentException {
final OrderBy orderBy = queryCommand.getOrderBy();
if (orderBy == null) {
return queryCommand;
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 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/sql/navigator/PreOrPostOrderNavigator.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -132,6 +132,7 @@
public void visit(AggregateSymbol obj) {
preVisitVisitor(obj);
visitNode(obj.getExpression());
+ visitNode(obj.getOrderBy());
postVisitVisitor(obj);
}
public void visit(AliasSymbol obj) {
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 2010-05-18
17:06:12 UTC (rev 2139)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -33,6 +33,7 @@
import org.teiid.language.SQLReservedWords;
import org.teiid.query.QueryPlugin;
import org.teiid.query.sql.LanguageVisitor;
+import org.teiid.query.sql.lang.OrderBy;
import org.teiid.query.util.ErrorMessageKeys;
@@ -59,21 +60,23 @@
private String aggregate;
private boolean distinct;
+ private OrderBy orderBy;
- private static final Class COUNT_TYPE =
DataTypeManager.getDataTypeClass(DataTypeManager.DefaultDataTypes.INTEGER);
- private static final Set AGGREGATE_FUNCTIONS;
- private static final Map SUM_TYPES;
- private static final Map AVG_TYPES;
+ private static final Class<Integer> COUNT_TYPE =
DataTypeManager.DefaultDataClasses.INTEGER;
+ private static final Set<String> AGGREGATE_FUNCTIONS;
+ private static final Map<Class<?>, Class<?>> SUM_TYPES;
+ private static final Map<Class<?>, Class<?>> AVG_TYPES;
static {
- AGGREGATE_FUNCTIONS = new HashSet();
+ AGGREGATE_FUNCTIONS = new HashSet<String>();
AGGREGATE_FUNCTIONS.add(SQLReservedWords.COUNT);
AGGREGATE_FUNCTIONS.add(SQLReservedWords.SUM);
AGGREGATE_FUNCTIONS.add(SQLReservedWords.AVG);
AGGREGATE_FUNCTIONS.add(SQLReservedWords.MIN);
AGGREGATE_FUNCTIONS.add(SQLReservedWords.MAX);
+ AGGREGATE_FUNCTIONS.add(SQLReservedWords.XMLAGG);
- SUM_TYPES = new HashMap();
+ SUM_TYPES = new HashMap<Class<?>, Class<?>>();
SUM_TYPES.put(DataTypeManager.DefaultDataClasses.BYTE,
DataTypeManager.DefaultDataClasses.LONG);
SUM_TYPES.put(DataTypeManager.DefaultDataClasses.SHORT,
DataTypeManager.DefaultDataClasses.LONG);
SUM_TYPES.put(DataTypeManager.DefaultDataClasses.INTEGER,
DataTypeManager.DefaultDataClasses.LONG);
@@ -83,7 +86,7 @@
SUM_TYPES.put(DataTypeManager.DefaultDataClasses.DOUBLE,
DataTypeManager.DefaultDataClasses.DOUBLE);
SUM_TYPES.put(DataTypeManager.DefaultDataClasses.BIG_DECIMAL,
DataTypeManager.DefaultDataClasses.BIG_DECIMAL);
- AVG_TYPES = new HashMap();
+ AVG_TYPES = new HashMap<Class<?>, Class<?>>();
AVG_TYPES.put(DataTypeManager.DefaultDataClasses.BYTE,
DataTypeManager.DefaultDataClasses.DOUBLE);
AVG_TYPES.put(DataTypeManager.DefaultDataClasses.SHORT,
DataTypeManager.DefaultDataClasses.DOUBLE);
AVG_TYPES.put(DataTypeManager.DefaultDataClasses.INTEGER,
DataTypeManager.DefaultDataClasses.DOUBLE);
@@ -167,15 +170,15 @@
* type of the contained expression
* @return Type of the symbol
*/
- public Class getType() {
+ public Class<?> getType() {
if(this.aggregate.equals(SQLReservedWords.COUNT)) {
return COUNT_TYPE;
} else if(this.aggregate.equals(SQLReservedWords.SUM) ) {
- Class expressionType = this.getExpression().getType();
- return (Class) SUM_TYPES.get(expressionType);
+ Class<?> expressionType = this.getExpression().getType();
+ return SUM_TYPES.get(expressionType);
} else if (this.aggregate.equals(SQLReservedWords.AVG)) {
- Class expressionType = this.getExpression().getType();
- return (Class) AVG_TYPES.get(expressionType);
+ Class<?> expressionType = this.getExpression().getType();
+ return AVG_TYPES.get(expressionType);
} else {
return this.getExpression().getType();
}
@@ -184,6 +187,14 @@
public void acceptVisitor(LanguageVisitor visitor) {
visitor.visit(this);
}
+
+ public OrderBy getOrderBy() {
+ return orderBy;
+ }
+
+ public void setOrderBy(OrderBy orderBy) {
+ this.orderBy = orderBy;
+ }
/**
* Return a deep copy of this object
@@ -195,7 +206,9 @@
} else {
copy = new AggregateSymbol(getName(), getCanonical(), getAggregateFunction(),
isDistinct(), null);
}
-
+ if (orderBy != null) {
+ copy.setOrderBy(orderBy.clone());
+ }
return copy;
}
@@ -219,7 +232,8 @@
return this.aggregate.equals(other.aggregate)
&& this.distinct == other.distinct
- && EquivalenceUtil.areEqual(this.getExpression(),
other.getExpression());
+ && EquivalenceUtil.areEqual(this.getExpression(),
other.getExpression())
+ && EquivalenceUtil.areEqual(this.getOrderBy(), other.getOrderBy());
}
}
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 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -1104,6 +1104,11 @@
} else {
parts.add(registerNode(obj.getExpression()));
}
+
+ if (obj.getOrderBy() != null) {
+ parts.add(SPACE);
+ parts.add(registerNode(obj.getOrderBy()));
+ }
parts.add(")"); //$NON-NLS-1$
}
Modified:
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/main/java/org/teiid/query/validator/AggregateValidationVisitor.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -74,6 +74,8 @@
String aggregateFunction = obj.getAggregateFunction();
if((aggregateFunction.equals(SQLReservedWords.SUM) ||
aggregateFunction.equals(SQLReservedWords.AVG)) && obj.getType() == null) {
handleValidationError(QueryPlugin.Util.getString(ErrorMessageKeys.VALIDATOR_0041, new
Object[] {aggregateFunction, obj}), obj);
+ } else if (aggregateFunction.equals(SQLReservedWords.XMLAGG) &&
obj.getType() != DataTypeManager.DefaultDataClasses.XML) {
+
handleValidationError(QueryPlugin.Util.getString("AggregateValidationVisitor.non_xml",
new Object[] {aggregateFunction, obj}), obj);
}
if((obj.isDistinct() || aggregateFunction.equals(SQLReservedWords.MIN) ||
aggregateFunction.equals(SQLReservedWords.MAX)) &&
DataTypeManager.isNonComparable(DataTypeManager.getDataTypeName(aggExp.getType()))) {
handleValidationError(QueryPlugin.Util.getString("AggregateValidationVisitor.non_comparable",
new Object[] {aggregateFunction, obj}), obj); //$NON-NLS-1$
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-05-18 17:06:12
UTC (rev 2139)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2010-05-18 20:54:34
UTC (rev 2140)
@@ -1688,6 +1688,7 @@
AggregateSymbol agg = null;
boolean isDistinct = false;
Expression expression = null;
+ OrderBy orderBy = null;
}
{
// Things that can be aliased
@@ -1704,13 +1705,23 @@
functionToken = <SUM> |
functionToken = <AVG> |
functionToken = <MIN> |
- functionToken = <MAX>
+ functionToken = <MAX>
)
<LPAREN>
[ <DISTINCT> {isDistinct=true;} ]
expression = expression(info)
<RPAREN>
- )
+ )
+ |
+ (
+ functionToken = <XMLAGG>
+ <LPAREN>
+ expression = expression(info)
+ [
+ orderBy = orderby(info)
+ ]
+ <RPAREN>
+ )
)
{
if(! info.aggregatesAllowed) {
@@ -1726,7 +1737,7 @@
// COUNT(*)
agg = new AggregateSymbol(name, func, false, null);
}
-
+ agg.setOrderBy(orderBy);
return agg;
}
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-05-18 17:06:12
UTC (rev 2139)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2010-05-18 20:54:34
UTC (rev 2140)
@@ -300,6 +300,7 @@
ERR.015.012.0040 = Aggregate expression has unknown data type: {0}
ERR.015.012.0041 = The aggregate function {0} cannot be used with non-numeric
expressions: {1}
AggregateValidationVisitor.non_comparable = The aggregate function {0} cannot be used
with non-comparable expressions: {1}
+AggregateValidationVisitor.non_xml = The XMLAGG aggregate function {0} requires an
expression of type XML: {1}
ERR.015.012.0042 = Cross join may not have criteria: {0}
ERR.015.012.0043 = Join must have criteria declared in the ON clause: {0}
ERR.015.012.0045 = Elements in this join criteria are not from a group involved in the
join: {0}
@@ -768,7 +769,7 @@
SystemSource.xpath_description=Evaluate the XPath expression against a document
SystemSource.xpath_param1=Source document
SystemSource.xpath_param2=XPath expression
-SystemSource.xpath_param2=Namespaces
+SystemSource.xpath_param3=Namespaces
SystemSource.xpathvalue_result=Single result
SystemSource.xpath_result=XPath result
SystemSource.xsltransform_description=Transform the document with the given stylesheet.
Modified:
trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/language/TestAggregateImpl.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/language/TestAggregateImpl.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/test/java/org/teiid/dqp/internal/datamgr/language/TestAggregateImpl.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -47,7 +47,7 @@
functionName,
distinct,
new Constant(new Integer(value)));
- return (AggregateFunction)TstLanguageBridgeFactory.factory.translate(symbol);
+ return TstLanguageBridgeFactory.factory.translate(symbol);
}
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-05-18 17:06:12
UTC (rev 2139)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2010-05-18 20:54:34
UTC (rev 2140)
@@ -37,6 +37,7 @@
import org.teiid.client.metadata.ParameterInfo;
import org.teiid.core.TeiidException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.language.SQLReservedWords;
import org.teiid.query.sql.lang.BetweenCriteria;
import org.teiid.query.sql.lang.Command;
import org.teiid.query.sql.lang.CompareCriteria;
@@ -6732,5 +6733,14 @@
f.setNamespaces(new XMLNamespaces(Arrays.asList(new XMLNamespaces.NamespaceItem(),
new XMLNamespaces.NamespaceItem("x", "http://foo"))));
helpTestExpression("xmlforest(xmlnamespaces(no default, 'http://foo' as
x), a as \"table\")", "XMLFOREST(XMLNAMESPACES(NO DEFAULT,
'http://foo' AS x), a AS \"table\")", f);
}
+
+ @Test public void testXmlAggWithOrderBy() throws Exception {
+ String sql = "SELECT xmlAgg(1 order by e2)"; //$NON-NLS-1$
+ AggregateSymbol as = new AggregateSymbol("foo",
SQLReservedWords.XMLAGG, false, new Constant(1));
+ as.setOrderBy(new OrderBy(Arrays.asList(new ElementSymbol("e2"))));
+ Query query = new Query();
+ query.setSelect(new Select(Arrays.asList(as)));
+ helpTest(sql, "SELECT XMLAGG(1 ORDER BY e2)", query);
+ }
}
Modified: trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/test/java/org/teiid/query/processor/TestSQLXMLProcessing.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -171,5 +171,35 @@
helpProcess(plan, dataManager, expected);
}
+
+ @Test public void testXmlAgg() {
+ String sql = "SELECT xmlelement(parent, xmlAgg(xmlelement(x,
xmlattributes(e1, e2)))) from pm1.g1"; //$NON-NLS-1$
+
+ List[] expected = new List[] {
+ Arrays.asList("<parent><x e1=\"a\"
e2=\"0\"></x><x e2=\"1\"></x><x
e1=\"a\" e2=\"3\"></x><x e1=\"c\"
e2=\"1\"></x><x e1=\"b\"
e2=\"2\"></x><x e1=\"a\"
e2=\"0\"></x></parent>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
+
+ @Test public void testXmlAggOrderBy() {
+ String sql = "SELECT xmlelement(parent, xmlAgg(xmlelement(x,
xmlattributes(e1, e2)) order by e2)) from pm1.g1"; //$NON-NLS-1$
+
+ List[] expected = new List[] {
+ Arrays.asList("<parent><x e1=\"a\"
e2=\"0\"></x><x e1=\"a\"
e2=\"0\"></x><x e2=\"1\"></x><x
e1=\"c\" e2=\"1\"></x><x e1=\"b\"
e2=\"2\"></x><x e1=\"a\"
e2=\"3\"></x></parent>"),
+ };
+
+ FakeDataManager dataManager = new FakeDataManager();
+ sampleData1(dataManager);
+
+ ProcessorPlan plan = helpGetPlan(helpParse(sql),
FakeMetadataFactory.example1Cached());
+
+ helpProcess(plan, dataManager, expected);
+ }
}
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -22,13 +22,16 @@
package org.teiid.query.processor.relational;
+import java.util.Arrays;
+
import org.teiid.common.buffer.BufferManager;
import org.teiid.common.buffer.BufferManagerFactory;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.function.aggregate.Count;
-import org.teiid.query.processor.relational.DuplicateFilter;
+import org.teiid.query.processor.relational.SortingFilter;
+import org.teiid.query.sql.symbol.ElementSymbol;
import junit.framework.TestCase;
@@ -48,13 +51,17 @@
public void helpTestDuplicateFilter(Object[] input, Class dataType, int expected)
throws TeiidComponentException, TeiidProcessingException {
BufferManager mgr = BufferManagerFactory.getStandaloneBufferManager();
- DuplicateFilter filter = new DuplicateFilter(new Count(), mgr, "test");
//$NON-NLS-1$
+ SortingFilter filter = new SortingFilter(new Count(), mgr, "test",
true); //$NON-NLS-1$
filter.initialize(dataType, dataType);
+ ElementSymbol element = new ElementSymbol("val"); //$NON-NLS-1$
+ element.setType(dataType);
+ filter.setElements(Arrays.asList(element));
+ filter.setSortElements(filter.getElements());
filter.reset();
// Add inputs
for(int i=0; i<input.length; i++) {
- filter.addInput(input[i]);
+ filter.addInputDirect(input[i], null);
}
Integer actual = (Integer) filter.getResult();
Modified:
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2010-05-18
17:06:12 UTC (rev 2139)
+++
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestGroupingNode.java 2010-05-18
20:54:34 UTC (rev 2140)
@@ -44,13 +44,9 @@
import org.teiid.query.function.FunctionDescriptor;
import org.teiid.query.function.SystemFunctionManager;
import org.teiid.query.function.aggregate.AggregateFunction;
-import org.teiid.query.function.aggregate.NullFilter;
import org.teiid.query.processor.FakeDataManager;
import org.teiid.query.processor.FakeTupleSource;
import org.teiid.query.processor.ProcessorDataManager;
-import org.teiid.query.processor.relational.DuplicateFilter;
-import org.teiid.query.processor.relational.GroupingNode;
-import org.teiid.query.processor.relational.RelationalNode;
import org.teiid.query.sql.symbol.AggregateSymbol;
import org.teiid.query.sql.symbol.Constant;
import org.teiid.query.sql.symbol.ElementSymbol;
@@ -177,7 +173,7 @@
//ensure that the distinct input type is correct
AggregateFunction[] functions = node.getFunctions();
AggregateFunction countDist = functions[5];
- DuplicateFilter dup = (DuplicateFilter)((NullFilter)countDist).getProxy();
+ SortingFilter dup = (SortingFilter)countDist;
assertEquals(DataTypeManager.DefaultDataClasses.INTEGER,
((ElementSymbol)dup.getElements().get(0)).getType());
}