001: package org.mandarax.jdbc.server.sql;
002:
003: /*
004: * Copyright (C) 1999-2004 <a href="mailto:mandarax@jbdietrich.com">Jens Dietrich</a>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: import java.util.*;
022: import org.mandarax.jdbc.server.parser.ParseException;
023: import org.mandarax.kernel.InferenceException;
024: import org.mandarax.kernel.VariableTerm;
025: import org.mandarax.util.resultsetfilters.AggregationFunction;
026: import org.mandarax.util.resultsetfilters.aggregationfunctions.*;
027:
028: /**
029: * The SQL group by clause.
030: * @author <A HREF="mailto:mandarax@jbdietrich.com">Jens Dietrich</A>
031: * @version 3.3.2 <29 December 2004>
032: * @since 3.0
033: */
034:
035: public class GroupByClause extends SQLObject implements
036: ColumnTermContext {
037: private List columns = new ArrayList();
038: private Map variablesByName = null;
039:
040: private SelectStatement owner;
041:
042: /**
043: * Add a column to the list.
044: * @param item a new column.
045: */
046: public void add(ColumnTerm colTerm) throws ParseException {
047: if (colTerm instanceof HostVariable)
048: throw new ParseException(
049: "Host variables are not allowed in GROUP BY list");
050: if (colTerm instanceof Null)
051: throw new ParseException(
052: "Null not allowed in GROUP BY list");
053: if (colTerm instanceof Value)
054: throw new ParseException(
055: "Values are not allowed in GROUP BY list");
056: columns.add(colTerm);
057: }
058:
059: /**
060: * Indicates whether the clause is empty.
061: * @return a boolean indicating whether the clause is empty
062: */
063: boolean isEmpty() {
064: return columns.size() == 0;
065: }
066:
067: /**
068: * Set variable names / variable associations.
069: * @param variablesByNames a map containing variable name -> variable term associations
070: */
071: void setVariablesByName(Map variablesByName) {
072: this .variablesByName = variablesByName;
073: }
074:
075: /**
076: * Get an array of aggregation functions.
077: * @return aggregation functions.
078: */
079: AggregationFunction[] getAggregationFunctions()
080: throws InferenceException {
081:
082: List columnTerms = owner.getColumns();
083: List aggregationFunctions = new ArrayList();
084: for (int i = 0; i < columnTerms.size(); i++) {
085: Object columnTerm = columnTerms.get(i);
086: if (columnTerm instanceof ComplexTerm1) {
087: ComplexTerm1 ct1 = (ComplexTerm1) columnTerm;
088: Function f = ct1.getFunction();
089: if (f.isAggregationFunction()) {
090: if (f.equals(Functions.COUNT)) {
091: aggregationFunctions.add(new COUNT());
092: } else {
093: ColumnTerm nested = ct1.getColTerm();
094: if (nested instanceof ColumnName) {
095: ColumnName nestedColName = (ColumnName) nested;
096: VariableTerm var = (VariableTerm) variablesByName
097: .get(nestedColName.getName());
098: if (var == null)
099: throw new InferenceException(
100: "No variable found for column name "
101: + nestedColName
102: .getName());
103: if (f.equals(Functions.AVG))
104: aggregationFunctions.add(new AVG(var));
105: else if (f.equals(Functions.SUM))
106: aggregationFunctions.add(new SUM(var));
107: else if (f.equals(Functions.MAX))
108: aggregationFunctions.add(new MAX(var));
109: else if (f.equals(Functions.MIN))
110: aggregationFunctions.add(new MIN(var));
111: else
112: throw new InferenceException(
113: "Unknown aggregation function "
114: + f.getName());
115: } else
116: throw new InferenceException(
117: "Only column names are allowed as arguments of aggregation functions: "
118: + ct1.asVariableName());
119: }
120: }
121: }
122: }
123: return (AggregationFunction[]) aggregationFunctions
124: .toArray(new AggregationFunction[aggregationFunctions
125: .size()]);
126: }
127:
128: /**
129: * Get an array of aggregation terms.
130: * @return aggregation terms (variables).
131: */
132: VariableTerm[] getAggregationTerms() throws InferenceException {
133: VariableTerm[] vars = new VariableTerm[columns.size()];
134: for (int i = 0; i < columns.size(); i++) {
135: ColumnTerm colTerm = (ColumnTerm) columns.get(i);
136: if (colTerm instanceof ColumnName) {
137: String colName = ((ColumnName) colTerm).getName();
138: VariableTerm var = (VariableTerm) variablesByName
139: .get(colName);
140: if (var == null)
141: throw new InferenceException(
142: "No variable term found for GROUP BY column "
143: + colName);
144: vars[i] = var;
145: } else
146: throw new InferenceException(
147: "Only column names are allowed in group by column list");
148: }
149: return vars;
150: }
151:
152: /**
153: * Get an array of group by terms that are used in the result set
154: * (= associated with columns in the select clause).
155: * @return aggregation terms (variables).
156: */
157: VariableTerm[] getSelectedAggregationTerms()
158: throws InferenceException {
159: List columnNames = owner.getColumnNames();
160: VariableTerm[] vars = new VariableTerm[columnNames.size()];
161: for (int i = 0; i < columnNames.size(); i++) {
162: ColumnName colTerm = (ColumnName) columnNames.get(i);
163: String colName = ((ColumnName) colTerm).getName();
164: VariableTerm var = (VariableTerm) variablesByName
165: .get(colName);
166: if (var == null)
167: throw new InferenceException(
168: "No variable term found for GROUP BY column "
169: + colName);
170: vars[i] = var;
171: }
172: return vars;
173: }
174:
175: /**
176: * Get the owner.
177: * @return the select statement
178: */
179: public SelectStatement getOwner() {
180: return owner;
181: }
182:
183: /**
184: * Sets the owner.
185: * @param owner The owner to set
186: */
187: void setOwner(SelectStatement owner) {
188: this .owner = owner;
189: }
190:
191: /**
192: * Print the object on a buffer in order to display the parsed SQL.
193: * @param out a string bufer to print on
194: */
195: public void print(StringBuffer out) {
196: for (int i = 0; i < columns.size(); i++) {
197: if (i > 0)
198: out.append(',');
199: ((ColumnTerm) columns.get(i)).print(out);
200: }
201: }
202:
203: /**
204: * Normalize the object.
205: * @param typesByColumn associations between column names and (SQL) types
206: */
207: public void normalize(Map typesByColumn) {
208: // nothing to do here
209: }
210:
211: /**
212: * Compares objects.
213: * @param obj another object.
214: * @return a boolean
215: */
216: public boolean sameAs(Object obj) {
217: if (obj != null && obj instanceof GroupByClause) {
218: GroupByClause s = (GroupByClause) obj;
219: boolean result = true;
220: result = result && s.columns.equals(s.columns);
221: return result;
222: }
223: return false;
224: }
225:
226: }
|