Skip to content

Commit

Permalink
MONDRIAN: [MONDRIAN-893] Adds support for the return clause in DRILLT…
Browse files Browse the repository at this point in the history
…HROUGH queries. For now this only works with Mondrian's olap4j driver, but its a first step. The tests are in olap4j's TCK. Also fixes some javadoc and coding standard errors.

[git-p4: depot-paths = "//open/mondrian/": change = 14969]
  • Loading branch information
lucboudreau committed Feb 21, 2012
1 parent 8fae8c5 commit 71235c1
Show file tree
Hide file tree
Showing 13 changed files with 219 additions and 66 deletions.
4 changes: 4 additions & 0 deletions src/main/mondrian/olap/DrillThrough.java
Expand Up @@ -80,6 +80,10 @@ public int getMaxRowCount() {
public int getFirstRowOrdinal() {
return firstRowOrdinal;
}

public List<Exp> getReturnList() {
return returnList;
}
}

// End DrillThrough.java
18 changes: 14 additions & 4 deletions src/main/mondrian/olap4j/MondrianOlap4jCell.java
Expand Up @@ -9,6 +9,8 @@
*/
package mondrian.olap4j;

import mondrian.olap.Exp;
import mondrian.olap.Util;
import mondrian.rolap.RolapCell;
import mondrian.rolap.SqlStatement;

Expand All @@ -19,6 +21,7 @@

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
Expand Down Expand Up @@ -118,7 +121,13 @@ public String getFormattedValue() {
}

public ResultSet drillThrough() throws OlapException {
return drillThroughInternal(-1, -1, null, false, null, null);
return drillThroughInternal(
-1,
-1,
new ArrayList<Exp>(),
false,
null,
null);
}

/**
Expand All @@ -130,7 +139,8 @@ public ResultSet drillThrough() throws OlapException {
* @param maxRowCount Maximum number of rows to retrieve, <= 0 if unlimited
* @param firstRowOrdinal Ordinal of row to skip to (1-based), or 0 to
* start from beginning
* @param tabFields Comma-separated list of fields to return (deprecated)
* @param fields List of fields to return, expressed as MDX
* expressions.
* @param extendedContext If true, add non-constraining columns to the
* query for levels below each current member.
* This additional context makes the drill-through
Expand All @@ -143,7 +153,7 @@ public ResultSet drillThrough() throws OlapException {
ResultSet drillThroughInternal(
int maxRowCount,
int firstRowOrdinal,
String tabFields,
List<Exp> fields,
boolean extendedContext,
Logger logger,
int[] rowCountSlot)
Expand All @@ -157,7 +167,7 @@ ResultSet drillThroughInternal(
}
final SqlStatement sqlStmt =
cell.drillThroughInternal(
maxRowCount, firstRowOrdinal, tabFields, extendedContext,
maxRowCount, firstRowOrdinal, fields, extendedContext,
logger);
return sqlStmt.getWrappedResultSet();
}
Expand Down
4 changes: 3 additions & 1 deletion src/main/mondrian/olap4j/MondrianOlap4jStatement.java
Expand Up @@ -16,6 +16,7 @@
import mondrian.util.Pair;

import org.olap4j.*;
import org.olap4j.layout.RectangularCellSetFormatter;
import org.olap4j.mdx.*;

import java.io.PrintWriter;
Expand Down Expand Up @@ -94,11 +95,12 @@ ResultSet executeQuery2(
cellSet.getAxes().size(), 0);
final MondrianOlap4jCell cell =
(MondrianOlap4jCell) cellSet.getCell(coords);

ResultSet resultSet =
cell.drillThroughInternal(
drillThrough.getMaxRowCount(),
drillThrough.getFirstRowOrdinal(),
null,
drillThrough.getReturnList(),
true,
null,
rowCountSlot);
Expand Down
2 changes: 1 addition & 1 deletion src/main/mondrian/parser/MdxParser.jj
Expand Up @@ -1210,7 +1210,7 @@ List<Exp> returnItemList() :
i = returnItem() {
list.add(i);
}
)
)*
{
return list;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/mondrian/rolap/FastBatchingCellReader.java
Expand Up @@ -821,13 +821,13 @@ public LoadBatchCommand(
this.dialect = dialect;
this.cube = cube;
this.cellRequests = cellRequests;
if(MDC.getContext() != null) {
if (MDC.getContext() != null) {
this.mdc.putAll(MDC.getContext());
}
}

public LoadBatchResponse call() {
if(MDC.getContext() != null) {
if (MDC.getContext() != null) {
final Map<String, Object> old = MDC.getContext();
old.clear();
old.putAll(mdc);
Expand Down
100 changes: 88 additions & 12 deletions src/main/mondrian/rolap/RolapAggregationManager.java
Expand Up @@ -4,7 +4,7 @@
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2001-2002 Kana Software, Inc.
// Copyright (C) 2001-2011 Julian Hyde and others
// Copyright (C) 2001-2012 Julian Hyde and others
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
Expand All @@ -16,7 +16,6 @@
import mondrian.olap.fun.VisualTotalsFunDef.VisualTotalMember;
import mondrian.rolap.agg.*;

import java.io.PrintWriter;
import java.util.*;

/**
Expand Down Expand Up @@ -52,7 +51,7 @@ protected RolapAggregationManager() {
*/
public static CellRequest makeRequest(final Member[] members)
{
return makeCellRequest(members, false, false, null);
return makeCellRequest(members, false, false, null, null);
}

