Skip to content

Commit

Permalink
MONDRIAN: Fix testCmNativeFilter() and testOrderBug712702_Original()
Browse files Browse the repository at this point in the history
[git-p4: depot-paths = "//open/mondrian/": change = 8013]
  • Loading branch information
Andreas Voss committed Oct 27, 2006
1 parent 781a8a2 commit 1683345
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 28 deletions.
12 changes: 2 additions & 10 deletions src/main/mondrian/rolap/RolapNativeFilter.java
Expand Up @@ -109,17 +109,9 @@ NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args
}
LOGGER.debug("using native filter");

// Override current members in position by default members in
// hierarchies which are involved in this filter
RolapEvaluator newEvaluator = (RolapEvaluator) evaluator.push();
for (int i = 0; i < cargs.length; i++) {
Hierarchy hierarchy = cargs[i].getLevel().getHierarchy();
Member defaultMember =
schemaReader.getHierarchyDefaultMember(hierarchy);
newEvaluator.setContext(defaultMember);
}
evaluator = overrideContext(evaluator, cargs, sql.getStoredMeasure());

TupleConstraint constraint = new FilterConstraint(cargs, newEvaluator, filterExpr);
TupleConstraint constraint = new FilterConstraint(cargs, evaluator, filterExpr);
return new SetEvaluator(cargs, schemaReader, constraint);
} catch (SQLException e) {
throw Util.newInternal(e, "RolapNativeFilter");
Expand Down
27 changes: 27 additions & 0 deletions src/main/mondrian/rolap/RolapNativeSet.java
Expand Up @@ -14,6 +14,7 @@

import mondrian.olap.*;
import mondrian.rolap.TupleReader.MemberBuilder;
import mondrian.rolap.agg.AggregationManager;
import mondrian.rolap.cache.HardSmartCache;
import mondrian.rolap.cache.SmartCache;
import mondrian.rolap.cache.SoftSmartCache;
Expand Down Expand Up @@ -608,6 +609,32 @@ void useHardCache(boolean hard) {
cache = new SoftSmartCache();
}
}

/**
* Override current members in position by default members in
* hierarchies which are involved in this filter/topcount.
* Stores the RolapStoredMeasure into the context because that is needed to
* generate a cell request to constraint the sql.
*
* The current context may contain a calculated measure, this measure
* was translated into an sql condition (filter/topcount). The measure
* is not used to constrain the result but only to access the star.
*
* @see RolapAggregationManager#makeRequest(Member[], boolean, boolean)
*/
protected RolapEvaluator overrideContext(RolapEvaluator evaluator, CrossJoinArg[] cargs, RolapStoredMeasure storedMeasure) {
SchemaReader schemaReader = evaluator.getSchemaReader();
RolapEvaluator newEvaluator = (RolapEvaluator) evaluator.push();
for (int i = 0; i < cargs.length; i++) {
Hierarchy hierarchy = cargs[i].getLevel().getHierarchy();
Member defaultMember =
schemaReader.getHierarchyDefaultMember(hierarchy);
newEvaluator.setContext(defaultMember);
}
if (storedMeasure != null)
newEvaluator.setContext(storedMeasure);
return newEvaluator;
}
}

