Skip to content

Commit

Permalink
MONDRIAN: Integrate from 3.1 to main @13313.
Browse files Browse the repository at this point in the history
[git-p4: depot-paths = "//open/mondrian/": change = 13314]
  • Loading branch information
julianhyde committed Jan 12, 2010
1 parent 25d8df6 commit 68407eb
Show file tree
Hide file tree
Showing 15 changed files with 455 additions and 81 deletions.
2 changes: 1 addition & 1 deletion src/main/mondrian/gui/resources/schemaBuilder.html
Expand Up @@ -70,7 +70,7 @@
<BODY LANG="en-US" TEXT="#000000" DIR="LTR">
<H2><U><FONT FACE="Tahoma, sans-serif">Schema Workbench</U></FONT></H2>
<P CLASS="msonormal"><FONT FACE="Tahoma, sans-serif"><BR><B>Product
Version :</B> 3.1.1 revision 12687
Version :</B> 3.1.5 revision 13307
<BR><BR><B>New Features :</B> Access Control, Aggregate Tables <BR><BR><B>Java
:</B> 1.5 and above</FONT></P>
<P CLASS="msonormal"><BR><BR>
Expand Down
3 changes: 3 additions & 0 deletions src/main/mondrian/olap/Mondrian.xml
Expand Up @@ -375,6 +375,9 @@ Revision is $Id$
Default true.
</Doc>
</Attribute>
<Object name="annotations" type="Annotations" required="false">
<Doc>Contains values of user-defined properties.</Doc>
</Object>
</Element>

<!-- DimensionUsage =================================================== -->
Expand Down
7 changes: 5 additions & 2 deletions src/main/mondrian/rolap/RolapCube.java
Expand Up @@ -512,7 +512,9 @@ static CellFormatter getCellFormatter(
new RolapVirtualCubeMeasure(
null,
measuresLevel,
(RolapStoredMeasure) cubeMeasure);
(RolapStoredMeasure) cubeMeasure,
RolapHierarchy.createAnnotationMap(
xmlMeasure.annotations));

// Set member's visibility, default true.
Boolean visible = xmlMeasure.visible;
Expand Down Expand Up @@ -2887,7 +2889,8 @@ public Object visit(MemberExpr memberExpr)
new RolapVirtualCubeMeasure(
null,
measuresLevel,
baseMeasure);
baseMeasure,
Collections.<String, Annotation>emptyMap());
if (!measuresFound.contains(virtualCubeMeasure)) {
measuresFound.add(virtualCubeMeasure);
}
Expand Down
22 changes: 19 additions & 3 deletions src/main/mondrian/rolap/RolapCubeHierarchy.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-2009 Julian Hyde and others
// Copyright (C) 2001-2010 Julian Hyde and others
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
Expand Down Expand Up @@ -38,7 +38,7 @@ public class RolapCubeHierarchy extends RolapHierarchy {
private final RolapCubeDimension parentDimension;
private final RolapHierarchy rolapHierarchy;
private final RolapCubeLevel currentNullLevel;
private RolapNullMember currentNullMember;
private RolapNullCubeMember currentNullMember;
private RolapCubeMember currentAllMember;
private final MondrianDef.RelationOrJoin currentRelation;
private final RolapCubeHierarchyMemberReader reader;
Expand Down Expand Up @@ -343,7 +343,10 @@ public Member getDefaultMember() {
public Member getNullMember() {
// use lazy initialization to get around bootstrap issues
if (currentNullMember == null) {
currentNullMember = new RolapNullMember(currentNullLevel);
currentNullMember =
new RolapNullCubeMember(
currentNullLevel,
(RolapMember) rolapHierarchy.getNullMember());
}
return currentNullMember;
}
Expand Down Expand Up @@ -1149,6 +1152,19 @@ public Object getMemberCacheLock() {
return memberCacheLock;
}
}

/**
* Variant of {@link mondrian.rolap.RolapHierarchy.RolapNullMember} but
* extends {@link mondrian.rolap.RolapCubeMember} and therefore belongs to
* a cube.
*/
static class RolapNullCubeMember extends RolapCubeMember {
RolapNullCubeMember(RolapCubeLevel level, RolapMember nullMember) {
super(null, nullMember, level, level.getCube());
assert level != null;
}
}

}