/**
Expand All @@ -72,13 +71,15 @@ public static CellRequest makeRequest(final Member[] members)
* @param cube Cube
* @return Cell request, or null if the requst is unsatisfiable
*/
public static CellRequest makeDrillThroughRequest(
public static DrillThroughCellRequest makeDrillThroughRequest(
final Member[] members,
final boolean extendedContext,
RolapCube cube)
RolapCube cube,
List<Exp> fieldsList)
{
assert cube != null;
return makeCellRequest(members, true, extendedContext, cube);
return (DrillThroughCellRequest) makeCellRequest(
members, true, extendedContext, cube, fieldsList);
}

/**
Expand Down Expand Up @@ -107,7 +108,7 @@ public static CellRequest makeRequest(
int starColumnCount = starMeasure.getStar().getColumnCount();

CellRequest request =
makeCellRequest(currentMembers, false, false, null);
makeCellRequest(currentMembers, false, false, null, null);

/*
* Now setting the compound keys.
Expand Down Expand Up @@ -175,7 +176,8 @@ private static CellRequest makeCellRequest(
final Member[] members,
boolean drillThrough,
final boolean extendedContext,
RolapCube cube)
RolapCube cube,
List<Exp> fieldsList)
{
// Need cube for drill-through requests
assert drillThrough == (cube != null);
Expand Down Expand Up @@ -210,20 +212,49 @@ private static CellRequest makeCellRequest(
final RolapStar.Measure starMeasure =
(RolapStar.Measure) measure.getStarMeasure();
assert starMeasure != null;
final CellRequest request =
new CellRequest(starMeasure, extendedContext, drillThrough);
final CellRequest request;
if (drillThrough) {
request =
new DrillThroughCellRequest(starMeasure, extendedContext);
} else {
request =
new CellRequest(starMeasure, extendedContext, drillThrough);
}

// Since 'request.extendedContext == false' is a well-worn code path,
// we have moved the test outside the loop.
if (extendedContext) {
if (fieldsList != null) {
// If a field list was specified, there will be some columns
// to include in the result set, other that we don't. This
// happens when the MDX is a DRILLTHROUGH operation and
// includes a RETURN clause.
final SchemaReader reader = cube.getSchemaReader().withLocus();
for (Exp exp : fieldsList) {
final OlapElement member =
reader.lookupCompound(
cube,
Util.parseIdentifier(exp.toString()),
true,
Category.Unknown);
if (member.getHierarchy() instanceof RolapCubeHierarchy
&& ((RolapCubeHierarchy)member.getHierarchy())
.getRolapHierarchy().closureFor != null)
{
continue;
}
addNonConstrainingColumns(member, cube, request);
}
}
for (int i = 1; i < members.length; i++) {
final RolapCubeMember member = (RolapCubeMember) members[i];
if (member.getHierarchy().getRolapHierarchy().closureFor
!= null)
{
continue;
}
addNonConstrainingColumns(member, measure.getCube(), request);

addNonConstrainingColumns(member, cube, request);

final RolapCubeLevel level = member.getLevel();
final boolean needToReturnNull =
Expand All @@ -233,6 +264,7 @@ private static CellRequest makeCellRequest(
return null;
}
}

} else {
for (int i = 1; i < members.length; i++) {
if (!(members[i] instanceof RolapCubeMember)) {
Expand Down Expand Up @@ -302,6 +334,49 @@ private static void addNonConstrainingColumns(
}
}

private static void addNonConstrainingColumns(
final OlapElement member,
final RolapCube baseCube,
final CellRequest request)
{
RolapCubeLevel level;
if (member instanceof RolapCubeLevel) {
level = (RolapCubeLevel) member;
} else if (member instanceof RolapCubeHierarchy
|| member instanceof RolapCubeDimension)
{
level = (RolapCubeLevel) member.getHierarchy().getLevels()[0];
if (level.isAll()) {
level = level.getChildLevel();
}
} else if (member instanceof RolapStar.Measure) {
((DrillThroughCellRequest)request)
.addDrillThroughMeasure((RolapStar.Measure)member);
return;
} else if (member instanceof RolapBaseCubeMeasure) {
((DrillThroughCellRequest)request)
.addDrillThroughMeasure(
(RolapStar.Measure)
((RolapBaseCubeMeasure)member).getStarMeasure());
return;
} else {
// FIXME make this better.
throw new MondrianException();
}
RolapStar.Column column = level.getBaseStarKeyColumn(baseCube);
if (column != null) {
request.addConstrainedColumn(column, null);
((DrillThroughCellRequest)request).addDrillThroughColumn(column);
if (request.extendedContext
&& level.getNameExp() != null)
{
final RolapStar.Column nameColumn = column.getNameColumn();
Util.assertTrue(nameColumn != null);
request.addConstrainedColumn(nameColumn, null);
}
}
}

/**
* Groups members (or tuples) from the same compound (i.e. hierarchy) into
* groups that are constrained by the same set of columns.
Expand Down Expand Up @@ -621,8 +696,9 @@ public abstract Object getCellFromCache(
* @return SQL statement
*/
public abstract String getDrillThroughSql(
CellRequest request,
DrillThroughCellRequest request,
StarPredicate starPredicateSlicer,
List<Exp> fields,
boolean countOnly);

public static RolapCacheRegion makeCacheRegion(
Expand Down

0 comments on commit 71235c1

Please sign in to comment.