// End RolapNativeSet.java
32 changes: 31 additions & 1 deletion src/main/mondrian/rolap/RolapNativeSql.java
Expand Up @@ -32,6 +32,30 @@ public class RolapNativeSql {
CompositeSqlCompiler numericCompiler;
CompositeSqlCompiler booleanCompiler;

RolapStoredMeasure storedMeasure;

/**
* We remember one of the measures so we can generate
* the constraints from RolapAggregationManager. Also
* make sure all measures live in the same star.
*
* @see RolapAggregationManager#makeRequest(Member[], boolean, boolean)
*/
private boolean saveStoredMeasure(RolapStoredMeasure m) {
if (storedMeasure != null) {
RolapStar star1 = getStar(storedMeasure);
RolapStar star2 = getStar(m);
if (star1 != star2)
return false;
}
this.storedMeasure = m;
return true;
}

private RolapStar getStar(RolapStoredMeasure m) {
return ((RolapStar.Measure )m.getStarMeasure()).getStar();
}

/**
* translates an Expr into SQL
* @author av
Expand Down Expand Up @@ -131,6 +155,8 @@ public String compile(Exp exp) {
if (measure.isCalculated()) {
return null; // ??
}
if (!saveStoredMeasure(measure))
return null;
String exprInner = measure.getMondrianDefExpression().getExpression(sqlQuery);
String expr = measure.getAggregator().getExpression(exprInner);
if (dialect.isDB2()) {
Expand All @@ -139,7 +165,7 @@ public String compile(Exp exp) {
return expr;
}

public String toString() {
public String toString() {
return "StoredMeasureSqlCompiler";
}
}
Expand Down Expand Up @@ -412,6 +438,10 @@ public String generateFilterCondition(Exp exp) {
return booleanCompiler.compile(exp);
}

public RolapStoredMeasure getStoredMeasure() {
return storedMeasure;
}

}

// End RolapNativeSql.java
1 change: 1 addition & 0 deletions src/main/mondrian/rolap/RolapNativeTopCount.java
Expand Up @@ -131,6 +131,7 @@ NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args
}
}
LOGGER.debug("using native topcount");
evaluator = overrideContext(evaluator, cargs, sql.getStoredMeasure());

TupleConstraint constraint = new TopCountConstraint(cargs, evaluator, orderByExpr);
SetEvaluator sev = new SetEvaluator(cargs, schemaReader, constraint);
Expand Down
11 changes: 7 additions & 4 deletions src/main/mondrian/rolap/SqlConstraintUtils.java
Expand Up @@ -51,16 +51,19 @@ public static void addContextConstraint(

Member[] members = e.getMembers();
if (strict) {
assert !containsCalculatedMember(members) :
"can not restrict SQL to calculated Members";
if (containsCalculatedMember(members)) {
throw Util.newInternal("can not restrict SQL to calculated Members");
}
} else {
members = removeCalculatedMembers(members);
}

CellRequest request =
RolapAggregationManager.makeRequest(members, false, false);
if (request == null) {
assert !strict : "CellRequest is null - why?";
if (strict) {
throw Util.newInternal("CellRequest is null - why?");
}
// One or more of the members was null or calculated, so the
// request is impossible to satisfy.
return;
Expand Down Expand Up @@ -200,7 +203,7 @@ public static void addMemberConstraint(
String q = level.getKeyExp().getExpression(sqlQuery);
ColumnConstraint[] cc = getColumnConstraints(c);

if (cc.length >= MondrianProperties.instance().MaxConstraints.get()){
if (!strict && cc.length >= MondrianProperties.instance().MaxConstraints.get()){
// Simply get them all, do not create where-clause.
// Below are two alternative approaches (and code). They
// both have problems.
Expand Down
3 changes: 1 addition & 2 deletions testsrc/main/mondrian/olap/fun/FunctionTest.java
Expand Up @@ -4923,8 +4923,7 @@ public void testOrderBug712702_Simplified() {
"Row #0: 266,773\n"));
}

// TODO: Fix NPE in SqlConstraintUtils.addContextConstraint, and re-enable
public void _testOrderBug712702_Original() {
public void testOrderBug712702_Original() {
assertQueryReturns(
"with member [Measures].[Average Unit Sales] as 'Avg(Descendants([Time].CurrentMember, [Time].[Month]), \n" +
"[Measures].[Unit Sales])' \n" +
Expand Down
76 changes: 65 additions & 11 deletions testsrc/main/mondrian/rolap/NonEmptyTest.java
Expand Up @@ -54,6 +54,7 @@ public NonEmptyTest() {
public NonEmptyTest(String name) {
super(name);
}

/**
* must not use native sql optimization because it chooses the wrong RolapStar
* in SqlContextConstraint/SqlConstraintUtils.
Expand All @@ -79,24 +80,77 @@ public void testNativeFilter() {
18,
"select {[Measures].[Store Sales]} ON COLUMNS, "
+ "Order(Filter(Descendants([Customers].[All Customers].[USA].[CA], [Customers].[Name]), ([Measures].[Store Sales] > 200.0)), [Measures].[Store Sales], DESC) ON ROWS "
+ "from [Sales] " + "where ([Time].[1997])");
+ "from [Sales] "
+ "where ([Time].[1997])");
}

/**
* Executes a Filter() whose condition contains a calculated member.
*/
public void _testCmNativeFilter() {
public void testCmNativeFilter() {
String mdx = "with member [Measures].[Rendite] as '([Measures].[Store Sales] - [Measures].[Store Cost]) / [Measures].[Store Cost]' "
+ "select NON EMPTY {[Measures].[Unit Sales], [Measures].[Store Cost], [Measures].[Rendite], [Measures].[Store Sales]} ON COLUMNS, "
+ "NON EMPTY Order(Filter([Product].[Product Name].Members, ([Measures].[Rendite] > 1.8)), [Measures].[Rendite], BDESC) ON ROWS "
+ "from [Sales] "
+ "where ([Store].[All Stores].[USA].[CA], [Time].[1997])";

if (!MondrianProperties.instance().EnableNativeFilter.get()) {
return;
assertQueryReturns(
mdx,
"Axis #0:" + nl +
"{[Store].[All Stores].[USA].[CA], [Time].[1997]}" + nl +
"Axis #1:" + nl +
"{[Measures].[Unit Sales]}" + nl +
"{[Measures].[Store Cost]}" + nl +
"{[Measures].[Store Sales]}" + nl +
"{[Measures].[Rendite]}" + nl +
"Axis #2:" + nl +
"{[Product].[All Products].[Food].[Baking Goods].[Jams and Jellies].[Peanut Butter].[Plato].[Plato Extra Chunky Peanut Butter]}" + nl +
"{[Product].[All Products].[Food].[Snack Foods].[Snack Foods].[Popcorn].[Horatio].[Horatio Buttered Popcorn]}" + nl +
"{[Product].[All Products].[Food].[Canned Foods].[Canned Tuna].[Tuna].[Better].[Better Canned Tuna in Oil]}" + nl +
"{[Product].[All Products].[Food].[Produce].[Fruit].[Fresh Fruit].[High Top].[High Top Cantelope]}" + nl +
"{[Product].[All Products].[Non-Consumable].[Household].[Electrical].[Lightbulbs].[Denny].[Denny 75 Watt Lightbulb]}" + nl +
"{[Product].[All Products].[Food].[Breakfast Foods].[Breakfast Foods].[Cereal].[Johnson].[Johnson Oatmeal]}" + nl +
"{[Product].[All Products].[Drink].[Alcoholic Beverages].[Beer and Wine].[Wine].[Portsmouth].[Portsmouth Light Wine]}" + nl +
"{[Product].[All Products].[Food].[Produce].[Vegetables].[Fresh Vegetables].[Ebony].[Ebony Squash]}" + nl +
"Row #0: 42" + nl +
"Row #0: 24.06" + nl +
"Row #0: 70.56" + nl +
"Row #0: 1.93" + nl +
"Row #1: 36" + nl +
"Row #1: 29.02" + nl +
"Row #1: 84.60" + nl +
"Row #1: 1.91" + nl +
"Row #2: 39" + nl +
"Row #2: 20.55" + nl +
"Row #2: 58.50" + nl +
"Row #2: 1.85" + nl +
"Row #3: 25" + nl +
"Row #3: 21.76" + nl +
"Row #3: 61.75" + nl +
"Row #3: 1.84" + nl +
"Row #4: 43" + nl +
"Row #4: 59.62" + nl +
"Row #4: 168.99" + nl +
"Row #4: 1.83" + nl +
"Row #5: 34" + nl +
"Row #5: 7.20" + nl +
"Row #5: 20.40" + nl +
"Row #5: 1.83" + nl +
"Row #6: 36" + nl +
"Row #6: 33.10" + nl +
"Row #6: 93.60" + nl +
"Row #6: 1.83" + nl +
"Row #7: 46" + nl +
"Row #7: 28.34" + nl +
"Row #7: 79.58" + nl +
"Row #7: 1.81" + nl
);
return;

}
checkNative(
32,
8,
"with member [Measures].[Rendite] as 'IIf(([Measures].[Store Cost] = 0.0), 1.0, (([Measures].[Store Sales] - [Measures].[Store Cost]) / [Measures].[Store Cost]))' "
+ "select NON EMPTY {[Measures].[Unit Sales], [Measures].[Store Cost], [Measures].[Store Sales], [Measures].[Rendite]} ON COLUMNS, "
+ "NON EMPTY Order(Filter([Product].[Product Name].Members, ([Measures].[Rendite] > 1.8)), [Measures].[Rendite], BDESC) ON ROWS "
+ "from [Sales] "
+ "where ([Store].[All Stores].[USA].[CA], [Time].[1997])");
else
checkNative(32, 8, mdx);
}

/**
Expand Down

0 comments on commit 1683345

Please sign in to comment.