// End RolapCubeHierarchy.java
Expand Down
32 changes: 20 additions & 12 deletions src/main/mondrian/rolap/RolapEvaluator.java
Expand Up @@ -53,11 +53,12 @@ public class RolapEvaluator implements Evaluator {
private static final Object nullResult = new Object();

private final RolapMember[] currentMembers;
private final Evaluator parent;
private final RolapEvaluator parent;
protected CellReader cellReader;
private final int depth;

private Member expandingMember;
private boolean firstExpanding;
private boolean nonEmpty;
protected final RolapEvaluatorRoot root;
private int iterationLength;
Expand Down Expand Up @@ -240,7 +241,7 @@ public final int getDepth() {
return depth;
}

public final Evaluator getParent() {
public final RolapEvaluator getParent() {
return parent;
}

Expand Down Expand Up @@ -299,7 +300,7 @@ protected RolapEvaluator _push() {
return new RolapEvaluator(root, this);
}

public final Evaluator pop() {
public final RolapEvaluator pop() {
return parent;
}

Expand Down Expand Up @@ -475,11 +476,13 @@ public final Object evaluateCurrent() {
}

void setExpanding(Member member) {
assert member != null;
expandingMember = member;
firstExpanding = true;
final int memberCount = currentMembers.length;
if (depth > memberCount) {
if (depth % memberCount == 0) {
checkRecursion((RolapEvaluator) parent);
checkRecursion(parent);
}
}
}
Expand Down Expand Up @@ -513,18 +516,25 @@ private static void checkRecursion(RolapEvaluator eval) {
if (eval == null) {
return;
}
if (eval.expandingMember != null) {
if (eval.firstExpanding) {
break;
}
eval = (RolapEvaluator) eval.getParent();
eval = eval.parent;
}

// Find an ancestor evaluator that has identical context to this one:
// same member context, and expanding the same calculation.
outer:
for (RolapEvaluator eval2 = (RolapEvaluator) eval.getParent();
for (RolapEvaluator eval2 = eval.parent;
eval2 != null;
eval2 = (RolapEvaluator) eval2.getParent())
eval2 = eval2.parent)
{
if (eval2.expandingMember != eval.expandingMember) {
// Ignore ancestors which are not the first level expanding a
// member. (They are dummy evaluators created to avoid stomping on
// context while iterating over a set, say.)
if (!eval2.firstExpanding
|| eval2.expandingMember != eval.expandingMember)
{
continue;
}
for (int i = 0; i < eval.currentMembers.length; i++) {
Expand Down Expand Up @@ -558,9 +568,7 @@ private String getContextString() {
final boolean skipDefaultMembers = true;
final StringBuilder buf = new StringBuilder("{");
int frameCount = 0;
for (RolapEvaluator eval = this; eval != null;
eval = (RolapEvaluator) eval.getParent())
{
for (RolapEvaluator eval = this; eval != null; eval = eval.parent) {
if (eval.expandingMember == null) {
continue;
}
Expand Down
16 changes: 12 additions & 4 deletions src/main/mondrian/rolap/RolapVirtualCubeMeasure.java
Expand Up @@ -3,14 +3,15 @@
// 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) 2006-2006 Julian Hyde
// Copyright (C) 2006-2009 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.rolap;

import mondrian.olap.MondrianDef;
import mondrian.olap.CellFormatter;
import mondrian.olap.*;

import java.util.Map;

/**
* Measure which is defined in a virtual cube, and based on a stored measure
Expand All @@ -28,14 +29,17 @@ public class RolapVirtualCubeMeasure
* The measure in the underlying cube.
*/
private final RolapStoredMeasure cubeMeasure;
private final Map<String, Annotation> annotationMap;

public RolapVirtualCubeMeasure(
RolapMember parentMember,
RolapLevel level,
RolapStoredMeasure cubeMeasure)
RolapStoredMeasure cubeMeasure,
Map<String, Annotation> annotationMap)
{
super(parentMember, level, cubeMeasure.getName());
this.cubeMeasure = cubeMeasure;
this.annotationMap = annotationMap;
}

public Object getPropertyValue(String propertyName, boolean matchCase) {
Expand Down Expand Up @@ -69,6 +73,10 @@ public RolapAggregator getAggregator() {
public CellFormatter getFormatter() {
return cubeMeasure.getFormatter();
}

public Map<String, Annotation> getAnnotationMap() {
return annotationMap;
}
}

// End RolapVirtualCubeMeasure.java
23 changes: 14 additions & 9 deletions src/main/mondrian/spi/impl/JdbcDialectImpl.java
Expand Up @@ -102,6 +102,8 @@ public class JdbcDialectImpl implements Dialect {
* same.</p>
*
* @param connection Connection
*
* @throws java.sql.SQLException on error
*/
public JdbcDialectImpl(
Connection connection)
Expand Down Expand Up @@ -194,11 +196,11 @@ protected Set<List<Integer>> deduceSupportedResultSetStyles(
DatabaseMetaData databaseMetaData)
{
Set<List<Integer>> supports = new HashSet<List<Integer>>();
try {
for (int type : RESULT_SET_TYPE_VALUES) {
for (int concurrency : CONCURRENCY_VALUES) {
for (int type : RESULT_SET_TYPE_VALUES) {
for (int concurrency : CONCURRENCY_VALUES) {
try {
if (databaseMetaData.supportsResultSetConcurrency(
type, concurrency))
type, concurrency))
{
String driverName =
databaseMetaData.getDriverName();
Expand All @@ -218,12 +220,15 @@ protected Set<List<Integer>> deduceSupportedResultSetStyles(
new ArrayList<Integer>(
Arrays.asList(type, concurrency)));
}
} catch (SQLException e) {
// DB2 throws "com.ibm.db2.jcc.b.SqlException: Unknown type
// or Concurrency" for certain values of type/concurrency.
// No harm in interpreting all such exceptions as 'this
// database does not support this type/concurrency
// combination'.
Util.discard(e);
}
}
} catch (SQLException e11) {
throw Util.newInternal(
e11,
"while detecting result set concurrency");
}
return supports;
}
Expand All @@ -238,7 +243,7 @@ protected Set<List<Integer>> deduceSupportedResultSetStyles(
*
* @param conn The database connection
* @return Whether the feature is enabled.
* @throws SQLException
* @throws SQLException on error
*/
protected boolean deduceSupportsSelectNotInGroupBy(Connection conn)
throws SQLException
Expand Down
8 changes: 8 additions & 0 deletions src/main/mondrian/util/Bug.java
Expand Up @@ -165,6 +165,14 @@ public class Bug {
*/
public static final boolean BugMondrian648Fixed = false;

/**
* Whether
* <a href="http://jira.pentaho.com/browse/MONDRIAN-675">bug MONDRIAN-675,
* "Allow rollup of measures based on AVG aggregate function"</a>
* is fixed.
*/
public static final boolean BugMondrian675Fixed = false;

/**
* Returns whether to avoid a test because the memory monitor may cause it
* to fail.
Expand Down
47 changes: 20 additions & 27 deletions src/main/mondrian/xmla/XmlaHandler.java
Expand Up @@ -1304,11 +1304,27 @@ private QueryResult executeDrillThroughQuery(XmlaRequest request)
for (MondrianDef.Relation relation1 : relationList) {
final String tableName = relation1.toString();
List<String> fieldNameList = new ArrayList<String>();
// FIXME: Quote table name
dtSql = "SELECT * FROM " + tableName + " WHERE 1=2";
ResultSet rs = stmt.executeQuery(dtSql);
Dialect dialect =
((RolapSchema) connection.getSchema()).getDialect();
// FIXME: Include schema name, if specified.
// FIXME: Deal with relations that are not tables.
final StringBuilder buf = new StringBuilder();
buf.append("SELECT * FROM ");
dialect.quoteIdentifier(buf, tableName);
buf.append(" WHERE 1=2");
String sql = buf.toString();
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData rsMeta = rs.getMetaData();
for (int j = 1; j <= rsMeta.getColumnCount(); j++) {
// FIXME: In some JDBC drivers,
// ResultSetMetaData.getColumnName(int) does strange
// things with aliased columns. See MONDRIAN-654
// http://jira.pentaho.com/browse/MONDRIAN-654 for
// details. Therefore, we don't want to use that
// method. It seems harmless here, but I'd still
// like to phase out use of getColumnName. After
// PhysTable is introduced (coming in mondrian-4.0)
// we should be able to just use its column list.
String colName = rsMeta.getColumnName(j);
boolean colNameExists = false;
for (List<String> prvField : fields) {
Expand All @@ -1318,7 +1334,7 @@ private QueryResult executeDrillThroughQuery(XmlaRequest request)
}
}
if (!colNameExists) {
fieldNameList.add(rsMeta.getColumnName(j));
fieldNameList.add(colName);
}
}
fields.add(fieldNameList);
Expand Down Expand Up @@ -1540,29 +1556,6 @@ public void unparse(SaxWriter writer) throws SAXException {
}
}

public TabularRowSet(ResultSet rs) throws SQLException {
ResultSetMetaData md = rs.getMetaData();
int columnCount = md.getColumnCount();

// populate column definitions
for (int i = 0; i < columnCount; i++) {
columns.add(
new Column(
md.getColumnName(i + 1),
md.getColumnType(i + 1)));
}

// populate data
rows = new ArrayList<Object[]>();
while (rs.next()) {
Object[] row = new Object[columnCount];
for (int i = 0; i < columnCount; i++) {
row[i] = rs.getObject(i + 1);
}
rows.add(row);
}
}

/**
* Writes the tabular drillthrough schema
*
Expand Down

0 comments on commit 68407eb

Please sign in to comment.