001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2005-2005 Julian Hyde
008// Copyright (C) 2005-2011 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.rolap.agg;
012
013import mondrian.rolap.*;
014import mondrian.rolap.sql.SqlQuery;
015
016import java.util.*;
017
018/**
019 * Provides the information necessary to generate a SQL statement to
020 * retrieve a list of segments.
021 *
022 * @author jhyde
023 * @author Richard M. Emberson
024 */
025class SegmentArrayQuerySpec extends AbstractQuerySpec {
026    private final List<Segment> segments;
027    private final Segment segment0;
028    private final GroupingSetsList groupingSetsList;
029
030    /*
031     * Compound member predicates.
032     * Each list constrains one dimension.
033     */
034    private final List<StarPredicate> compoundPredicateList;
035
036    /**
037     * Creates a SegmentArrayQuerySpec.
038     *
039     * @param groupingSetsList Collection of grouping sets
040     * @param compoundPredicateList list of predicates representing the
041     * compound member constraints
042     */
043    SegmentArrayQuerySpec(
044        GroupingSetsList groupingSetsList,
045        List<StarPredicate> compoundPredicateList)
046    {
047        super(groupingSetsList.getStar(), false);
048        this.segments = groupingSetsList.getDefaultSegments();
049        this.segment0 = segments.get(0);
050        this.groupingSetsList = groupingSetsList;
051        this.compoundPredicateList = compoundPredicateList;
052        assert isValid(true);
053    }
054
055    /**
056     * Returns whether this query specification is valid, or throws if invalid
057     * and <code>fail</code> is true.
058     *
059     * @param fail Whether to throw if invalid
060     * @return Whether this query specification is valid
061     */
062    private boolean isValid(boolean fail) {
063        assert segments.size() > 0;
064        for (Segment segment : segments) {
065            int n = segment.predicates.length;
066            if (n != segment0.predicates.length) {
067                assert !fail;
068                return false;
069            }
070            for (int j = 0; j < segment.predicates.length; j++) {
071                // We only require that the two arrays have the same
072                // contents, we but happen to know they are the same array,
073                // because we constructed them at the same time.
074                if (segment.predicates[j] != segment0.predicates[j]) {
075                    assert !fail;
076                    return false;
077                }
078            }
079        }
080        return true;
081    }
082
083    public int getMeasureCount() {
084        return segments.size();
085    }
086
087    public RolapStar.Measure getMeasure(final int i) {
088        return segments.get(i).measure;
089    }
090
091    public String getMeasureAlias(final int i) {
092        return "m" + Integer.toString(i);
093    }
094
095    public RolapStar.Column[] getColumns() {
096        return segment0.getColumns();
097    }
098
099    /**
100     * SqlQuery relies on "c" and index. All this should go into SqlQuery!
101     *
102     * @see mondrian.rolap.sql.SqlQuery#addOrderBy
103     */
104    public String getColumnAlias(final int i) {
105        return "c" + Integer.toString(i);
106    }
107
108    public StarColumnPredicate getColumnPredicate(final int i) {
109        return segment0.predicates[i];
110    }
111
112    protected List<StarPredicate> getPredicateList() {
113        if (compoundPredicateList == null) {
114            return super.getPredicateList();
115        } else {
116            return compoundPredicateList;
117        }
118    }
119
120    protected void addGroupingFunction(SqlQuery sqlQuery) {
121        List<RolapStar.Column> list = groupingSetsList.getRollupColumns();
122        for (RolapStar.Column column : list) {
123            sqlQuery.addGroupingFunction(column.generateExprString(sqlQuery));
124        }
125    }
126
127    protected void addGroupingSets(
128        SqlQuery sqlQuery,
129        Map<String, String> groupingSetsAliases)
130    {
131        List<RolapStar.Column[]> groupingSetsColumns =
132            groupingSetsList.getGroupingSetsColumns();
133        for (RolapStar.Column[] groupingSetsColumn : groupingSetsColumns) {
134            ArrayList<String> groupingColumnsExpr = new ArrayList<String>();
135            for (RolapStar.Column aColumn : groupingSetsColumn) {
136                final String columnExpr = aColumn.generateExprString(sqlQuery);
137                if (groupingSetsAliases.containsKey(columnExpr)) {
138                    groupingColumnsExpr.add(
139                        groupingSetsAliases.get(columnExpr));
140                } else {
141                    groupingColumnsExpr.add(columnExpr);
142                }
143            }
144            sqlQuery.addGroupingSet(groupingColumnsExpr);
145        }
146    }
147
148    protected boolean isAggregate() {
149        return true;
150    }
151}
152
153// End SegmentArrayQuerySpec.java