Skip to content

Commit

Permalink
MONDRIAN: Implement "aggregate" builtin function.
Browse files Browse the repository at this point in the history
[git-p4: depot-paths = "//open/mondrian/": change = 310]
  • Loading branch information
julianhyde committed Feb 19, 2003
1 parent 09484fc commit 4b4fb3e
Show file tree
Hide file tree
Showing 10 changed files with 392 additions and 100 deletions.
8 changes: 7 additions & 1 deletion src/main/mondrian/olap/Evaluator.java
Expand Up @@ -57,6 +57,12 @@ public interface Evaluator {
* Returns parent evaluator.
*/
Evaluator getParent();
};
/**
* Retrieves the value of property <code>name</code>. If more than one
* member in the current context defines that property, the one with the
* highest solve order has precedence.
*/
Object getProperty(String name);
}

// End Evaluator.java
16 changes: 16 additions & 0 deletions src/main/mondrian/olap/Property.java
Expand Up @@ -24,6 +24,22 @@ public abstract class Property {
public static final int TYPE_NUMERIC = 1;
public static final int TYPE_BOOLEAN = 2;

/** The name of the property which holds the parsed format string. Internal. **/
public static final String PROPERTY_FORMAT_EXP = "$format_exp";
/** The name of the property which holds the aggregation type. This is
* automatically set for stored measures, based upon their SQL
* aggregation. **/
public static final String PROPERTY_AGGREGATION_TYPE = "$aggregation_type";

/**
* A list of the names of properties which have special meaning to the
* Mondrian system.
*/
public static final String[] systemPropertyNames = {
PROPERTY_FORMAT_EXP,
PROPERTY_AGGREGATION_TYPE,
};

protected Property(String name, int type) {
this.name = name;
this.type = type;
Expand Down
244 changes: 215 additions & 29 deletions src/main/mondrian/olap/fun/BuiltinFunTable.java

Large diffs are not rendered by default.

53 changes: 39 additions & 14 deletions src/main/mondrian/olap/fun/FunUtil.java
Expand Up @@ -648,7 +648,6 @@ static Object covariance(Evaluator evaluator, Vector members, ExpBase exp1, ExpB
SetWrapper sw2 = evaluateSet(evaluator.push(), members, exp2);
//todo: because evaluateSet does not add nulls to the SetWrapper, this solution may
//lead to mismatched vectors and is therefore not robust
// return _covariance(sw1, sw2, biased);
return _covariance(sw1, sw2, biased);
}

Expand All @@ -674,10 +673,9 @@ private static Object _covariance(SetWrapper sw1, SetWrapper sw2, boolean biased
static Object stdev(Evaluator evaluator, Vector members, ExpBase exp, boolean biased) {
Object o = var(evaluator, members, exp, biased);
if (o instanceof Double) {
return new Double(Math.sqrt(((Double) o).doubleValue()));
}
else {
return o;
return new Double(Math.sqrt(((Double) o).doubleValue()));
} else {
return o;
}
}

Expand Down Expand Up @@ -724,27 +722,54 @@ static Object sum(Evaluator evaluator, Vector members, ExpBase exp) {
}
}

static Object count(Vector members, boolean includeEmpty) {
if (includeEmpty) {
return new Double(members.size());
} else {
int retval = 0;
for (int i = 0; i < members.size(); i++) {
final Object member = members.elementAt(i);
if (member != Util.nullValue && member != null) {
retval++;
}
}
return new Double(retval);
}
}

static Object aggregate(
Evaluator evaluator, String aggregator, Vector members, ExpBase exp) {
if (aggregator.equals("sum")) {
return sum(evaluator, members, exp);
} else if (aggregator.equals("count")) {
return count(members, false);
} else if (aggregator.equals("avg")) {
return avg(evaluator, members, exp);
} else if (aggregator.equals("min")) {
return min(evaluator, members, exp);
} else if (aggregator.equals("max")) {
return max(evaluator, members, exp);
} else {
throw newEvalException(null, "Unknown aggregator '" + aggregator + "'");
}
}

/**
* Evaluates <code>exp</code> (if defined) over <code>members</code> to
* generate a <code>Vector</code> of <code>SetWrapper</code>, which contains
* a <code>Double</code> value and meta information, unlike
* <code>evaluateMembers</code>, which only produces values
*
* @pre exp != null
*/
static SetWrapper evaluateSet(Evaluator evaluator, Vector members, ExpBase exp) {
Util.assertPrecondition(exp != null, "exp != null");
// todo: treat constant exps as evaluateMembers() does
SetWrapper retval = new SetWrapper();
for (int i = 0, count = members.size(); i < count; i++) {
Member member = (Member) members.elementAt(i);
evaluator.setContext(member);
Object o = null;
if (exp != null) {
o = exp.evaluateScalar(evaluator);
}
else { //is this right?
evaluator.setContext(member);
o = evaluator.evaluateCurrent();
}

Object o = exp.evaluateScalar(evaluator);
if (o == null || o == Util.nullValue) {
retval.nullCount++;
} else if (o instanceof Throwable) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/rolap/RolapCalculatedMember.java
Expand Up @@ -43,7 +43,7 @@ public class RolapCalculatedMember extends RolapMember {
if (formatExp == null) {
formatExp = Literal.emptyString;
}
setProperty(PROPERTY_FORMAT_EXP, formatExp);
setProperty(Property.PROPERTY_FORMAT_EXP, formatExp);
}

// override RolapMember
Expand Down
40 changes: 16 additions & 24 deletions src/main/mondrian/rolap/RolapEvaluator.java
Expand Up @@ -30,7 +30,6 @@ class RolapEvaluator implements Evaluator
Evaluator parent;
CellReader cellReader;
int depth;
private static final RolapMember[] emptyMembers = {};

RolapEvaluator(RolapCube cube, RolapConnection connection)
{
Expand Down Expand Up @@ -80,29 +79,27 @@ public Evaluator getParent() {
}

public Evaluator push(Member[] members) {
RolapMember[] cloneCurrentMembers = new RolapMember[
this.currentMembers.length];
for (int i = 0; i < this.currentMembers.length; i++) {
cloneCurrentMembers[i] = this.currentMembers[i];
}
for (int i = 0; i < members.length; i++) {
RolapMember member = (RolapMember) members[i];
int ordinal = member.getDimension().getOrdinal(cube);
cloneCurrentMembers[ordinal] = member;
}
return new RolapEvaluator(cube, connection, cloneCurrentMembers, this);
final RolapEvaluator evaluator = _push();
evaluator.setContext(members);
return evaluator;
}

public Evaluator push(Member member) {
final RolapEvaluator evaluator = _push();
evaluator.setContext(member);
return evaluator;
}

public Evaluator push() {
return push(emptyMembers);
return _push();
}

public Evaluator push(Member member) {
return push(new Member[] {member});
private final RolapEvaluator _push() {
RolapMember[] cloneCurrentMembers = (RolapMember[]) this.currentMembers.clone();
return new RolapEvaluator(cube, connection, cloneCurrentMembers, this);
}

public Evaluator pop()
{
public Evaluator pop() {
return parent;
}
public Object xx(Literal literal) {
Expand Down Expand Up @@ -199,12 +196,7 @@ private String getContextString() {
return sb.toString();
}

/**
* Retrieves the value of property <code>name</code>. If more than one
* member in the current context defines that property, the one with the
* highest solve order has precedence.
*/
Object getProperty(String name)
public Object getProperty(String name)
{
Object o = null;
int maxSolve = Integer.MIN_VALUE;
Expand All @@ -223,7 +215,7 @@ Object getProperty(String name)
}
private String getFormatString()
{
Exp formatExp = (Exp) getProperty(RolapMember.PROPERTY_FORMAT_EXP);
Exp formatExp = (Exp) getProperty(Property.PROPERTY_FORMAT_EXP);
Object o = formatExp.evaluate(this);
return o.toString();
}
Expand Down
7 changes: 2 additions & 5 deletions src/main/mondrian/rolap/RolapMeasure.java
Expand Up @@ -11,10 +11,7 @@
*/

package mondrian.rolap;
import mondrian.olap.MondrianDef;
import mondrian.olap.Evaluator;
import mondrian.olap.Literal;
import mondrian.olap.Exp;
import mondrian.olap.*;

/**
* todo:
Expand Down Expand Up @@ -42,7 +39,7 @@ abstract class RolapMeasure extends RolapMember
}
RolapConnection connection = ((RolapDimension) getDimension()).schema.getInternalConnection();
Exp formatExp = connection.parseExpression("'" + formatString + "'");
setProperty(PROPERTY_FORMAT_EXP, formatExp);
setProperty(Property.PROPERTY_FORMAT_EXP, formatExp);
}

}
Expand Down
4 changes: 2 additions & 2 deletions src/main/mondrian/rolap/RolapMember.java
Expand Up @@ -87,15 +87,15 @@ public void setName(String name)
{
throw new Error("unsupported");
}
/** The name of the property which holds the parsed format string. Internal. **/
public static final String PROPERTY_FORMAT_EXP = "$format_exp";
/** Sets a property of this member to a given value. */
public synchronized void setProperty(String name, Object value) {
if (mapPropertyNameToValue.isEmpty()) {
// the empty map is shared and immutable; create our own
mapPropertyNameToValue = new HashMap();
}
mapPropertyNameToValue.put(name, value);
}

public synchronized Object getPropertyValue(String name) {
return mapPropertyNameToValue.get(name);
}
Expand Down
16 changes: 15 additions & 1 deletion src/main/mondrian/rolap/RolapStoredMeasure.java
Expand Up @@ -13,6 +13,7 @@
package mondrian.rolap;
import mondrian.olap.Util;
import mondrian.olap.MondrianDef;
import mondrian.olap.Property;

/**
* todo:
Expand All @@ -36,8 +37,21 @@ class RolapStoredMeasure extends RolapMeasure
super(parentMember, level, name, formatString);
this.cube = cube;
this.expression = expression;
//Util.assertTrue(aggregator.equals("sum") || aggregator.equals("count"));
Util.assertTrue(aggregatorIsValid(aggregator));
this.aggregator = aggregator;
setProperty(Property.PROPERTY_AGGREGATION_TYPE, aggregator);
}

private static final String[] aggregators = new String[] {
"sum", "count", "min", "max", "avg"
};
private static boolean aggregatorIsValid(String aggregator) {
for (int i = 0; i < aggregators.length; i++) {
if (aggregator.equals(aggregators[i])) {
return true;
}
}
return false;
}

RolapStoredMeasure(
Expand Down

0 comments on commit 4b4fb3e

Please sign in to comment.