Author: shawkins
Date: 2012-04-04 15:54:58 -0400 (Wed, 04 Apr 2012)
New Revision: 3973
Added:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/UserDefined.java
Modified:
trunk/api/src/main/java/org/teiid/UserDefinedAggregate.java
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java
trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.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/RankingFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/SingleArgumentAggregateFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/StatsFunction.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/TextAgg.java
trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.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/lang/Query.java
trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
trunk/engine/src/main/resources/org/teiid/query/i18n.properties
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java
trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java
Log:
TEIID-1560 adding parsing/validation/processing logic for aggregates. more to come
Modified: trunk/api/src/main/java/org/teiid/UserDefinedAggregate.java
===================================================================
--- trunk/api/src/main/java/org/teiid/UserDefinedAggregate.java 2012-04-04 19:49:28 UTC
(rev 3972)
+++ trunk/api/src/main/java/org/teiid/UserDefinedAggregate.java 2012-04-04 19:54:58 UTC
(rev 3973)
@@ -27,8 +27,16 @@
* @param <T>
*/
public interface UserDefinedAggregate<T> {
-
- void init(CommandContext commandContext);
- T getResult();
+ /**
+ * Called when state from the current partition can be forgotten
+ */
+ void reset();
+ /**
+ * Called to get the current value. May be called multiple times in the same
+ * partition for windowed aggregates.
+ * @param commandContext
+ * @return
+ */
+ T getResult(CommandContext commandContext);
}
Modified:
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/dqp/internal/datamgr/ExecutionContextImpl.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -33,6 +33,7 @@
import org.teiid.adminapi.Session;
import org.teiid.common.buffer.BufferManager;
+import org.teiid.core.util.EquivalenceUtil;
import org.teiid.core.util.HashCodeUtil;
import org.teiid.dqp.internal.process.RequestWorkItem;
import org.teiid.dqp.message.RequestID;
@@ -145,23 +146,10 @@
return false;
}
ExecutionContext other = (ExecutionContext) obj;
- return compareWithNull(this.getRequestId(), other.getRequestId()) &&
- compareWithNull(this.getPartIdentifier(), other.getPartIdentifier());
+ return EquivalenceUtil.areEqual(this.getRequestId(), other.getRequestId())
&&
+ EquivalenceUtil.areEqual(this.getPartIdentifier(), other.getPartIdentifier());
}
- private boolean compareWithNull(Object obj1, Object obj2) {
- if(obj1 == null) {
- if(obj2 == null) {
- return true;
- }
- return false;
- }
- if(obj2 == null) {
- return false;
- }
- return obj1.equals(obj2);
- }
-
public int hashCode() {
return HashCodeUtil.hashCode(HashCodeUtil.hashCode(0, getRequestId()), partID);
}
Modified: trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-04-04 19:49:28 UTC
(rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/QueryPlugin.java 2012-04-04 19:54:58 UTC
(rev 3973)
@@ -612,7 +612,7 @@
TEIID30581,
TEIID30590,
TEIID30591,
- TEIID30600, TEIID30601, //User defined aggregate errors
+ TEIID30600, TEIID30601, TEIID30602, //User defined aggregate errors
TEIID31069,
TEIID31070,
Modified: trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-04-04 19:49:28 UTC
(rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/eval/Evaluator.java 2012-04-04 19:54:58 UTC
(rev 3973)
@@ -59,8 +59,6 @@
import org.teiid.core.types.basic.StringToSQLXMLTransform;
import org.teiid.core.util.EquivalenceUtil;
import org.teiid.language.Like.MatchMode;
-import org.teiid.metadata.FunctionMethod.Determinism;
-import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionDescriptor;
import org.teiid.query.function.FunctionLibrary;
@@ -970,11 +968,8 @@
values[i+start] = internalEvaluate(args[i], tuple);
}
- // Check for function we can't evaluate
- if(fd.getPushdown() == PushDown.MUST_PUSHDOWN) {
- throw new TeiidComponentException(QueryPlugin.Event.TEIID30341,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, fd.getName()));
- }
-
+ fd.checkNotPushdown();
+
// Check for special lookup function
if(fd.getName().equalsIgnoreCase(FunctionLibrary.LOOKUP)) {
if(dataMgr == null) {
@@ -993,13 +988,7 @@
}
// Execute function
- Object result = fd.invokeFunction(values);
-
- if (context != null && fd.getDeterministic().ordinal() <=
Determinism.USER_DETERMINISTIC.ordinal()) {
- context.setDeterminismLevel(fd.getDeterministic());
- }
-
- return result;
+ return fd.invokeFunction(values, context, null);
}
private Object evaluate(ScalarSubquery scalarSubquery, List<?> tuple)
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionDescriptor.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -37,6 +37,7 @@
import org.teiid.metadata.FunctionMethod.Determinism;
import org.teiid.metadata.FunctionMethod.PushDown;
import org.teiid.query.QueryPlugin;
+import org.teiid.query.util.CommandContext;
/**
@@ -74,6 +75,16 @@
this.method = method;
}
+ public Object newInstance() {
+ try {
+ return invocationMethod.getDeclaringClass().newInstance();
+ } catch (InstantiationException e) {
+ throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30602,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30602, method.getName(),
method.getInvocationClass()));
+ } catch (IllegalAccessException e) {
+ throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30602,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30602, method.getName(),
method.getInvocationClass()));
+ }
+ }
+
public void setHasWrappedArgs(boolean hasWrappedArgs) {
this.hasWrappedArgs = hasWrappedArgs;
}
@@ -165,17 +176,25 @@
public void setMetadataID(Object metadataID) {
this.metadataID = metadataID;
}
+
+ public void checkNotPushdown() throws FunctionExecutionException {
+ // Check for function we can't evaluate
+ if(getPushdown() == PushDown.MUST_PUSHDOWN) {
+ throw new FunctionExecutionException(QueryPlugin.Event.TEIID30341,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30341, getName()));
+ }
+ }
/**
* Invoke the function described in the function descriptor, using the
* values provided. Return the result of the function.
- * @param fd Function descriptor describing the name and types of the arguments
* @param values Values that should match 1-to-1 with the types described in the
* function descriptor
+ * @param context
+ * @param functionTarget TODO
+ * @param fd Function descriptor describing the name and types of the arguments
* @return Result of invoking the function
*/
- public Object invokeFunction(Object[] values) throws FunctionExecutionException {
-
+ public Object invokeFunction(Object[] values, CommandContext context, Object
functionTarget) throws FunctionExecutionException {
if (!isNullDependent()) {
for (int i = requiresContext?1:0; i < values.length; i++) {
if (values[i] == null) {
@@ -206,7 +225,10 @@
newValues[i - 1] = Arrays.copyOfRange(values, i - 1, values.length);
values = newValues;
}
- Object result = invocationMethod.invoke(null, values);
+ Object result = invocationMethod.invoke(functionTarget, values);
+ if (context != null && getDeterministic().ordinal() <=
Determinism.USER_DETERMINISTIC.ordinal()) {
+ context.setDeterminismLevel(getDeterministic());
+ }
return importValue(result, getReturnType());
} catch(ArithmeticException e) {
throw new FunctionExecutionException(QueryPlugin.Event.TEIID30383, e,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30383, getName()));
Modified: trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/FunctionTree.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -327,7 +327,7 @@
if (invocationMethod != null) {
// Check return type is non void
Class<?> methodReturn = invocationMethod.getReturnType();
- if(methodReturn.equals(Void.TYPE)) {
+ if(method.getAggregateAttributes() == null &&
methodReturn.equals(Void.TYPE)) {
throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30390,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30390, method.getName(), invocationMethod));
}
@@ -347,12 +347,15 @@
}
if (method.getAggregateAttributes() != null &&
!(UserDefinedAggregate.class.isAssignableFrom(method.getClass()))) {
- throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30601,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30601, method.getName(),
method.getInvocationClass(), UserDefinedAggregate.class.getName()));
+ throw new TeiidRuntimeException(QueryPlugin.Event.TEIID30601,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30601, method.getName(),
method.getInvocationClass(), UserDefinedAggregate.class.getName()));
}
}
}
FunctionDescriptor result = new FunctionDescriptor(method, types, outputType,
invocationMethod, requiresContext);
+ if (method.getAggregateAttributes() != null) {
+ result.newInstance();
+ }
result.setHasWrappedArgs(hasWrappedArg);
return result;
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/AggregateFunction.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -28,6 +28,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.util.CommandContext;
/**
@@ -66,7 +67,7 @@
*/
public abstract void reset();
- public void addInput(List<?> tuple) throws TeiidComponentException,
TeiidProcessingException {
+ public void addInput(List<?> tuple, CommandContext commandContext) throws
TeiidComponentException, TeiidProcessingException {
if (conditionIndex != -1 && !Boolean.TRUE.equals(tuple.get(conditionIndex)))
{
return;
}
@@ -77,7 +78,7 @@
}
}
}
- addInputDirect(tuple);
+ addInputDirect(tuple, commandContext);
}
public boolean respectsNull() {
@@ -87,16 +88,18 @@
/**
* Called for the element value in every row of a group.
* @param tuple
+ * @param commandContext
* @throws TeiidProcessingException
*/
- public abstract void addInputDirect(List<?> tuple) throws
TeiidComponentException, TeiidProcessingException;
+ public abstract void addInputDirect(List<?> tuple, CommandContext
commandContext) throws TeiidComponentException, TeiidProcessingException;
/**
* Called after all values have been processed to get the result.
+ * @param commandContext
* @return Result value
* @throws TeiidProcessingException
*/
- public abstract Object getResult()
+ public abstract Object getResult(CommandContext commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException, TeiidProcessingException;
}
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/ArrayAgg.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -33,14 +33,9 @@
public class ArrayAgg extends SingleArgumentAggregateFunction {
private ArrayList<Object> result;
- private CommandContext context;
- public ArrayAgg(CommandContext context) {
- this.context = context;
- }
-
@Override
- public void addInputDirect(Object input, List<?> tuple) throws
TeiidComponentException, TeiidProcessingException {
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext) throws TeiidComponentException, TeiidProcessingException {
if (this.result == null) {
this.result = new ArrayList<Object>();
}
@@ -51,7 +46,7 @@
}
@Override
- public Object getResult() throws FunctionExecutionException,
ExpressionEvaluationException, TeiidComponentException,TeiidProcessingException {
+ public Object getResult(CommandContext commandContext) throws
FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException,TeiidProcessingException {
if (this.result == null) {
return null;
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Avg.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -31,6 +31,7 @@
import org.teiid.core.types.DataTypeManager;
import org.teiid.query.QueryPlugin;
import org.teiid.query.function.FunctionMethods;
+import org.teiid.query.util.CommandContext;
/**
@@ -60,22 +61,22 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object input, List<?> tuple)
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
- super.addInputDirect(input, tuple);
+ super.addInputDirect(input, tuple, commandContext);
count++;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult()
+ public Object getResult(CommandContext commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
- Object sum = super.getResult();
+ Object sum = super.getResult(commandContext);
if (count == 0 || sum == null) {
return null;
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/ConstantFunction.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -27,6 +27,7 @@
import org.teiid.api.exception.query.ExpressionEvaluationException;
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
+import org.teiid.query.util.CommandContext;
/**
@@ -45,18 +46,18 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object input, List<?> tuple)
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
value = input;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult()
+ public Object getResult(CommandContext commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
return this.value;
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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Count.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -26,6 +26,7 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.util.CommandContext;
/**
* Just a simple COUNT() implementation that counts every non-null row it sees.
@@ -39,15 +40,15 @@
}
@Override
- public void addInputDirect(List<?> tuple)
+ public void addInputDirect(List<?> tuple, CommandContext commandContext)
throws TeiidComponentException, TeiidProcessingException {
count++;
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult() {
+ public Object getResult(CommandContext commandContext) {
return Integer.valueOf(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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Max.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -28,6 +28,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.util.CommandContext;
/**
@@ -41,9 +42,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object value, List<?> tuple)
+ public void addInputDirect(Object value, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if(maxValue == null) {
@@ -58,9 +59,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult() {
+ public Object getResult(CommandContext commandContext) {
return this.maxValue;
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Min.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -28,6 +28,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.query.sql.symbol.Constant;
+import org.teiid.query.util.CommandContext;
/**
@@ -41,9 +42,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object value, List<?> tuple)
+ public void addInputDirect(Object value, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if(minValue == null) {
@@ -58,9 +59,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult() {
+ public Object getResult(CommandContext commandContext) {
return this.minValue;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/RankingFunction.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -28,6 +28,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+import org.teiid.query.util.CommandContext;
/**
* computes rank/dense_rank
@@ -49,7 +50,7 @@
}
@Override
- public void addInputDirect(List<?> tuple)
+ public void addInputDirect(List<?> tuple, CommandContext commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if (type == Type.RANK) {
@@ -58,7 +59,7 @@
}
@Override
- public Object getResult() throws FunctionExecutionException,
+ public Object getResult(CommandContext commandContext) throws
FunctionExecutionException,
ExpressionEvaluationException, TeiidComponentException {
if (type == Type.DENSE_RANK) {
count++;
Modified:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/SingleArgumentAggregateFunction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/SingleArgumentAggregateFunction.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/SingleArgumentAggregateFunction.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -26,13 +26,14 @@
import org.teiid.core.TeiidComponentException;
import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.util.CommandContext;
public abstract class SingleArgumentAggregateFunction extends AggregateFunction {
@Override
- public void addInputDirect(List<?> tuple)
+ public void addInputDirect(List<?> tuple, CommandContext commandContext)
throws TeiidComponentException, TeiidProcessingException {
- addInputDirect(tuple.get(argIndexes[0]), tuple);
+ addInputDirect(tuple.get(argIndexes[0]), tuple, commandContext);
}
public void initialize(java.lang.Class<?> dataType, java.lang.Class<?>[]
inputTypes) {
@@ -47,6 +48,6 @@
}
- public abstract void addInputDirect(Object input, List<?> tuple)
+ public abstract void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext)
throws TeiidProcessingException, TeiidComponentException;
}
Modified:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/StatsFunction.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/function/aggregate/StatsFunction.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/StatsFunction.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -28,6 +28,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.query.sql.symbol.AggregateSymbol.Type;
+import org.teiid.query.util.CommandContext;
public class StatsFunction extends SingleArgumentAggregateFunction {
@@ -48,7 +49,7 @@
}
@Override
- public void addInputDirect(Object input, List<?> tuple)
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
sum += ((Number)input).doubleValue();
@@ -57,7 +58,7 @@
}
@Override
- public Object getResult() throws FunctionExecutionException,
+ public Object getResult(CommandContext commandContext) throws
FunctionExecutionException,
ExpressionEvaluationException, TeiidComponentException {
double result = 0;
switch (type) {
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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/Sum.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -30,6 +30,7 @@
import org.teiid.api.exception.query.FunctionExecutionException;
import org.teiid.core.TeiidComponentException;
import org.teiid.core.types.DataTypeManager;
+import org.teiid.query.util.CommandContext;
/**
@@ -85,9 +86,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object input, List<?> tuple)
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
isNull = false;
@@ -117,9 +118,9 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult()
+ public Object getResult(CommandContext commandContext)
throws FunctionExecutionException, ExpressionEvaluationException,
TeiidComponentException {
if (isNull){
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/TextAgg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/TextAgg.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/TextAgg.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -50,15 +50,13 @@
public class TextAgg extends SingleArgumentAggregateFunction {
private FileStoreInputStreamFactory result;
- private CommandContext context;
private TextLine textLine;
- public TextAgg(CommandContext context, TextLine textLine) {
- this.context = context;
+ public TextAgg(TextLine textLine) {
this.textLine = textLine;
}
- private FileStoreInputStreamFactory buildResult() throws TeiidProcessingException {
+ private FileStoreInputStreamFactory buildResult(CommandContext context) throws
TeiidProcessingException {
try {
FileStore fs = context.getBufferManager().createFileStore("textagg");
//$NON-NLS-1$
FileStoreInputStreamFactory fisf = new FileStoreInputStreamFactory(fs,
textLine.getEncoding()==null?Streamable.ENCODING:textLine.getEncoding());
@@ -87,12 +85,12 @@
/**
* @throws TeiidProcessingException
* @throws TeiidComponentException
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object input, List<?> tuple) throws
TeiidComponentException, TeiidProcessingException {
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext) throws TeiidComponentException, TeiidProcessingException {
try {
if (this.result == null) {
- this.result = buildResult();
+ this.result = buildResult(commandContext);
}
String in = (String)input;
Writer w = result.getWriter();
@@ -104,11 +102,11 @@
}
/**
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult() throws TeiidProcessingException{
+ public Object getResult(CommandContext commandContext) throws
TeiidProcessingException{
if (this.result == null) {
- this.result = buildResult();
+ this.result = buildResult(commandContext);
}
try {
Added: trunk/engine/src/main/java/org/teiid/query/function/aggregate/UserDefined.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/UserDefined.java
(rev 0)
+++
trunk/engine/src/main/java/org/teiid/query/function/aggregate/UserDefined.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -0,0 +1,73 @@
+/*
+ * 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.UserDefinedAggregate;
+import org.teiid.api.exception.query.ExpressionEvaluationException;
+import org.teiid.api.exception.query.FunctionExecutionException;
+import org.teiid.core.TeiidComponentException;
+import org.teiid.core.TeiidProcessingException;
+import org.teiid.query.function.FunctionDescriptor;
+import org.teiid.query.util.CommandContext;
+
+public class UserDefined extends AggregateFunction {
+
+ private FunctionDescriptor fd;
+ private UserDefinedAggregate<?> instance;
+ private Object[] values;
+
+ public UserDefined(FunctionDescriptor functionDescriptor) {
+ this.fd = functionDescriptor;
+ this.instance = (UserDefinedAggregate<?>) fd.newInstance();
+ }
+
+ @Override
+ public void addInputDirect(List<?> tuple, CommandContext commandContext) throws
TeiidComponentException,
+ TeiidProcessingException {
+ if (values == null) {
+ values = new Object[argIndexes.length + (fd.requiresContext()?1:0)];
+ }
+ if (fd.requiresContext()) {
+ values[0] = commandContext;
+ }
+ for (int i = 0; i < argIndexes.length; i++) {
+ values[i + (fd.requiresContext()?1:0)] = tuple.get(argIndexes[i]);
+ }
+ fd.invokeFunction(values, commandContext, instance);
+ }
+
+ @Override
+ public void reset() {
+ instance.reset();
+ }
+
+ @Override
+ public Object getResult(CommandContext commandContext) throws
FunctionExecutionException,
+ ExpressionEvaluationException, TeiidComponentException,
+ TeiidProcessingException {
+ return instance.getResult(commandContext);
+ }
+
+}
Property changes on:
trunk/engine/src/main/java/org/teiid/query/function/aggregate/UserDefined.java
___________________________________________________________________
Added: svn:mime-type
+ text/plain
Modified: trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/function/aggregate/XMLAgg.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -37,10 +37,8 @@
private XMLType result;
private XmlConcat concat;
- private CommandContext context;
- public XMLAgg(CommandContext context) {
- this.context = context;
+ public XMLAgg() {
}
public void reset() {
@@ -51,11 +49,11 @@
/**
* @throws TeiidProcessingException
* @throws TeiidComponentException
- * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List)
+ * @see org.teiid.query.function.aggregate.AggregateFunction#addInputDirect(List,
CommandContext, CommandContext)
*/
- public void addInputDirect(Object input, List<?> tuple) throws
TeiidComponentException, TeiidProcessingException {
+ public void addInputDirect(Object input, List<?> tuple, CommandContext
commandContext) throws TeiidComponentException, TeiidProcessingException {
if (concat == null) {
- concat = new XmlConcat(context.getBufferManager());
+ concat = new XmlConcat(commandContext.getBufferManager());
}
concat.addValue(input);
}
@@ -63,9 +61,9 @@
/**
* @throws TeiidProcessingException
* @throws TeiidComponentException
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult() throws TeiidComponentException, TeiidProcessingException {
+ public Object getResult(CommandContext commandContext) throws
TeiidComponentException, TeiidProcessingException {
if (result == null) {
if (concat == null) {
return null;
Modified: trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/AccessNode.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -178,7 +178,7 @@
int i = 0;
int j = 0;
for (Iterator<Expression> iter = symbols.iterator(); iter.hasNext(); ) {
- Expression ss = (Expression) iter.next();
+ Expression ss = iter.next();
Expression ex = SymbolMap.getExpression(ss);
if (ex instanceof Constant) {
projection[i] = ex;
@@ -208,7 +208,7 @@
Integer index = uniqueSymbols.get(SymbolMap.getExpression(item.getSymbol()));
if (index != null) {
item.setExpressionPosition(index);
- item.setSymbol((Expression) select.getSymbols().get(index));
+ item.setSymbol(select.getSymbols().get(index));
}
}
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/GroupingNode.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -184,7 +184,7 @@
Class<?> outputType = symbol.getType();
if(symbol instanceof AggregateSymbol) {
AggregateSymbol aggSymbol = (AggregateSymbol) symbol;
- functions[i] = initAccumulator(context, aggSymbol, this,
this.collectedExpressions);
+ functions[i] = initAccumulator(aggSymbol, this, this.collectedExpressions);
} else {
functions[i] = new ConstantFunction();
functions[i].setArgIndexes(new int[]
{this.collectedExpressions.get(symbol)});
@@ -202,8 +202,8 @@
return index;
}
- static AggregateFunction initAccumulator(CommandContext context,
- AggregateSymbol aggSymbol, RelationalNode node, LinkedHashMap<Expression,
Integer> expressionIndexes) {
+ static AggregateFunction initAccumulator(AggregateSymbol aggSymbol,
+ RelationalNode node, LinkedHashMap<Expression, Integer> expressionIndexes) {
int[] argIndexes = new int[aggSymbol.getArgs().length];
AggregateFunction result = null;
Expression[] args = aggSymbol.getArgs();
@@ -235,14 +235,16 @@
result = new Max();
break;
case XMLAGG:
- result = new XMLAgg(context);
+ result = new XMLAgg();
break;
case ARRAY_AGG:
- result = new ArrayAgg(context);
+ result = new ArrayAgg();
break;
case TEXTAGG:
- result = new TextAgg(context, (TextLine)args[0]);
- break;
+ result = new TextAgg((TextLine)args[0]);
+ break;
+ case USER_DEFINED:
+ result = new UserDefined(aggSymbol.getFunctionDescriptor());
default:
result = new StatsFunction(function);
}
@@ -382,7 +384,7 @@
// Close old group
List<Object> row = new ArrayList<Object>(functions.length);
for(int i=0; i<functions.length; i++) {
- row.add( functions[i].getResult() );
+ row.add( functions[i].getResult(getContext()) );
functions[i].reset();
}
@@ -404,7 +406,7 @@
// Close last group
List<Object> row = new ArrayList<Object>(functions.length);
for(int i=0; i<functions.length; i++) {
- row.add( functions[i].getResult() );
+ row.add( functions[i].getResult(getContext()) );
}
addBatchRow(row);
@@ -425,7 +427,7 @@
throws TeiidComponentException, TeiidProcessingException {
for(int i=0; i<functions.length; i++) {
- functions[i].addInput(tuple);
+ functions[i].addInput(tuple, getContext());
}
}
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/SortingFilter.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -35,6 +35,7 @@
import org.teiid.query.processor.relational.SortUtility.Mode;
import org.teiid.query.sql.lang.OrderByItem;
import org.teiid.query.sql.symbol.ElementSymbol;
+import org.teiid.query.util.CommandContext;
/**
*/
@@ -97,7 +98,7 @@
}
@Override
- public void addInputDirect(List<?> tuple)
+ public void addInputDirect(List<?> tuple, CommandContext commandContext)
throws TeiidComponentException, TeiidProcessingException {
if(collectionBuffer == null) {
collectionBuffer = mgr.createTupleBuffer(elements, groupName,
TupleSourceType.PROCESSOR);
@@ -113,9 +114,9 @@
/**
* @throws TeiidProcessingException
- * @see org.teiid.query.function.aggregate.AggregateFunction#getResult()
+ * @see
org.teiid.query.function.aggregate.AggregateFunction#getResult(CommandContext)
*/
- public Object getResult()
+ public Object getResult(CommandContext commandContext)
throws TeiidComponentException, TeiidProcessingException {
if(collectionBuffer != null) {
@@ -136,7 +137,7 @@
break;
}
//TODO should possibly remove the order by columns from this tuple
- this.proxy.addInputDirect(tuple);
+ this.proxy.addInputDirect(tuple, commandContext);
}
} finally {
sorted.remove();
@@ -146,7 +147,7 @@
}
// Return
- return this.proxy.getResult();
+ return this.proxy.getResult(commandContext);
}
@Override
Modified:
trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/processor/relational/WindowFunctionProjectNode.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -350,10 +350,10 @@
}
}
for (AggregateFunction function : aggs) {
- function.addInput(tuple);
+ function.addInput(tuple, getContext());
}
for (AggregateFunction function : rowValueAggs) {
- function.addInput(tuple);
+ function.addInput(tuple, getContext());
}
lastRow = tuple;
}
@@ -375,7 +375,7 @@
List<Object> row = new ArrayList<Object>(aggs.size() + 1);
row.add(id);
for (AggregateFunction function : aggs) {
- row.add(function.getResult());
+ row.add(function.getResult(getContext()));
if (!samePartition) {
function.reset();
}
@@ -400,7 +400,7 @@
}
List<ElementSymbol> elements = new
ArrayList<ElementSymbol>(functions.size());
for (WindowFunctionInfo wfi : functions) {
- aggs.add(GroupingNode.initAccumulator(this.getContext(), wfi.function.getFunction(),
this, expressionIndexes));
+ aggs.add(GroupingNode.initAccumulator(wfi.function.getFunction(), this,
expressionIndexes));
Class<?> outputType = wfi.function.getType();
ElementSymbol value = new ElementSymbol("val"); //$NON-NLS-1$
value.setType(outputType);
@@ -466,8 +466,10 @@
public void initialize(CommandContext context, BufferManager bufferManager,
ProcessorDataManager dataMgr) {
super.initialize(context, bufferManager, dataMgr);
- List<? extends Expression> sourceElements = this.getChildren()[0].getElements();
- this.elementMap = createLookupMap(sourceElements);
+ if (this.elementMap == null) {
+ List<? extends Expression> sourceElements =
this.getChildren()[0].getElements();
+ this.elementMap = createLookupMap(sourceElements);
+ }
}
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/resolver/util/ResolverVisitor.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -51,6 +51,7 @@
import org.teiid.query.sql.lang.*;
import org.teiid.query.sql.navigator.PostOrderNavigator;
import org.teiid.query.sql.symbol.*;
+import org.teiid.query.sql.symbol.AggregateSymbol.Type;
import org.teiid.query.sql.symbol.ElementSymbol.DisplayMode;
@@ -395,6 +396,9 @@
handleException(e);
}
}
+ if (obj.getAggregateFunction() == Type.USER_DEFINED) {
+ visit((Function)obj);
+ }
}
public TeiidComponentException getComponentException() {
Modified: trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/rewriter/QueryRewriter.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -1352,7 +1352,7 @@
if (rightExpr instanceof Constant) {
Constant const2 = (Constant)rightExpr;
try {
- Object result = descriptor.invokeFunction(new Object[] {
const2.getValue(), const1.getValue() } );
+ Object result = descriptor.invokeFunction(new Object[] {
const2.getValue(), const1.getValue() }, null, this.context );
combinedConst = new Constant(result, descriptor.getReturnType());
} catch(FunctionExecutionException e) {
throw new QueryValidatorException(QueryPlugin.Event.TEIID30373, e,
QueryPlugin.Util.gs(QueryPlugin.Event.TEIID30373, e.getMessage()));
@@ -1590,9 +1590,9 @@
}
Object value = ((Constant)rightExpr).getValue();
try {
- Object result = descriptor.invokeFunction(new Object[] {context,
((Constant)rightExpr).getValue(), format});
- result = leftFunction.getFunctionDescriptor().invokeFunction(new Object[] {context,
result, format } );
- if (((Comparable)value).compareTo(result) != 0) {
+ Object result = descriptor.invokeFunction(new Object[] {context,
((Constant)rightExpr).getValue(), format}, null, this.context );
+ result = leftFunction.getFunctionDescriptor().invokeFunction(new Object[] {context,
result, format }, null, this.context );
+ if (Constant.COMPARATOR.compare(value, result) != 0) {
return getSimpliedCriteria(crit, leftExpr, crit.getOperator() !=
CompareCriteria.EQ, true);
}
} catch(FunctionExecutionException e) {
Modified: trunk/engine/src/main/java/org/teiid/query/sql/lang/Query.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/sql/lang/Query.java 2012-04-04 19:49:28 UTC
(rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/sql/lang/Query.java 2012-04-04 19:54:58 UTC
(rev 3973)
@@ -454,6 +454,6 @@
public boolean hasAggregates() {
return getGroupBy() != null
|| getHaving() != null
- || !AggregateSymbolCollectorVisitor.getAllAggregates(getSelect()).isEmpty();
+ || !AggregateSymbolCollectorVisitor.getAggregates(getSelect(), false).isEmpty();
}
} // END CLASS
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 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/sql/symbol/AggregateSymbol.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -132,12 +132,17 @@
* @param expression Contained expression
*/
public AggregateSymbol(String aggregateFunction, boolean isDistinct, Expression
expression) {
- super(aggregateFunction, expression == null?EMPTY_ARGS:new Expression[] {expression});
+ this(aggregateFunction, isDistinct, expression == null?EMPTY_ARGS:new Expression[]
{expression}, null);
+ }
+
+ public AggregateSymbol(String aggregateFunction, boolean isDistinct, Expression[] args,
OrderBy orderBy) {
+ super(aggregateFunction, args);
this.aggregate = nameMap.get(aggregateFunction);
if (this.aggregate == null) {
this.aggregate = Type.USER_DEFINED;
}
this.distinct = isDistinct;
+ this.orderBy = orderBy;
}
/**
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/AggregateSymbolCollectorVisitor.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -33,7 +33,6 @@
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.Function;
import org.teiid.query.sql.symbol.WindowFunction;
@@ -72,7 +71,6 @@
private Collection<? super AggregateSymbol> aggregates;
private Collection<? super ElementSymbol> otherElements;
private Collection<? super WindowFunction> windowFunctions;
- private Collection<? super Function> aggregateFunctions;
public AggregateSymbolCollectorVisitor(Collection<? super AggregateSymbol>
aggregates, Collection<? super ElementSymbol> elements) {
this.aggregates = aggregates;
@@ -85,13 +83,6 @@
}
}
- @Override
- public void visit(Function obj) {
- if (aggregateFunctions != null && obj.isAggregate()) {
- this.aggregateFunctions.add(obj);
- }
- }
-
public void visit(WindowFunction windowFunction) {
if (this.windowFunctions != null) {
this.windowFunctions.add(windowFunction);
@@ -116,18 +107,6 @@
asn.visitNode(obj);
}
- public static final Collection<Function> getAllAggregates(LanguageObject obj)
{
- if (obj == null) {
- return Collections.emptyList();
- }
- Collection<Function> aggregates = new ArrayList<Function>();
- AggregateSymbolCollectorVisitor visitor = new
AggregateSymbolCollectorVisitor(aggregates, null);
- visitor.aggregateFunctions = aggregates;
- AggregateStopNavigator asn = new AggregateStopNavigator(visitor, null, null);
- obj.acceptVisitor(asn);
- return aggregates;
- }
-
public static final Collection<AggregateSymbol> getAggregates(LanguageObject
obj, boolean removeDuplicates) {
if (obj == null) {
return Collections.emptyList();
Modified: trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java
===================================================================
---
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/main/java/org/teiid/query/sql/visitor/SQLStringVisitor.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -1074,12 +1074,15 @@
// ############ Visitor methods for symbol objects ####################
public void visit( AggregateSymbol obj ) {
- append(obj.getAggregateFunction().name());
+ append(obj.getName());
append("("); //$NON-NLS-1$
if (obj.isDistinct()) {
append(DISTINCT);
append(" "); //$NON-NLS-1$
+ } else if (obj.getAggregateFunction() == Type.USER_DEFINED) {
+ append(ALL);
+ append(" "); //$NON-NLS-1$
}
if (obj.getArgs().length == 0) {
Modified: trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java
===================================================================
--- trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/main/java/org/teiid/query/validator/ValidationVisitor.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -44,6 +44,7 @@
import org.teiid.core.TeiidProcessingException;
import org.teiid.core.types.DataTypeManager;
import org.teiid.core.util.EquivalenceUtil;
+import org.teiid.metadata.AggregateAttributes;
import org.teiid.query.QueryPlugin;
import org.teiid.query.eval.Evaluator;
import org.teiid.query.function.FunctionLibrary;
@@ -324,6 +325,8 @@
} catch (IllegalArgumentException e) {
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.invalid_encoding",
obj.getArg(1)), obj); //$NON-NLS-1$
}
+ } else if (obj.isAggregate()) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.user_defined_aggregate_as_function",
obj, obj.getName()), obj); //$NON-NLS-1$
}
}
@@ -983,6 +986,18 @@
handleValidationError(QueryPlugin.Util.getString("SQLParser.Aggregate_only_top_level",
obj), obj); //$NON-NLS-1$
return;
}
+ if (obj.getAggregateFunction() == AggregateSymbol.Type.USER_DEFINED) {
+ AggregateAttributes aa =
obj.getFunctionDescriptor().getMethod().getAggregateAttributes();
+ if (!aa.allowsDistinct() && obj.isDistinct()) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.uda_not_allowed",
"DISTINCT", obj), obj); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!aa.allowsOrderBy() && obj.getOrderBy() != null) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.uda_not_allowed",
"ORDER BY", obj), obj); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!aa.isWindowable() && obj.isWindowed()) {
+
handleValidationError(QueryPlugin.Util.getString("ValidationVisitor.uda_not_allowed",
"windowing", obj), obj); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
if (obj.getCondition() != null) {
Expression condition = obj.getCondition();
validateNoSubqueriesOrOuterReferences(condition);
Modified: trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj
===================================================================
--- trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-04-04 19:49:28
UTC (rev 3972)
+++ trunk/engine/src/main/javacc/org/teiid/query/parser/SQLParser.jj 2012-04-04 19:54:58
UTC (rev 3973)
@@ -3326,7 +3326,7 @@
(expression=aggregateSymbol(info) expression = windowSpecification(expression, info))
|
// Function
- LOOKAHEAD(2) (expression=function(info))
+ LOOKAHEAD(2) (expression=function(info) [expression = windowSpecification(expression,
info)])
|
// ElementSymbol
(symbol=<ID>
@@ -3389,6 +3389,9 @@
{
WindowFunction result = new WindowFunction();
WindowSpecification ws = new WindowSpecification();
+ if (!(agg instanceof AggregateSymbol)) {
+ throw new
ParseException(QueryPlugin.Util.getString("SQLParser.invalid_window", agg));
//$NON-NLS-1$
+ }
result.setFunction((AggregateSymbol)agg);
ws.setPartition(partitionList);
ws.setOrderBy(orderBy);
@@ -3477,6 +3480,9 @@
ArrayList args = new ArrayList(2);
ArrayList otherArgs = null;
Token funcToken = null;
+ Boolean distinct = null;
+ OrderBy orderBy = null;
+ Expression condition = null;
}
{
(( funcToken = <CONVERT>
@@ -3681,14 +3687,21 @@
|
( funcName = id()
<LPAREN>
+ [<ALL> { distinct = false; } | <DISTINCT> {distinct = true;} ]
[ args = expressionList(info) ]
+ [ orderBy = orderby(info) ]
<RPAREN>
+ condition = filterClause(info)
))
{
if(funcName == null) {
funcName = funcToken.image;
}
-
+ if (distinct != null || orderBy != null || condition != null) {
+ AggregateSymbol as = new AggregateSymbol(funcName, distinct,
(Expression[])args.toArray(new Expression[args.size()]), orderBy);
+ as.setCondition(condition);
+ return as;
+ }
return new Function(funcName, (Expression[])args.toArray(new
Expression[args.size()]));
}
}
Modified: trunk/engine/src/main/resources/org/teiid/query/i18n.properties
===================================================================
--- trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-04-04 19:49:28
UTC (rev 3972)
+++ trunk/engine/src/main/resources/org/teiid/query/i18n.properties 2012-04-04 19:54:58
UTC (rev 3973)
@@ -274,6 +274,7 @@
SQLParser.Invalid_short_name=Invalid simple identifier format: [{0}]
SQLParser.Invalid_char={0} value must be a single character: [{1}].
SQLParser.expected_non_reserved=Expected non-reserved word {0}, but was {1}.
+SQLParser.invalid_window=Cannot window a non-aggregate expression {0}.
SystemSource.array_length_desc=Get the length of the given array value
SystemSource.array_param1=Array
SystemSource.array_length_result=The array length
@@ -673,6 +674,8 @@
ValidationVisitor.badlimit2=The row limit in the LIMIT clause must be >= 0
ValidationVisitor.invalid_scalar_group_reference=Cannot reference a scalar group as a
table: {0}
ValidationVisitor.select_into_wrong_elements=Wrong number of elements being SELECTed INTO
the target table. Expected {0} elements, but was {1}.
+ValidationVisitor.user_defined_aggregate_as_function=Cannot call user defined aggregate
function {0} as a function. To disambiguate, please include an ALL keyword - {1}(ALL
...)
+ValidationVisitor.uda_not_allowed=User defined aggregate function does not allow {0}:
{1}
SimpleQueryResolver.Query_was_redirected_to_Mat_table=The query against {0} was
redirected to the materialization table {1}.
SimpleQueryResolver.ambiguous_all_in_group=The symbol {0} refers to more than one group
defined in the FROM clause.
TEIID30114=Cannot access procedure {0} using table semantics since the parameter and
result set column names are not all unique.
@@ -1060,4 +1063,5 @@
TEIID30600=User defined aggregate function "{0}" method "{1}" must
not be static.
TEIID30601=User defined aggregate function "{0}" class "{1}" does not
implement {2}
+TEIID30602=User defined aggregate function "{0}" class "{1}" does not
provide a public no-arg constructor.
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java
===================================================================
---
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/test/java/org/teiid/query/function/TestFunctionLibrary.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -227,11 +227,11 @@
for (int i = 0; i < inputs.length; i++) {
in[i+1] = inputs[i];
}
- actualOutput = descriptor.invokeFunction(in);
+ actualOutput = descriptor.invokeFunction(in, null, null);
}
else {
// Invoke function with inputs
- actualOutput = descriptor.invokeFunction(inputs);
+ actualOutput = descriptor.invokeFunction(inputs, null, null);
}
return actualOutput;
}
Modified: trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java 2012-04-04
19:49:28 UTC (rev 3972)
+++ trunk/engine/src/test/java/org/teiid/query/function/TestFunctionTree.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -162,7 +162,7 @@
FunctionLibrary fl = new FunctionLibrary(sys, new FunctionTree("foo", new
UDFSource(Arrays.asList(method)), true));
FunctionDescriptor fd = fl.findFunction("dummy", new Class<?>[]
{DataTypeManager.DefaultDataClasses.VARBINARY});
String hello = "hello";
- assertEquals(hello, fd.invokeFunction(new Object[] {new
BinaryType(hello.getBytes())}));
+ assertEquals(hello, fd.invokeFunction(new Object[] {new
BinaryType(hello.getBytes())}, null, null));
}
/*
Modified: trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java
===================================================================
--- trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-04-04 19:49:28
UTC (rev 3972)
+++ trunk/engine/src/test/java/org/teiid/query/parser/TestParser.java 2012-04-04 19:54:58
UTC (rev 3973)
@@ -5213,5 +5213,19 @@
assertEquals(DataTypeManager.DefaultDataClasses.VARBINARY,
actualCommand.getSelect().getSymbol(0).getType());
assertEquals("SELECT X'AABBCC0A'", actualCommand.toString());
}
+
+ @Test public void testUserDefinedAggregateParsing() throws QueryParserException {
+ Query actualCommand = (Query)QueryParser.getQueryParser().parseCommand("SELECT
foo(ALL x, y)", new ParseInfo());
+ assertEquals("SELECT foo(ALL x, y)", actualCommand.toString());
+ }
+ @Test(expected=QueryParserException.class) public void testWindowedExpression()
throws QueryParserException {
+ QueryParser.getQueryParser().parseCommand("SELECT foo(x, y) over ()", new
ParseInfo());
+ }
+
+ @Test public void testWindowedExpression1() throws QueryParserException {
+ Query actualCommand = (Query)QueryParser.getQueryParser().parseCommand("SELECT
foo(distinct x, y) over ()", new ParseInfo());
+ assertEquals("SELECT foo(DISTINCT x, y) OVER ()", actualCommand.toString());
+ }
+
}
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 2012-04-04
19:49:28 UTC (rev 3972)
+++
trunk/engine/src/test/java/org/teiid/query/processor/relational/TestDuplicateFilter.java 2012-04-04
19:54:58 UTC (rev 3973)
@@ -52,10 +52,10 @@
// Add inputs
for(int i=0; i<input.length; i++) {
- filter.addInputDirect(Arrays.asList(input[i]));
+ filter.addInputDirect(Arrays.asList(input[i]), null);
}
- Integer actual = (Integer) filter.getResult();
+ Integer actual = (Integer) filter.getResult(null);
assertEquals("Did not get expected number of results", expected,
actual.intValue()); //$NON-NLS-1$
}