001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.SumAvgAggregateDefinition
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
025: import org.apache.derby.iapi.services.context.ContextService;
026: import org.apache.derby.iapi.services.sanity.SanityManager;
027:
028: import org.apache.derby.impl.sql.execute.SumAggregator;
029: import org.apache.derby.impl.sql.execute.AvgAggregator;
030:
031: import org.apache.derby.catalog.TypeDescriptor;
032: import org.apache.derby.iapi.types.TypeId;
033: import org.apache.derby.iapi.types.DataTypeDescriptor;
034:
035: import org.apache.derby.iapi.sql.compile.TypeCompiler;
036: import org.apache.derby.iapi.sql.compile.TypeCompilerFactory;
037:
038: import org.apache.derby.iapi.sql.compile.CompilerContext;
039:
040: import org.apache.derby.iapi.error.StandardException;
041: import org.apache.derby.iapi.reference.ClassName;
042:
043: /**
044: * Defintion for the SUM()/AVG() aggregates.
045: *
046: * @author jamie
047: */
048: public class SumAvgAggregateDefinition implements AggregateDefinition {
049: private boolean isSum;
050:
051: /**
052: * Niladic constructor. Does nothing. For ease
053: * Of use, only.
054: */
055: public SumAvgAggregateDefinition() {
056: super ();
057: }
058:
059: /**
060: * Determines the result datatype. Accept NumberDataValues
061: * only.
062: * <P>
063: * <I>Note</I>: In the future you should be able to do
064: * a sum user data types. One option would be to run
065: * sum on anything that implements plus(). In which
066: * case avg() would need divide().
067: *
068: * @param inputType the input type, either a user type or a java.lang object
069: *
070: * @return the output Class (null if cannot operate on
071: * value expression of this type.
072: */
073: public final TypeDescriptor getAggregator(TypeDescriptor inputType,
074: StringBuffer aggregatorClass) {
075: try {
076: LanguageConnectionContext lcc = (LanguageConnectionContext) ContextService
077: .getContext(LanguageConnectionContext.CONTEXT_ID);
078:
079: DataTypeDescriptor dts = new DataTypeDescriptor(
080: (DataTypeDescriptor) inputType, inputType
081: .isNullable());
082: TypeId compType = dts.getTypeId();
083:
084: CompilerContext cc = (CompilerContext) ContextService
085: .getContext(CompilerContext.CONTEXT_ID);
086: TypeCompilerFactory tcf = cc.getTypeCompilerFactory();
087: TypeCompiler tc = tcf.getTypeCompiler(compType);
088:
089: /*
090: ** If the class implements NumberDataValue, then we
091: ** are in business. Return type is same as input
092: ** type.
093: */
094: if (compType.isNumericTypeId()) {
095: aggregatorClass.append(getAggregatorClassName());
096:
097: DataTypeDescriptor outDts = tc
098: .resolveArithmeticOperation(dts, dts,
099: getOperator());
100: /*
101: ** SUM and AVG may return null
102: */
103: outDts.setNullability(true);
104: return outDts;
105: }
106: } catch (StandardException e) {
107: if (SanityManager.DEBUG) {
108: SanityManager.THROWASSERT("Unexpected exception " + e);
109: }
110: }
111:
112: return null;
113: }
114:
115: /**
116: * Return the aggregator class.
117: *
118: * @return SumAggregator.CLASS_NAME/AvgAggregator.CLASS_NAME
119: */
120: private String getAggregatorClassName() {
121: if (isSum)
122: return ClassName.SumAggregator;
123: else
124: return ClassName.AvgAggregator;
125: }
126:
127: /**
128: * Return the arithmetic operator corresponding
129: * to this operation.
130: *
131: * @return TypeCompiler.SUM_OP /TypeCompiler.AVG_OP
132: */
133: protected String getOperator() {
134: if (isSum)
135: return TypeCompiler.SUM_OP;
136: else
137: return TypeCompiler.AVG_OP;
138: }
139:
140: /**
141: * This is set by the parser.
142: */
143: public final void setSumOrAvg(boolean isSum) {
144: this.isSum = isSum;
145: }
146:
147: }
|