⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aggregation.java

📁 数据仓库展示程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/agg/Aggregation.java#24 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// Copyright (C) 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 28 August, 2001
 */

package mondrian.rolap.agg;

import mondrian.olap.Level;
import mondrian.olap.Member;
import mondrian.olap.SchemaReader;
import mondrian.olap.Util;
import mondrian.rolap.RolapStar;
import mondrian.rolap.BitKey;
import mondrian.rolap.sql.SqlQuery;

import java.lang.ref.SoftReference;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;

/**
 * A <code>Aggregation</code> is a pre-computed aggregation over a set of
 * columns.
 *
 * <p>Rollup operations:<ul>
 * <li>drop an unrestricted column (e.g. state=*)</li>
 * <li>tighten any restriction (e.g. year={1997,1998} becomes
 *     year={1997})</li>
 * <li>restrict an unrestricted column (e.g. year=* becomes
 *     year={1997})</li>
 * </ul>
 *
 * <p>Representation of aggregations. Sparse and dense representations are
 * necessary for different data sets. Should adapt automatically. Use an
 * interface to hold the data set, so the segment doesn't care.</p>
 *
 * Suppose we have a segment {year=1997, quarter={1,2,3},
 * state={CA,WA}}. We want to roll up to a segment for {year=1997,
 * state={CA,WA}}.  We need to know that we have all quarters.  We don't.
 * Because year and quarter are independent, we know that we have all of
 * the ...</p>
 *
 * <p>Suppose we have a segment specified by {region=West, state=*,
 * year=*}, which materializes to ({West}, {CA,WA,OR}, {1997,1998}).
 * Because state=*, we can rollup to {region=West, year=*} or {region=West,
 * year=1997}.</p>
 *
 * <p>The space required for a segment depends upon the dimensionality (d),
 * cell count (c) and the value count (v). We don't count the space
 * required for the actual values, which is the same in any scheme.</p>
 *
 * <b>Note to developers</b>: {@link Segment} implements
 * {@link CachePool.Cacheable}, and must adhere to the contract that imposes.
 * For this class, that means that references to segments must be made using
 * soft references (see {@link CachePool.SoftCacheableReference}) so that they
 * can be garbage-collected.
 *
 * @author jhyde
 * @since 28 August, 2001
 * @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/Aggregation.java#24 $
 **/
public class Aggregation {
    private static final int MAXLEN_ORACLE = 1000;

    private final RolapStar star;

    private final BitKey bitKey;

    /**
     * List of soft references to segments.
     * Access must be inside of synchronized methods.
     **/
    private final List segmentRefs;
    private final boolean oracle;

    /**
     * This is set in the load method and is used during
     * the processing of a particular aggregate load.
     * The AggregateManager synchonizes access to each instance's methods
     * so that an instance is processing a single set of columns, measures,
     * contraints at any one time.
     */
    private RolapStar.Column[] columns;

    public Aggregation(RolapStar star,
                       BitKey bitKey) {
        this.star = star;
        this.bitKey = bitKey;
        this.segmentRefs = new ArrayList();

        this.oracle = star.getSqlQueryDialect().isOracle();
    }

    /**
     * Loads a set of segments into this aggregation, one per measure,
     * each constrained by the same set of column values, and each pinned
     * once.
     * <p>
     * A Column and its constraints are accessed at the same level in their
     * respective arrays.
     *
     * For example,
     *   measures = {unit_sales, store_sales},
     *   state = {CA, OR},
     *   gender = unconstrained
     */
    public synchronized void load(RolapStar.Column[] columns,
                                  RolapStar.Measure[] measures,
                                  ColumnConstraint[][] constraintses,
                                  Collection pinnedSegments) {
        this.columns = columns;

        BitKey bitKey = this.bitKey.copy();
        int axisCount = columns.length;
        Util.assertTrue(constraintses.length == axisCount);

        // This array of Aggregation.Axis is shared by all Segments for
        // this set of measures and constraintses
        Aggregation.Axis[] axes = new Aggregation.Axis[axisCount];
        for (int i = 0; i < axisCount; i++) {
            axes[i] = new Aggregation.Axis(columns[i], constraintses[i]);
        }

        boolean isDistinct = false;
        Segment[] segments = new Segment[measures.length];
        for (int i = 0; i < measures.length; i++) {
            RolapStar.Measure measure = measures[i];

            if (measure.getAggregator().isDistinct()) {
                isDistinct = true;
            }

            bitKey.setByPos(measure.getBitPosition());
            Segment segment = new Segment(this, measure, constraintses, axes);
            segments[i] = segment;
            SoftReference ref = new SoftReference(segment);
            segmentRefs.add(ref);
            pinnedSegments.add(segment);
        }
        Segment.load(segments, bitKey, isDistinct, pinnedSegments, axes);

    }


    /**
     * Drops constraints, where the list of values is close to the values which
     * would be returned anyway.
     **/
    public synchronized ColumnConstraint[][] optimizeConstraints(
                       RolapStar.Column[] columns,
            ColumnConstraint[][] constraintses) {

        Util.assertTrue(constraintses.length == columns.length);
        ColumnConstraint[][] newConstraintses =
            (ColumnConstraint[][]) constraintses.clone();
        double[] bloats = new double[columns.length];

        // We want to handle the special case "drilldown" which occurs pretty often.
        // Here, the parent is here as a constraint with a single member
        //  and the list of children as well.
        List potentialParents = new ArrayList();
        for (int i = 0; i < constraintses.length; i++) {
            if (constraintses[i] != null && constraintses[i].length == 1
                    && constraintses[i][0].isMember())
                potentialParents.add(constraintses[i][0].getMember());
        }

        for (int i = 0; i < newConstraintses.length; i++) {
            double constraintLength = (double) newConstraintses[i].length;
            // a set of constraints with only one entry will not be optimized away
            if (newConstraintses[i] == null || newConstraintses[i].length < 2) {
                bloats[i] = 0.0;
            } else {
                // Oracle can only handle up to 1000 elements inside an IN(..) clause
                if (oracle && newConstraintses[i].length > MAXLEN_ORACLE) {
                    bloats[i] = 1.0; // will be optimized away
                    continue;
                }
                // more than one - check for children of same parent
                Member parent = null;
                Level level = null;
                for (int j = 0; j < newConstraintses[i].length; j++) {
                    if (!(newConstraintses[i][j].isMember())) {
                        // should not occur - but
                        //  we compute bloat by #constraints / column cardinality
                        parent = null;
                        level = null;
                        bloats[i] =  constraintLength / columns[i].getCardinality();
                        break;
                    } else {
                        Member m = newConstraintses[i][j].getMember();
                        if (j == 0) {
                            parent = m.getParentMember();
                            level = m.getLevel();
                        } else {
                            if (parent != null
                                    && !parent.equals(m.getParentMember())) {
                                parent = null; // no common parent
                            }
                            if (level != null
                                    && !level.equals(m.getLevel())) {
                                // should never occur, constraintses are of same level
                                level = null;
                            }
                        }
                    }
                }
                boolean done = false;
                if (parent != null) {
                    // common parent exists
                    if (parent.isAll() || potentialParents.contains(parent) ) {
                        // common parent is there as constraint
                        //  if the children are complete, this constraint set is
                        //  unneccessary try to get the children directly from
                        //  cache for the drilldown case, the children will be
                        //  in the cache
                        // - if not, forget this optimization.
                        int nChildren = -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -