KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > agg > SegmentArrayQuerySpec


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/agg/SegmentArrayQuerySpec.java#15 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2005-2007 Julian Hyde and others
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10
11 package mondrian.rolap.agg;
12
13 import mondrian.olap.Util;
14 import mondrian.rolap.RolapStar;
15 import mondrian.rolap.StarColumnPredicate;
16 import mondrian.rolap.sql.SqlQuery;
17
18 /**
19  * Provides the information necessary to generate a SQL statement to
20  * retrieve a list of segments.
21  *
22  * @author jhyde
23  * @author Richard M. Emberson
24  * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/SegmentArrayQuerySpec.java#15 $
25  */

26 class SegmentArrayQuerySpec extends AbstractQuerySpec {
27     private final Segment[] segments;
28
29     /**
30      * Creates a SegmentArrayQuerySpec.
31      *
32      * @param segments Array of segments (must be at least one)
33      */

34     SegmentArrayQuerySpec(final Segment[] segments) {
35         super(segments[0].aggregation.getStar());
36         this.segments = segments;
37         assert isValid(true);
38     }
39
40     /**
41      * Returns whether this query specification is valid, or throws if invalid
42      * and <code>fail</code> is true.
43      *
44      * @param fail Whether to throw if invalid
45      * @return Whether this query specification is valid
46      */

47     private boolean isValid(boolean fail) {
48         assert segments.length > 0;
49         for (Segment segment : segments) {
50             if (segment.aggregation != segments[0].aggregation) {
51                 assert!fail;
52                 return false;
53             }
54             int n = segment.axes.length;
55             if (n != segments[0].axes.length) {
56                 assert!fail;
57                 return false;
58             }
59             for (int j = 0; j < segment.axes.length; j++) {
60                 // We only require that the two arrays have the same
61
// contents, we but happen to know they are the same array,
62
// because we constructed them at the same time.
63
if (segment.axes[j].getPredicate() !=
64                     segments[0].axes[j].getPredicate()) {
65                     assert!fail;
66                     return false;
67                 }
68             }
69         }
70         return true;
71     }
72
73     public int getMeasureCount() {
74         return segments.length;
75     }
76
77     public RolapStar.Measure getMeasure(final int i) {
78         return segments[i].measure;
79     }
80
81     public String JavaDoc getMeasureAlias(final int i) {
82         return "m" + Integer.toString(i);
83     }
84
85     public RolapStar.Column[] getColumns() {
86         return segments[0].aggregation.getColumns();
87     }
88
89     /**
90      * SqlQuery relies on "c" and index. All this should go into SqlQuery!
91      *
92      * @see mondrian.rolap.sql.SqlQuery#addOrderBy
93      */

94     public String JavaDoc getColumnAlias(final int i) {
95         return "c" + Integer.toString(i);
96     }
97
98     public StarColumnPredicate getColumnPredicate(final int i) {
99         return segments[0].axes[i].getPredicate();
100     }
101
102     public String JavaDoc generateSqlQuery() {
103         SqlQuery sqlQuery = newSqlQuery();
104
105         int k = getDistinctMeasureCount();
106         final SqlQuery.Dialect dialect = sqlQuery.getDialect();
107         if (!dialect.allowsCountDistinct() && k > 0 ||
108             !dialect.allowsMultipleCountDistinct() && k > 1) {
109             distinctGenerateSql(sqlQuery);
110         } else {
111             nonDistinctGenerateSql(sqlQuery, false, false);
112         }
113
114         return sqlQuery.toString();
115     }
116
117     /**
118      * Returns the number of measures which are distinct.
119      *
120      * @return the number of measures which are distinct
121      */

122     protected int getDistinctMeasureCount() {
123         int k = 0;
124         for (int i = 0, count = getMeasureCount(); i < count; i++) {
125             RolapStar.Measure measure = getMeasure(i);
126             if (measure.getAggregator().isDistinct()) {
127                 ++k;
128             }
129         }
130         return k;
131     }
132
133     protected void addMeasure(final int i, final SqlQuery sqlQuery) {
134         RolapStar.Measure measure = getMeasure(i);
135         Util.assertTrue(measure.getTable() == getStar().getFactTable());
136         measure.getTable().addToFrom(sqlQuery, false, true);
137
138         String JavaDoc exprInner = measure.generateExprString(sqlQuery);
139         String JavaDoc exprOuter = measure.getAggregator().getExpression(exprInner);
140         sqlQuery.addSelect(exprOuter, getMeasureAlias(i));
141     }
142
143     protected boolean isAggregate() {
144         return true;
145     }
146
147     /**
148      * Generates a SQL query to retrieve the values in this segment using
149      * an algorithm which converts distinct-aggregates to non-distinct
150      * aggregates over subqueries.
151      *
152      * @param outerSqlQuery Query to modify
153      */

154     protected void distinctGenerateSql(final SqlQuery outerSqlQuery) {
155         final SqlQuery.Dialect dialect = outerSqlQuery.getDialect();
156         // Generate something like
157
// select d0, d1, count(m0)
158
// from (
159
// select distinct x as d0, y as d1, z as m0
160
// from t) as foo
161
// group by d0, d1
162

163         final SqlQuery innerSqlQuery = newSqlQuery();
164         innerSqlQuery.setDistinct(true);
165
166         // add constraining dimensions
167
RolapStar.Column[] columns = getColumns();
168         int arity = columns.length;
169         for (int i = 0; i < arity; i++) {
170             RolapStar.Column column = columns[i];
171             RolapStar.Table table = column.getTable();
172             if (table.isFunky()) {
173                 // this is a funky dimension -- ignore for now
174
continue;
175             }
176             table.addToFrom(innerSqlQuery, false, true);
177             String JavaDoc expr = column.generateExprString(innerSqlQuery);
178             StarColumnPredicate predicate = getColumnPredicate(i);
179             final String JavaDoc where = RolapStar.Column.createInExpr(
180                 expr,
181                 predicate,
182                 column.getDatatype(),
183                 innerSqlQuery.getDialect());
184             if (!where.equals("true")) {
185                 innerSqlQuery.addWhere(where);
186             }
187             final String JavaDoc alias = "d" + i;
188             innerSqlQuery.addSelect(expr, alias);
189             final String JavaDoc quotedAlias = dialect.quoteIdentifier(alias);
190             outerSqlQuery.addSelect(quotedAlias);
191             outerSqlQuery.addGroupBy(quotedAlias);
192         }
193         for (int i = 0, count = getMeasureCount(); i < count; i++) {
194             RolapStar.Measure measure = getMeasure(i);
195
196             Util.assertTrue(measure.getTable() == getStar().getFactTable());
197             measure.getTable().addToFrom(innerSqlQuery, false, true);
198
199             String JavaDoc alias = getMeasureAlias(i);
200             String JavaDoc expr = measure.generateExprString(outerSqlQuery);
201             innerSqlQuery.addSelect(expr, alias);
202
203             outerSqlQuery.addSelect(
204                 measure.getAggregator().getNonDistinctAggregator().getExpression(
205                     dialect.quoteIdentifier(alias)));
206         }
207         outerSqlQuery.addFrom(innerSqlQuery, "dummyname", true);
208     }
209 }
210
211 // End SegmentArrayQuerySpec.java
212
Popular Tags