From 518c99b6c8584b8a2c808bb860e9a7644b7e2397 Mon Sep 17 00:00:00 2001 From: Julian Hyde Date: Mon, 5 Apr 2010 01:34:29 +0000 Subject: [PATCH] Cosmetic stuff. Mainly checkFile exceptions. git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@306 c6a108a4-781c-0410-a6c6-c2d559e19af0 --- src/org/olap4j/query/Olap4jNodeConverter.java | 212 ++++++++++-------- src/org/olap4j/query/QueryDimension.java | 28 ++- src/org/olap4j/query/Selection.java | 8 +- src/org/olap4j/query/SelectionImpl.java | 14 +- testsrc/org/olap4j/ConnectionTest.java | 6 +- testsrc/org/olap4j/OlapTest.java | 100 +++++---- .../olap4j/impl/ConnectStringParserTest.java | 2 +- 7 files changed, 208 insertions(+), 162 deletions(-) diff --git a/src/org/olap4j/query/Olap4jNodeConverter.java b/src/org/olap4j/query/Olap4jNodeConverter.java index 796c65f..372fd52 100644 --- a/src/org/olap4j/query/Olap4jNodeConverter.java +++ b/src/org/olap4j/query/Olap4jNodeConverter.java @@ -3,7 +3,7 @@ // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. -// Copyright (C) 2007-2009 Julian Hyde +// Copyright (C) 2007-2010 Julian Hyde // All Rights Reserved. // You must accept the terms of that agreement to use this software. */ @@ -82,93 +82,119 @@ private static CallNode generateListTupleCall(List cnodes) { Syntax.Parentheses, cnodes); } - + protected static CallNode generateCrossJoin(List selections) { - ParseTreeNode sel1 = toOlap4j(selections.remove(0)); - if (sel1 instanceof MemberNode) { - sel1 = generateSetCall(sel1); - } - if (selections.size() == 1) { - ParseTreeNode sel2 = toOlap4j(selections.get(0)); - if (sel2 instanceof MemberNode) { - sel2 = generateSetCall(sel2); - } - - return new CallNode( null, "CrossJoin", Syntax.Function, sel1, sel2); - } else { - return new CallNode( null, "CrossJoin", Syntax.Function, sel1, generateCrossJoin(selections)); - } + ParseTreeNode sel1 = toOlap4j(selections.remove(0)); + if (sel1 instanceof MemberNode) { + sel1 = generateSetCall(sel1); + } + if (selections.size() == 1) { + ParseTreeNode sel2 = toOlap4j(selections.get(0)); + if (sel2 instanceof MemberNode) { + sel2 = generateSetCall(sel2); + } + return new CallNode( + null, "CrossJoin", Syntax.Function, sel1, sel2); + } else { + return new CallNode( + null, "CrossJoin", Syntax.Function, sel1, + generateCrossJoin(selections)); + } } - + protected static CallNode generateUnion(List> unions) { - if (unions.size() > 2) { - List first = unions.remove(0); - return new CallNode( null, "Union", Syntax.Function, generateCrossJoin(first), generateUnion(unions)); - } else { - return new CallNode( null, "Union", Syntax.Function, generateCrossJoin(unions.get(0)), generateCrossJoin(unions.get(1))); - } + if (unions.size() > 2) { + List first = unions.remove(0); + return new CallNode( + null, "Union", Syntax.Function, + generateCrossJoin(first), + generateUnion(unions)); + } else { + return new CallNode( + null, "Union", Syntax.Function, + generateCrossJoin(unions.get(0)), + generateCrossJoin(unions.get(1))); + } } - - protected static CallNode generateHierarchizeUnion(List> unions) { - return new CallNode(null, "Hierarchize", Syntax.Function, - generateUnion(unions) - ); + + protected static CallNode generateHierarchizeUnion( + List> unions) + { + return new CallNode( + null, "Hierarchize", Syntax.Function, + generateUnion(unions)); } - + /** - * - * Algorithm: - * - generate all combinations of dimension groups - * - skip the selection if has a context - * - for all the selections with context, resolve them last - * - union all combinations + * Algorithm:
    + *
  • generate all combinations of dimension groups + *
  • skip the selection if has a context + *
  • for all the selections with context, resolve them last + *
  • union all combinations + *
