From 7e31ed001f565caba65c3ee73e5754ed8d6622eb Mon Sep 17 00:00:00 2001 From: pstoellberger Date: Thu, 24 Jan 2013 13:34:07 +0100 Subject: [PATCH] add Filter() for QueryAxis --- .gitignore | 2 + src/org/olap4j/query/Olap4jNodeConverter.java | 22 +++- src/org/olap4j/query/QueryAxis.java | 26 ++++- testsrc/org/olap4j/OlapTest.java | 108 ++++++++++++++++++ 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 164f7d0..c64393a 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ src/org/olap4j/mdx/parser/impl/SimpleCharStream.java src/org/olap4j/mdx/parser/impl/Token.java src/org/olap4j/mdx/parser/impl/TokenMgrError.java testlib/ +eclipse-bin/ + diff --git a/src/org/olap4j/query/Olap4jNodeConverter.java b/src/org/olap4j/query/Olap4jNodeConverter.java index 39dc73b..e0a9e6a 100644 --- a/src/org/olap4j/query/Olap4jNodeConverter.java +++ b/src/org/olap4j/query/Olap4jNodeConverter.java @@ -299,6 +299,22 @@ private static AxisNode toOlap4j(QueryAxis axis) { } } + ParseTreeNode filteredNode = null; + if (axis.getFilterCondition() != null) { + LiteralNode conditionNode = + LiteralNode.createSymbol( + null, + axis.getFilterCondition()); + filteredNode = + new CallNode( + null, + "Filter", + Syntax.Function, + callNode, + conditionNode); + } else { + filteredNode = callNode; + } // We might need to limit the axis set ParseTreeNode limitedNode = null; if (axis.getLimitFunction() != null) { @@ -318,7 +334,7 @@ private static AxisNode toOlap4j(QueryAxis axis) { null, axis.getLimitFunction().toString(), Syntax.Function, - callNode, + filteredNode, n, evaluatorNode); } else { @@ -327,11 +343,11 @@ private static AxisNode toOlap4j(QueryAxis axis) { null, axis.getLimitFunction().toString(), Syntax.Function, - callNode, + filteredNode, n); } } else { - limitedNode = callNode; + limitedNode = filteredNode; } // We might need to sort the whole axis. ParseTreeNode sortedNode = null; diff --git a/src/org/olap4j/query/QueryAxis.java b/src/org/olap4j/query/QueryAxis.java index 606d770..ade1712 100644 --- a/src/org/olap4j/query/QueryAxis.java +++ b/src/org/olap4j/query/QueryAxis.java @@ -47,6 +47,7 @@ public class QueryAxis extends QueryNodeImpl { private LimitFunction limitFunction = null; private BigDecimal limitFunctionN = null; private String limitFunctionSortLiteral = null; + private String filterCondition = null; /** * Creates a QueryAxis. * @@ -418,7 +419,30 @@ public BigDecimal getLimitFunctionN() { */ public String getLimitFunctionSortLiteral() { return limitFunctionSortLiteral; } - + + /** + * Filter the axis using the given condition before TopCount / Order + * are applied + * @param filterCondition - the condition used for Filter() + */ + public void filter(String filterCondition) { + this.filterCondition = filterCondition; + } + + /** + * Returns the Filter Condition used to filter the axis set + * @return filter condition + */ + public String getFilterCondition() { + return this.filterCondition; + } + + /** + * Clears the filter for this axis + */ + public void clearFilter() { + this.filterCondition = null; + } } diff --git a/testsrc/org/olap4j/OlapTest.java b/testsrc/org/olap4j/OlapTest.java index 849169c..d1f91bc 100644 --- a/testsrc/org/olap4j/OlapTest.java +++ b/testsrc/org/olap4j/OlapTest.java @@ -1524,6 +1524,114 @@ public void testLimitFunction() throws Exception { + "Row #4: 3,836\n" + "Row #5: 3,064\n", resultsString); + } + public void testFilter() throws Exception { + Cube cube = getFoodmartCube("Sales"); + if (cube == null) { + fail("Could not find Sales cube"); + } + // Setup a base query. + Query query = new Query("my query", cube); + QueryDimension productDimension = query.getDimension("Product"); + NamedList productLevels = + productDimension.getDimension() + .getDefaultHierarchy().getLevels(); + + Level productLevel = productLevels.get("Product Category"); + productDimension.include(productLevel); + + QueryDimension measuresDimension = query.getDimension("Measures"); + measuresDimension.include(nameList("Measures", "Sales Count")); + + query.getAxis(Axis.ROWS).addDimension(productDimension); + query.getAxis(Axis.COLUMNS).addDimension(measuresDimension); + + query.getAxis(Axis.ROWS).filter("InStr(Product.CurrentMember.Name, 'Beverages') > 0"); + + query.validate(); + + // Validate the generated MDX + String mdxString = query.getSelect().toString(); + TestContext.assertEqualsVerbose( + "SELECT\n" + + "{[Measures].[Sales Count]} ON COLUMNS,\n" + + "Filter({[Product].[Product].[Product Category].Members}, InStr(Product.CurrentMember.Name, 'Beverages') > 0) ON ROWS\n" + + "FROM [Sales]", + mdxString); + + // Validate the returned results + CellSet results = query.execute(); + String resultsString = TestContext.toString(results); + TestContext.assertEqualsVerbose( + "Axis #0:\n" + + "{}\n" + + "Axis #1:\n" + + "{[Measures].[Sales Count]}\n" + + "Axis #2:\n" + + "{[Product].[Product].[Drink].[Beverages].[Carbonated Beverages]}\n" + + "{[Product].[Product].[Drink].[Beverages].[Hot Beverages]}\n" + + "{[Product].[Product].[Drink].[Beverages].[Pure Juice Beverages]}\n" + + "Row #0: 1,107\n" + + "Row #1: 1,391\n" + + "Row #2: 1,096\n", + resultsString); + + query.getAxis(Axis.ROWS).limit( + LimitFunction.TopCount, + new BigDecimal(2), + "[Measures].[Sales Count]"); + + query.validate(); + + // Validate the generated MDX + mdxString = query.getSelect().toString(); + TestContext.assertEqualsVerbose( + "SELECT\n" + + "{[Measures].[Sales Count]} ON COLUMNS,\n" + + "TopCount(Filter({[Product].[Product].[Product Category].Members}, InStr(Product.CurrentMember.Name, 'Beverages') > 0), 2, [Measures].[Sales Count]) ON ROWS\n" + + "FROM [Sales]", + mdxString); + + // Validate the returned results + results = query.execute(); + resultsString = TestContext.toString(results); + TestContext.assertEqualsVerbose( + "Axis #0:\n" + + "{}\n" + + "Axis #1:\n" + + "{[Measures].[Sales Count]}\n" + + "Axis #2:\n" + + "{[Product].[Product].[Drink].[Beverages].[Hot Beverages]}\n" + + "{[Product].[Product].[Drink].[Beverages].[Carbonated Beverages]}\n" + + "Row #0: 1,391\n" + + "Row #1: 1,107\n", + resultsString); + + query.getAxis(Axis.ROWS).filter("InStr(Product.CurrentMember.Name, 'NoMatchingString') > 0"); + + query.validate(); + + // Validate the generated MDX + mdxString = query.getSelect().toString(); + TestContext.assertEqualsVerbose( + "SELECT\n" + + "{[Measures].[Sales Count]} ON COLUMNS,\n" + + "TopCount(Filter({[Product].[Product].[Product Category].Members}, InStr(Product.CurrentMember.Name, 'NoMatchingString') > 0), 2, [Measures].[Sales Count]) ON ROWS\n" + + "FROM [Sales]", + mdxString); + + // Validate the returned results + results = query.execute(); + resultsString = TestContext.toString(results); + TestContext.assertEqualsVerbose( + "Axis #0:\n" + + "{}\n" + + "Axis #1:\n" + + "{[Measures].[Sales Count]}\n" + + "Axis #2:\n", + resultsString); + + } public void testHierarchyConsistency() throws Exception { Cube cube = getFoodmartCube("Sales");