segment.java
来自「数据仓库展示程序」· Java 代码 · 共 438 行 · 第 1/2 页
JAVA
438 行
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/agg/Segment.java#33 $
// 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) 2002-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 21 March, 2002
*/
package mondrian.rolap.agg;
import mondrian.olap.*;
import mondrian.rolap.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
/**
* A <code>Segment</code> is a collection of cell values parameterized by
* a measure, and a set of (column, value) pairs. An example of a segment is</p>
*
* <blockquote>
* <p>(Unit sales, Gender = 'F', State in {'CA','OR'}, Marital Status = <i>
* anything</i>)</p>
* </blockquote>
*
* <p>All segments over the same set of columns belong to an Aggregation, in this
* case</p>
*
* <blockquote>
* <p>('Sales' Star, Gender, State, Marital Status)</p>
* </blockquote>
*
* <p>Note that different measures (in the same Star) occupy the same Aggregation.
* Aggregations belong to the AggregationManager, a singleton.</p>
* <p>Segments are pinned during the evaluation of a single MDX query. The query
* evaluates the expressions twice. The first pass, it finds which cell values it
* needs, pins the segments containing the ones which are already present (one
* pin-count for each cell value used), and builds a {@link CellRequest
* cell request} for those which are not present. It executes
* the cell request to bring the required cell values into the cache, again,
* pinned. Then it evalutes the query a second time, knowing that all cell values
* are available. Finally, it releases the pins.</p>
*
* @author jhyde
* @since 21 March, 2002
* @version $Id: //open/mondrian/src/main/mondrian/rolap/agg/Segment.java#33 $
**/
class Segment {
/**
* <code>State</code> enumerates the allowable values of a segment's
* state.
*/
private static class State extends EnumeratedValues {
public static final State instance = new State();
private State() {
super(new String[] {"init","loading","ready","failed"});
}
public static final int Initial = 0;
public static final int Loading = 1;
public static final int Ready = 2;
public static final int Failed = 3;
}
private static int nextId = 0; // generator for "id"
private final int id; // for debug
private String desc;
final Aggregation aggregation;
final RolapStar.Measure measure;
final Aggregation.Axis[] axes;
private SegmentDataset data;
private final CellKey cellKey; // workspace
/** State of the segment, values are described by {@link State}. */
private int state;
/**
* Creates a <code>Segment</code>; it's not loaded yet.
*
* @param aggregation The aggregation that this <code>Segment</code>
* belongs to
* @param constraintses For each column, either an array of values
* to fetch or null, indicating that the column is unconstrained
**/
Segment(Aggregation aggregation,
RolapStar.Measure measure,
ColumnConstraint[][] constraintses,
Aggregation.Axis[] axes) {
this.id = nextId++;
this.aggregation = aggregation;
this.measure = measure;
this.axes = axes;
this.cellKey = new CellKey(new int[axes.length]);
this.state = State.Loading;
}
/**
* Sets the data, and notifies any threads which are blocked in
* {@link #waitUntilLoaded}.
*/
synchronized void setData(SegmentDataset data,
Collection pinnedSegments) {
Util.assertTrue(this.data == null);
Util.assertTrue(this.state == State.Loading);
this.data = data;
this.state = State.Ready;
notifyAll();
}
/**
* If this segment is still loading, signals that it failed to load, and
* notifies any threads which are blocked in {@link #waitUntilLoaded}.
*/
synchronized void setFailed() {
switch (state) {
case State.Loading:
Util.assertTrue(this.data == null);
this.state = State.Failed;
notifyAll();
break;
case State.Ready:
// The segment loaded just fine.
break;
default:
throw State.instance.badValue(state);
}
}
public boolean isReady() {
return (state == State.Ready);
}
private String makeDescription() {
StringBuffer buf = new StringBuffer(64);
buf.append("Segment #");
buf.append(id);
buf.append(" {measure=");
buf.append(measure.getAggregator().getExpression(
measure.getExpression().getGenericExpression()));
RolapStar.Column[] columns = aggregation.getColumns();
for (int i = 0; i < columns.length; i++) {
buf.append(", ");
buf.append(columns[i].getExpression().getGenericExpression());
ColumnConstraint[] constraints = axes[i].getConstraints();
if (constraints == null) {
buf.append("=any");
} else {
buf.append("={");
for (int j = 0; j < constraints.length; j++) {
if (j > 0) {
buf.append(", ");
}
buf.append(constraints[j].getValue().toString());
}
buf.append('}');
}
}
buf.append('}');
return buf.toString();
}
public String toString() {
if (this.desc == null) {
this.desc = makeDescription();
}
return this.desc;
}
/**
* Retrieves the value at the location identified by
* <code>keys</code>. Returns {@link Util#nullValue} if the cell value
* is null (because no fact table rows met those criteria), and
* <code>null</code> if the value is not supposed to be in this segment
* (because one or more of the keys do not pass the axis criteria).
*
* <p>Note: Must be called from a synchronized context, because uses the
* <code>cellKey[]</code> as workspace.</p>
**/
Object get(Object[] keys) {
Util.assertTrue(keys.length == axes.length);
int missed = 0;
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
Integer integer = axes[i].getOffset(key);
if (integer == null) {
if (axes[i].contains(key)) {
// see whether this segment should contain this value
missed++;
continue;
} else {
// this value should not appear in this segment; we
// should be looking in a different segment
return null;
}
}
cellKey.ordinals[i] = integer.intValue();
}
if (missed > 0) {
// the value should be in this segment, but isn't, because one
// or more of its keys does have any values
return Util.nullValue;
} else {
Object o = data.get(cellKey);
if (o == null) {
o = Util.nullValue;
}
return o;
}
}
/**
* Returns whether the given set of key values will be in this segment
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?