*/ - private static void generateUnionsRecursively(QueryAxis axis, int dim, List curr, List> unions, List selsWithContext, List> contextUnions) { - for (Selection sel : axis.getDimensions().get(dim).getInclusions()) { - - if (sel.getSelectionContext() != null && sel.getSelectionContext().size() > 0) { - // selections that have a context are treated differently than the - // rest of the MDX generation - if (!selsWithContext.contains(sel)) { - ArrayList sels = new ArrayList(); - for (int i = 0; i < axis.getDimensions().size(); i++) { - if (dim == i) { - sels.add(sel); - } else { - // return the selections in the correct dimensional order - QueryDimension dimension = axis.getDimensions().get(i); - boolean found = false; - for (Selection selection : sel.getSelectionContext()) { - if (selection.getDimension().equals(dimension.getDimension())) { - sels.add(selection); - found = true; - } - } - if (!found) { - // add the first selection of the dimension - if (dimension.getInclusions().size() > 0) { - sels.add(dimension.getInclusions().get(0)); - } - } - } - } - contextUnions.add(sels); - selsWithContext.add(sel); - } - } else { - List ncurr = new ArrayList(); - if (curr != null) { - ncurr.addAll(curr); - } - ncurr.add(sel); - if (dim == axis.getDimensions().size() - 1) { - // last dimension - unions.add(ncurr); - } else { - generateUnionsRecursively(axis, dim + 1, ncurr, unions, selsWithContext, contextUnions); - } - } - } + private static void generateUnionsRecursively( + QueryAxis axis, + int dim, + List curr, + List> unions, + List selsWithContext, + List> contextUnions) + { + for (Selection sel : axis.getDimensions().get(dim).getInclusions()) { + if (sel.getSelectionContext() != null + && sel.getSelectionContext().size() > 0) + { + // selections that have a context are treated + // differently than the rest of the MDX generation + if (!selsWithContext.contains(sel)) { + ArrayList sels = new ArrayList(); + for (int i = 0; i < axis.getDimensions().size(); i++) { + if (dim == i) { + sels.add(sel); + } else { + // return the selections in the correct + // dimensional order + QueryDimension dimension = + axis.getDimensions().get(i); + boolean found = false; + for (Selection selection + : sel.getSelectionContext()) + { + if (selection.getDimension().equals( + dimension.getDimension())) + { + sels.add(selection); + found = true; + } + } + if (!found) { + // add the first selection of the dimension + if (dimension.getInclusions().size() > 0) { + sels.add(dimension.getInclusions().get(0)); + } + } + } + } + contextUnions.add(sels); + selsWithContext.add(sel); + } + } else { + List ncurr = new ArrayList(); + if (curr != null) { + ncurr.addAll(curr); + } + ncurr.add(sel); + if (dim == axis.getDimensions().size() - 1) { + // last dimension + unions.add(ncurr); + } else { + generateUnionsRecursively( + axis, dim + 1, ncurr, unions, selsWithContext, + contextUnions); + } + } + } } /* @@ -198,17 +224,19 @@ private static AxisNode toOlap4j(QueryAxis axis) { List members = toOlap4j(dimension); callNode = generateListSetCall(members); } else { - // generate union sets of selections in each dimension - List> unions = new ArrayList>(); - List selsWithContext = new ArrayList(); - List> contextUnions = new ArrayList>(); - generateUnionsRecursively(axis, 0, null, unions, selsWithContext, contextUnions); - unions.addAll(contextUnions); - if (unions.size() > 1) { - callNode = generateHierarchizeUnion(unions); - } else { - callNode = generateCrossJoin(unions.get(0)); - } + // generate union sets of selections in each dimension + List> unions = new ArrayList>(); + List selsWithContext = new ArrayList(); + List> contextUnions = + new ArrayList>(); + generateUnionsRecursively( + axis, 0, null, unions, selsWithContext, contextUnions); + unions.addAll(contextUnions); + if (unions.size() > 1) { + callNode = generateHierarchizeUnion(unions); + } else { + callNode = generateCrossJoin(unions.get(0)); + } } // We might need to sort the whole axis. diff --git a/src/org/olap4j/query/QueryDimension.java b/src/org/olap4j/query/QueryDimension.java index f668619..3b52cd5 100644 --- a/src/org/olap4j/query/QueryDimension.java +++ b/src/org/olap4j/query/QueryDimension.java @@ -3,7 +3,7 @@ // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. -// Copyright (C) 2007-2009 Julian Hyde +// Copyright (C) 2007-2010 Julian Hyde // All Rights Reserved. // You must accept the terms of that agreement to use this software. */ @@ -116,7 +116,7 @@ public Selection include(String... nameParts) throws OlapException { } public Selection createSelection(String... nameParts) throws OlapException { - return this.createSelection(Selection.Operator.MEMBER, nameParts); + return this.createSelection(Selection.Operator.MEMBER, nameParts); } /** @@ -145,7 +145,7 @@ public Selection include( member); } } - + public Selection createSelection( Selection.Operator operator, String... nameParts) throws OlapException @@ -173,7 +173,7 @@ public Selection include(Member member) { } public Selection createSelection(Member member) { - return createSelection(Selection.Operator.MEMBER, member); + return createSelection(Selection.Operator.MEMBER, member); } /** @@ -487,9 +487,12 @@ public void clearSort() { /** * Returns the current mode of hierarchization, or null * if no hierarchization is currently performed. - * This capability is only available when a single dimension is selected on an axis. + * + *

This capability is only available when a single dimension is + * selected on an axis + * * @return Either a hierarchization mode value or null - * if no hierarchization is currently performed. + * if no hierarchization is currently performed. */ public HierarchizeMode getHierarchizeMode() { return hierarchizeMode; @@ -498,9 +501,13 @@ public HierarchizeMode getHierarchizeMode() { /** * Triggers the hierarchization of the included members within this * QueryDimension. + * *

The dimension inclusions will be wrapped in an MDX Hierarchize * function call. - * This capability is only available when a single dimension is selected on an axis. + * + *

This capability is only available when a single dimension is + * selected on an axis. + * * @param hierarchizeMode If parents should be included before or after * their children. (Equivalent to the POST/PRE MDX literal for the * Hierarchize() function) @@ -511,8 +518,11 @@ public void setHierarchizeMode(HierarchizeMode hierarchizeMode) { } /** - * Tells the QueryDimension not to hierarchize it's included selections. - * This capability is only available when a single dimension is selected on an axis. + * Tells the QueryDimension not to hierarchize its included + * selections. + * + *

This capability is only available when a single dimension is + * selected on an axis. */ public void clearHierarchizeMode() { this.hierarchizeMode = null; diff --git a/src/org/olap4j/query/Selection.java b/src/org/olap4j/query/Selection.java index 534b28b..3331b36 100644 --- a/src/org/olap4j/query/Selection.java +++ b/src/org/olap4j/query/Selection.java @@ -3,7 +3,7 @@ // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. -// Copyright (C) 2007-2008 Julian Hyde +// Copyright (C) 2007-2010 Julian Hyde // All Rights Reserved. // You must accept the terms of that agreement to use this software. */ @@ -46,8 +46,10 @@ public interface Selection extends QueryNode { String getHierarchyName(); /** - * The selection context includes selections from other dimensions that help determine the entire - * context of a selection, so drill down is possible. + * The selection context includes selections from other dimensions that + * help determine the entire context of a selection, so drill down is + * possible. + * * @return list of selections */ List getSelectionContext(); diff --git a/src/org/olap4j/query/SelectionImpl.java b/src/org/olap4j/query/SelectionImpl.java index d21d3ec..3918638 100644 --- a/src/org/olap4j/query/SelectionImpl.java +++ b/src/org/olap4j/query/SelectionImpl.java @@ -3,7 +3,7 @@ // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. -// Copyright (C) 2007-2008 Julian Hyde +// Copyright (C) 2007-2010 Julian Hyde // All Rights Reserved. // You must accept the terms of that agreement to use this software. */ @@ -113,18 +113,18 @@ void tearDown() { } public List getSelectionContext() { - return selectionContext; + return selectionContext; } public void addContext(Selection selection) { - if (selectionContext == null) { - selectionContext = new ArrayList(); - } - selectionContext.add(selection); + if (selectionContext == null) { + selectionContext = new ArrayList(); + } + selectionContext.add(selection); } public void removeContext(Selection selection) { - selectionContext.remove(selection); + selectionContext.remove(selection); } } diff --git a/testsrc/org/olap4j/ConnectionTest.java b/testsrc/org/olap4j/ConnectionTest.java index 04e0b64..02e5116 100644 --- a/testsrc/org/olap4j/ConnectionTest.java +++ b/testsrc/org/olap4j/ConnectionTest.java @@ -2556,15 +2556,17 @@ public void testCubeDimensionsOrder() throws Exception { *

Test case for * * bug 2951656, "Olap4j should not throw IllegalArgumentException". + * + * @throws java.sql.SQLException on error */ - public void _testDimensionProperties() throws SQLException { + public void testDimensionProperties() throws SQLException { connection = tester.createConnection(); OlapConnection olapConnection = tester.getWrapper().unwrap(connection, OlapConnection.class); String mdx = "select {[Product].[Product Family].Members} ON COLUMNS,\n" + "{[Store].[Store Name].Members}\n" - + " DIMENSION PROPERTIES [Store].[Store Sqft] ON ROWS\n" + + " DIMENSION PROPERTIES [Store].[Store Name].[Store Sqft] ON ROWS\n" + "from [Sales]\n" + "where [Measures].[Unit Sales]"; PreparedOlapStatement pstmt = diff --git a/testsrc/org/olap4j/OlapTest.java b/testsrc/org/olap4j/OlapTest.java index c68e6b4..175ba0c 100644 --- a/testsrc/org/olap4j/OlapTest.java +++ b/testsrc/org/olap4j/OlapTest.java @@ -2,7 +2,7 @@ // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. -// Copyright (C) 2007-2009 Julian Hyde +// Copyright (C) 2007-2010 Julian Hyde // All Rights Reserved. // You must accept the terms of that agreement to use this software. */ @@ -502,8 +502,7 @@ public void testSortDimension() { } } - public void testSelectionContext() { - try { + public void testSelectionContext() throws Exception { Cube cube = getFoodmartCube("Sales"); if (cube == null) { fail("Could not find Sales cube"); @@ -511,24 +510,34 @@ public void testSelectionContext() { Query query = new Query("my query", cube); // create selections - QueryDimension productDimension = query.getDimension("Product"); productDimension.include( - Selection.Operator.INCLUDE_CHILDREN, "Product", "All Products"); + Selection.Operator.INCLUDE_CHILDREN, "Product", "All Products"); QueryDimension timeDimension = query.getDimension("Time"); - timeDimension.include(Selection.Operator.MEMBER, "Time", "Year", "1997"); + timeDimension.include( + Selection.Operator.MEMBER, "Time", "Year", "1997"); + + Selection selection = + timeDimension.include( + Selection.Operator.CHILDREN, "Time", "Year", "1997"); + selection.addContext( + productDimension.createSelection( + "Product", "All Products", "Drink")); - Selection selection = timeDimension.include(Selection.Operator.CHILDREN, "Time", "Year", "1997"); - selection.addContext(productDimension.createSelection("Product", "All Products", "Drink")); - // [Store].[All Stores] QueryDimension storeDimension = query.getDimension("Store"); - storeDimension.include(Selection.Operator.MEMBER, "Store", "All Stores"); - - Selection children = storeDimension.include(Selection.Operator.CHILDREN, "Store", "All Stores"); - children.addContext(productDimension.createSelection("Product", "All Products", "Drink")); - children.addContext(timeDimension.createSelection("Time", "1997", "Q3")); + storeDimension.include( + Selection.Operator.MEMBER, "Store", "All Stores"); + + Selection children = + storeDimension.include( + Selection.Operator.CHILDREN, "Store", "All Stores"); + children.addContext( + productDimension.createSelection( + "Product", "All Products", "Drink")); + children.addContext( + timeDimension.createSelection("Time", "1997", "Q3")); QueryDimension measuresDimension = query.getDimension("Measures"); measuresDimension.include("Measures", "Store Sales"); @@ -569,45 +578,40 @@ public void testSelectionContext() { "SELECT\n" + "{[Measures].[Store Sales]} ON COLUMNS,\n" + "Order(Hierarchize(Union(CrossJoin({[Product].[All Products], [Product].[All Products].Children}, CrossJoin({[Time].[1997]}, {[Store].[All Stores]})), Union(CrossJoin({[Product].[All Products].[Drink]}, CrossJoin({[Time].[1997].[Q3]}, [Store].[All Stores].Children)), CrossJoin({[Product].[All Products].[Drink]}, CrossJoin([Time].[1997].Children, {[Store].[All Stores]}))))), [Measures].[Store Sales], ASC) ON ROWS\n" - + "FROM [Sales]" - , + + "FROM [Sales]", sortedMdxString); CellSet results = query.execute(); String s = TestContext.toString(results); TestContext.assertEqualsVerbose( - "Axis #0:\n" - + "{[Store Size in SQFT].[All Store Size in SQFTs], [Store Type].[All Store Types], [Promotion Media].[All Media], [Promotions].[All Promotions], [Customers].[All Customers], [Education Level].[All Education Levels], [Gender].[All Gender], [Marital Status].[All Marital Status], [Yearly Income].[All Yearly Incomes]}\n" - + "Axis #1:\n" - + "{[Measures].[Store Sales]}\n" - + "Axis #2:\n" - + "{[Product].[All Products], [Time].[1997], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q1], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q2], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[Canada]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[Mexico]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[USA]}\n" - + "{[Product].[All Products].[Drink], [Time].[1997].[Q4], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Non-Consumable], [Time].[1997], [Store].[All Stores]}\n" - + "{[Product].[All Products].[Food], [Time].[1997], [Store].[All Stores]}\n" - + "Row #0: 565,238.13\n" - + "Row #1: 48,836.21\n" - + "Row #2: 11,585.80\n" - + "Row #3: 11,914.58\n" - + "Row #4: 11,994.00\n" - + "Row #5: \n" - + "Row #6: \n" - + "Row #7: 11,994.00\n" - + "Row #8: 13,341.83\n" - + "Row #9: 107,366.33\n" - + "Row #10: 409,035.59\n", + "Axis #0:\n" + + "{[Store Size in SQFT].[All Store Size in SQFTs], [Store Type].[All Store Types], [Promotion Media].[All Media], [Promotions].[All Promotions], [Customers].[All Customers], [Education Level].[All Education Levels], [Gender].[All Gender], [Marital Status].[All Marital Status], [Yearly Income].[All Yearly Incomes]}\n" + + "Axis #1:\n" + + "{[Measures].[Store Sales]}\n" + + "Axis #2:\n" + + "{[Product].[All Products], [Time].[1997], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q1], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q2], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[Canada]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[Mexico]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q3], [Store].[All Stores].[USA]}\n" + + "{[Product].[All Products].[Drink], [Time].[1997].[Q4], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Non-Consumable], [Time].[1997], [Store].[All Stores]}\n" + + "{[Product].[All Products].[Food], [Time].[1997], [Store].[All Stores]}\n" + + "Row #0: 565,238.13\n" + + "Row #1: 48,836.21\n" + + "Row #2: 11,585.80\n" + + "Row #3: 11,914.58\n" + + "Row #4: 11,994.00\n" + + "Row #5: \n" + + "Row #6: \n" + + "Row #7: 11,994.00\n" + + "Row #8: 13,341.83\n" + + "Row #9: 107,366.33\n" + + "Row #10: 409,035.59\n", s); - } catch (Exception e) { - e.printStackTrace(); - fail(); - } } public void testSortAxis() { @@ -776,7 +780,7 @@ public void testDimensionsOrder() { } /** - * Note: hierarchize mode only works when a single dimension is selected + * Note: hierarchize mode only works when a single dimension is selected. */ public void testDimensionsHierarchize() { try { diff --git a/testsrc/org/olap4j/impl/ConnectStringParserTest.java b/testsrc/org/olap4j/impl/ConnectStringParserTest.java index a3ed0c2..1a0dd00 100644 --- a/testsrc/org/olap4j/impl/ConnectStringParserTest.java +++ b/testsrc/org/olap4j/impl/ConnectStringParserTest.java @@ -86,7 +86,7 @@ public void testConnectStringMore() { * Testcase for bug 1938151, "StringIndexOutOfBoundsException instead of a * meaningful error" */ - public void testBug1938151 () { + public void testBug1938151() { Map properties; // ends in semi