Skip to content

Commit

Permalink
MONDRIAN: store a queryStartTime in RolapevaluatorRoot; make CurrentD…
Browse files Browse the repository at this point in the history
…ateMember cache computed result.

[git-p4: depot-paths = "//open/mondrian/": change = 9827]
  • Loading branch information
Rushan Chen committed Aug 30, 2007
1 parent 05948ea commit 9437cb6
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 24 deletions.
6 changes: 6 additions & 0 deletions src/main/mondrian/olap/Evaluator.java
Expand Up @@ -16,6 +16,7 @@
import mondrian.calc.ParameterSlot;
import java.util.List;
import java.util.Locale;
import java.util.Date;

/**
* An <code>Evaluator</code> holds the context necessary to evaluate an
Expand All @@ -37,6 +38,11 @@ public interface Evaluator {
*/
Query getQuery();

/**
* Returns the start time of the current query.
*/
Date getQueryStartTime();

/**
* Creates a new Evaluator with each given member overriding the context of
* the current Evaluator for its dimension. Other dimensions retain the
Expand Down
28 changes: 28 additions & 0 deletions src/main/mondrian/olap/Util.java
Expand Up @@ -33,6 +33,7 @@
import mondrian.olap.fun.*;
import mondrian.olap.type.Type;
import mondrian.resource.MondrianResource;
import mondrian.spi.UserDefinedFunction;
import mondrian.mdx.*;
import mondrian.util.UtilCompatible;
import mondrian.util.Pair;
Expand Down Expand Up @@ -1967,6 +1968,33 @@ public static <E extends Enum<E>> Set<E> enumSetAllOf(Class<E> elementType) {
public static BigDecimal makeBigDecimalFromDouble(double d) {
return compatible.makeBigDecimalFromDouble(d);
}

/**
* Creates a new udf instance from the given udf class.
*
* @param udfClass the class to create new instance for
* @return an instance of UserDefinedFunction
*/
public static UserDefinedFunction createUdf(Class<?> udfClass) {
// Instantiate class with default constructor.
UserDefinedFunction udf;
String className = udfClass.getName();

try {
udf = (UserDefinedFunction) udfClass.newInstance();
} catch (InstantiationException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
} catch (IllegalAccessException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
} catch (ClassCastException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
}

return udf;
}
}

// End Util.java
16 changes: 2 additions & 14 deletions src/main/mondrian/olap/fun/GlobalFunTable.java
Expand Up @@ -112,7 +112,7 @@ private Collection<String> lookupUdfImplClasses() {
}
return classNames;
}

/**
* Defines a user-defined function in this table.
*
Expand All @@ -132,19 +132,7 @@ private void defineUdf(String className) {
}

// Instantiate class with default constructor.
final UserDefinedFunction udf;
try {
udf = (UserDefinedFunction) udfClass.newInstance();
} catch (InstantiationException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
} catch (IllegalAccessException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
} catch (ClassCastException e) {
throw MondrianResource.instance().UdfClassWrongIface.ex("",
className, UserDefinedFunction.class.getName());
}
final UserDefinedFunction udf = Util.createUdf(udfClass);

// Validate function.
validateFunction(udf);
Expand Down
3 changes: 2 additions & 1 deletion src/main/mondrian/olap/fun/UdfResolver.java
Expand Up @@ -136,6 +136,7 @@ public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final Calc scalarCalc = compiler.compileScalar(arg, true);
expCalcs[i] = new CalcExp(calc, scalarCalc);
}

return new CalcImpl(call, calcs, udf, expCalcs);
}
}
Expand All @@ -155,7 +156,7 @@ public CalcImpl(
UserDefinedFunction.Argument[] args) {
super(call);
this.calcs = calcs;
this.udf = udf;
this.udf = Util.createUdf(udf.getClass());
this.args = args;
}

Expand Down
17 changes: 16 additions & 1 deletion src/main/mondrian/rolap/RolapEvaluator.java
Expand Up @@ -187,12 +187,14 @@ protected static class RolapEvaluatorRoot {
final SchemaReader schemaReader;
final Map<Exp, Calc> compiledExps = new HashMap<Exp, Calc>();
final private Query query;

final private Date queryStartTime;

public RolapEvaluatorRoot(Query query) {
this.query = query;
this.cube = (RolapCube) query.getCube();
this.connection = (RolapConnection) query.getConnection();
this.schemaReader = query.getSchemaReader(true);
this.queryStartTime = new Date();
}

/**
Expand Down Expand Up @@ -281,6 +283,15 @@ public final void clearResultCache(boolean clearValidResult) {
}
tmpExpResultCache.clear();
}

/**
* Get query start time.
*
* @return the query start time
*/
public Date getQueryStartTime() {
return queryStartTime;
}
}

