From 633b6042c192b77d66ad91970bc8e35d1c424171 Mon Sep 17 00:00:00 2001 From: Paul Stoellberger Date: Thu, 7 Oct 2010 19:02:22 +0000 Subject: [PATCH] treat filter axis like any other, fix sort order and exclusions for crossjoin queries on an axis git-svn-id: https://olap4j.svn.sourceforge.net/svnroot/olap4j/trunk@354 c6a108a4-781c-0410-a6c6-c2d559e19af0 --- src/org/olap4j/mdx/CallNode.java | 37 ++++++ src/org/olap4j/query/Olap4jNodeConverter.java | 105 ++++++++++++------ 2 files changed, 111 insertions(+), 31 deletions(-) diff --git a/src/org/olap4j/mdx/CallNode.java b/src/org/olap4j/mdx/CallNode.java index f1bcafd..79b2c9a 100644 --- a/src/org/olap4j/mdx/CallNode.java +++ b/src/org/olap4j/mdx/CallNode.java @@ -188,6 +188,43 @@ public CallNode deepCopy() { this.syntax, MdxUtil.deepCopyList(argList)); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((argList == null) ? 0 : argList.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((syntax == null) ? 0 : syntax.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + CallNode other = (CallNode) obj; + if (argList == null) { + if (other.argList != null) + return false; + } else if (!argList.equals(other.argList)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (syntax == null) { + if (other.syntax != null) + return false; + } else if (!syntax.equals(other.syntax)) + return false; + return true; + } } // End CallNode.java diff --git a/src/org/olap4j/query/Olap4jNodeConverter.java b/src/org/olap4j/query/Olap4jNodeConverter.java index 372fd52..05960a1 100644 --- a/src/org/olap4j/query/Olap4jNodeConverter.java +++ b/src/org/olap4j/query/Olap4jNodeConverter.java @@ -83,13 +83,14 @@ private static CallNode generateListTupleCall(List cnodes) { cnodes); } - protected static CallNode generateCrossJoin(List selections) { - ParseTreeNode sel1 = toOlap4j(selections.remove(0)); + protected static CallNode generateCrossJoin(List selections) + { + ParseTreeNode sel1 = selections.remove(0); if (sel1 instanceof MemberNode) { sel1 = generateSetCall(sel1); } if (selections.size() == 1) { - ParseTreeNode sel2 = toOlap4j(selections.get(0)); + ParseTreeNode sel2 = selections.get(0); if (sel2 instanceof MemberNode) { sel2 = generateSetCall(sel2); } @@ -102,9 +103,9 @@ protected static CallNode generateCrossJoin(List selections) { } } - protected static CallNode generateUnion(List> unions) { + protected static CallNode generateUnion(List> unions) { if (unions.size() > 2) { - List first = unions.remove(0); + List first = unions.remove(0); return new CallNode( null, "Union", Syntax.Function, generateCrossJoin(first), @@ -118,7 +119,7 @@ protected static CallNode generateUnion(List> unions) { } protected static CallNode generateHierarchizeUnion( - List> unions) + List> unions) { return new CallNode( null, "Hierarchize", Syntax.Function, @@ -136,27 +137,79 @@ protected static CallNode generateHierarchizeUnion( private static void generateUnionsRecursively( QueryAxis axis, int dim, - List curr, - List> unions, + List curr, + List> unions, List selsWithContext, - List> contextUnions) + List> contextUnions) { - for (Selection sel : axis.getDimensions().get(dim).getInclusions()) { + ParseTreeNode exceptSet = null; + QueryDimension qDim = axis.getDimensions().get(dim); + + List exclusionSelections = qDim.getExclusions(); + List exclusionNodes = new ArrayList(); + + // Check if any exclusions are selected for this dimension + // and convert them to a list of nodes and then later a set + for (Selection exclusion : exclusionSelections) { + exclusionNodes.add(toOlap4j(exclusion)); + } + if (exclusionNodes.size() > 0) { + exceptSet = generateListSetCall(exclusionNodes); + } + + for (Selection sel : qDim.getInclusions()) { + ParseTreeNode selectionNode = toOlap4j(sel); + // If a sort Order was specified for this dimension + // apply it for this inclusion + if (qDim.getSortOrder() != null) { + CallNode currentMemberNode = new CallNode( + null, + "CurrentMember", + Syntax.Property, + new DimensionNode(null, sel.getDimension())); + CallNode currentMemberNameNode = new CallNode( + null, + "Name", + Syntax.Property, + currentMemberNode); + selectionNode = + new CallNode( + null, + "Order", + Syntax.Function, + generateSetCall(selectionNode), + currentMemberNameNode, + LiteralNode.createSymbol( + null, + qDim.getSortOrder().name())); + } + // If there are exlclusions wrap the ordered selection + // in an Except() function + if (exceptSet != null) { + selectionNode = new CallNode( + null, + "Except", + Syntax.Function, + generateSetCall(selectionNode), + exceptSet); + } 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(); + ArrayList sels = + new ArrayList(); for (int i = 0; i < axis.getDimensions().size(); i++) { if (dim == i) { - sels.add(sel); + sels.add(selectionNode); } else { // return the selections in the correct // dimensional order QueryDimension dimension = axis.getDimensions().get(i); + boolean found = false; for (Selection selection : sel.getSelectionContext()) @@ -164,14 +217,14 @@ private static void generateUnionsRecursively( if (selection.getDimension().equals( dimension.getDimension())) { - sels.add(selection); + sels.add(toOlap4j(selection)); found = true; } } if (!found) { // add the first selection of the dimension if (dimension.getInclusions().size() > 0) { - sels.add(dimension.getInclusions().get(0)); + sels.add(toOlap4j(dimension.getInclusions().get(0))); } } } @@ -180,11 +233,11 @@ private static void generateUnionsRecursively( selsWithContext.add(sel); } } else { - List ncurr = new ArrayList(); + List ncurr = new ArrayList(); if (curr != null) { ncurr.addAll(curr); } - ncurr.add(sel); + ncurr.add(selectionNode); if (dim == axis.getDimensions().size() - 1) { // last dimension unions.add(ncurr); @@ -206,18 +259,7 @@ private static void generateUnionsRecursively( private static AxisNode toOlap4j(QueryAxis axis) { CallNode callNode = null; int numDimensions = axis.getDimensions().size(); - if (axis.getLocation() == Axis.FILTER) { - // REVIEW : This part is not right. Fix this. - List members = new ArrayList(); - for (int dimNo = 0; dimNo < numDimensions; dimNo++) { - QueryDimension dimension = - axis.getDimensions().get(dimNo); - if (dimension.getInclusions().size() == 1) { - members.addAll(toOlap4j(dimension)); - } - } - callNode = generateListTupleCall(members); - } else if (numDimensions == 0) { + if (numDimensions == 0) { return null; } else if (numDimensions == 1) { QueryDimension dimension = axis.getDimensions().get(0); @@ -225,10 +267,11 @@ private static AxisNode toOlap4j(QueryAxis axis) { callNode = generateListSetCall(members); } else { // generate union sets of selections in each dimension - List> unions = new ArrayList>(); + List> unions = + new ArrayList>(); List selsWithContext = new ArrayList(); - List> contextUnions = - new ArrayList>(); + List> contextUnions = + new ArrayList>(); generateUnionsRecursively( axis, 0, null, unions, selsWithContext, contextUnions); unions.addAll(contextUnions);