protected final Logger getLogger() {
Expand Down Expand Up @@ -315,6 +326,10 @@ public SchemaReader getSchemaReader() {
return root.schemaReader;
}

public Date getQueryStartTime() {
return root.getQueryStartTime();
}

public final RolapEvaluator push(Member[] members) {
final RolapEvaluator evaluator = _push();
evaluator.setContext(members);
Expand Down
20 changes: 13 additions & 7 deletions src/main/mondrian/udf/CurrentDateMemberUdf.java
Expand Up @@ -37,15 +37,20 @@
* @version $Id$
*/
public class CurrentDateMemberUdf implements UserDefinedFunction {

private Object resultDateMember = null;

public Object execute(Evaluator evaluator, Argument[] arguments) {

if (resultDateMember != null) {
return resultDateMember;
}

// determine the current date
Object formatArg = arguments[1].evaluateScalar(evaluator);

final Locale locale = Locale.getDefault();
final Format format = new Format((String) formatArg, locale);
Date currDate = new Date();
Date currDate = evaluator.getQueryStartTime();
String currDateStr = format.format(currDate);

// determine the match type
Expand All @@ -58,21 +63,22 @@ public Object execute(Evaluator evaluator, Argument[] arguments) {
}

List<Id.Segment> uniqueNames = Util.parseIdentifier(currDateStr);
Object retDate =
resultDateMember =
evaluator.getSchemaReader().getMemberByUniqueName(
uniqueNames, false, matchType);
if (retDate != null) {
return retDate;
if (resultDateMember != null) {
return resultDateMember;
}

// if there is no matching member, return the null member for
// the specified dimension/hierarchy
Object arg0 = arguments[0].evaluate(evaluator);
if (arg0 instanceof Hierarchy) {
return ((Hierarchy) arg0).getNullMember();
resultDateMember = ((Hierarchy) arg0).getNullMember();
} else {
return ((Dimension) arg0).getHierarchy().getNullMember();
resultDateMember = ((Dimension) arg0).getHierarchy().getNullMember();
}
return resultDateMember;
}

public String getDescription() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/udf/CurrentDateStringUdf.java
Expand Up @@ -34,7 +34,7 @@ public Object execute(Evaluator evaluator, Argument[] arguments) {

final Locale locale = Locale.getDefault();
final Format format = new Format((String) arg, locale);
Date currDate = new Date();
Date currDate = evaluator.getQueryStartTime();
return format.format(currDate);
}

Expand Down
14 changes: 14 additions & 0 deletions testsrc/main/mondrian/test/UdfTest.java
Expand Up @@ -675,8 +675,22 @@ public void testAnotherMemberFun() {
"Row #0: 409,035.59" + nl);
}


public void testCachingCurrentDate() {
assertQueryReturns(
"SELECT {filter([Time].[Month].Members, " +
"[Time].CurrentMember in {CurrentDateMember([Time], '[\"Time\"]\\.[yyyy]\\.[\"Q\"q]\\.[m]', BEFORE)})} ON ROWS " +
"from [Sales]",
"Axis #0:" + nl +
"{}" + nl +
"Axis #1:" + nl +
"{[Time].[1998].[Q4].[12]}" + nl +
"Row #0: " + nl);
}

// ~ Inner classes --------------------------------------------------------


/**
* A simple user-defined function which adds one to its argument.
*/
Expand Down

0 comments on commit 9437cb6

Please sign in to comment.