Skip to content

Commit

Permalink
MONDRIAN: Fix bug MONDRIAN-560, "StrToMember function doesn't use
Browse files Browse the repository at this point in the history
    IgnoreInvalidMembers option". (Basic fix contributed by Anton Nitikin.) Also
    fix StrToTuple and StrToSet. Break out StrToMemberFunDef as a top-level
    class.

    Rationalize how we figure out whether the schema is being loaded, and
    therefore we should use IgnoreInvalidMembers as opposed to
    IgnoreInvalidMembersDuringQuery.

[git-p4: depot-paths = "//open/mondrian-release/3.2/": change = 13595]
  • Loading branch information
julianhyde committed May 2, 2010
1 parent 80b8dc2 commit 69f3df6
Show file tree
Hide file tree
Showing 12 changed files with 314 additions and 142 deletions.
58 changes: 23 additions & 35 deletions src/main/mondrian/olap/ConnectionBase.java
Expand Up @@ -56,15 +56,15 @@ public String getFullConnectString() {
}

public QueryPart parseStatement(String query) {
return parseStatement(query, null, false, false);
return parseStatement(query, null, false);
}

public Query parseQuery(String query) {
return (Query) parseStatement(query);
}

public Query parseQuery(String query, boolean load) {
return (Query) parseStatement(query, null, load, false);
return (Query) parseStatement(query, null, false);
}

/**
Expand All @@ -87,43 +87,12 @@ public QueryPart parseStatement(
String query,
FunTable funTable,
boolean strictValidation)
{
return parseStatement(query, funTable, false, strictValidation);
}

public Exp parseExpression(String expr) {
boolean debug = false;
if (getLogger().isDebugEnabled()) {
//debug = true;
getLogger().debug(
Util.nl
+ expr);
}
try {
Parser parser = new Parser();
final FunTable funTable = getSchema().getFunTable();
return parser.parseExpression(this, expr, debug, funTable);
} catch (Throwable exception) {
throw MondrianResource.instance().FailedToParseQuery.ex(
expr,
exception);
}
}

private QueryPart parseStatement(
String query,
FunTable cftab,
boolean load,
boolean strictValidation)
{
Parser parser = new Parser();
boolean debug = false;
final FunTable funTable;

if (cftab == null) {
if (funTable == null) {
funTable = getSchema().getFunTable();
} else {
funTable = cftab;
}

if (getLogger().isDebugEnabled()) {
Expand All @@ -136,11 +105,30 @@ private QueryPart parseStatement(
try {
return
parser.parseInternal(
this, query, debug, funTable, load, strictValidation);
this, query, debug, funTable, strictValidation);
} catch (Exception e) {
throw MondrianResource.instance().FailedToParseQuery.ex(query, e);
}
}

public Exp parseExpression(String expr) {
boolean debug = false;
if (getLogger().isDebugEnabled()) {
//debug = true;
getLogger().debug(
Util.nl
+ expr);
}
try {
Parser parser = new Parser();
final FunTable funTable = getSchema().getFunTable();
return parser.parseExpression(this, expr, debug, funTable);
} catch (Throwable exception) {
throw MondrianResource.instance().FailedToParseQuery.ex(
expr,
exception);
}
}
}

// End ConnectionBase.java
5 changes: 1 addition & 4 deletions src/main/mondrian/olap/Parser.cup
Expand Up @@ -27,7 +27,6 @@ parser code {:
private String queryString;
private Connection mdxConnection;
private FunTable funTable;
private boolean load;
private boolean strictValidation;

/**
Expand All @@ -48,15 +47,13 @@ parser code {:
String queryString,
boolean debug,
FunTable funTable,
boolean load,
boolean strictValidation)
{
Symbol parse_tree;
this.scanner = new StringScanner(queryString, debug);
this.mdxConnection = mdxConnection;
this.queryString = queryString;
this.funTable = funTable;
this.load = load;
this.strictValidation = strictValidation;
try {
if (debug) {
Expand Down Expand Up @@ -161,7 +158,7 @@ parser code {:
false, slicer, AxisOrdinal.StandardAxisOrdinal.SLICER,
QueryAxis.SubtotalVisibility.Undefined, new Id[0]);
return new Query(
mdxConnection, formulae, axes, cube, slicerAxis, cellProps, load,
mdxConnection, formulae, axes, cube, slicerAxis, cellProps,
strictValidation);
}

Expand Down
16 changes: 4 additions & 12 deletions src/main/mondrian/olap/Query.java
Expand Up @@ -153,11 +153,6 @@ public class Query extends QueryPart {
*/
private List<RolapCube> baseCubes;

/**
* If true, loading schema
*/
private boolean load;

/**
* If true, enforce validation even when ignoreInvalidMembers is set.
*/
Expand Down Expand Up @@ -193,7 +188,6 @@ public Query(
String cube,
QueryAxis slicerAxis,
QueryPart[] cellProps,
boolean load,
boolean strictValidation)
{
this(
Expand All @@ -204,7 +198,6 @@ public Query(
slicerAxis,
cellProps,
new Parameter[0],
load,
strictValidation);
}

Expand All @@ -219,7 +212,6 @@ public Query(
QueryAxis slicerAxis,
QueryPart[] cellProps,
Parameter[] parameters,
boolean load,
boolean strictValidation)
{
this.connection = connection;
Expand All @@ -237,7 +229,6 @@ public Query(
// assume, for now, that cross joins on virtual cubes can be
// processed natively; as we parse the query, we'll know otherwise
this.nativeCrossJoinVirtualCube = true;
this.load = load;
this.strictValidation = strictValidation;
this.alertedNonNativeFunDefs = new HashSet<FunDef>();
resolve();
Expand Down Expand Up @@ -373,7 +364,6 @@ public Query clone() {
(slicerAxis == null) ? null : (QueryAxis) slicerAxis.clone(),
cellProps,
parameters.toArray(new Parameter[parameters.size()]),
load,
strictValidation);
}

Expand Down Expand Up @@ -506,10 +496,12 @@ public void resolve() {
public boolean ignoreInvalidMembers()
{
MondrianProperties props = MondrianProperties.instance();
final boolean load = ((RolapCube) getCube()).isLoadInProgress();
return
!strictValidation
&& ((load && props.IgnoreInvalidMembers.get())
|| (!load && props.IgnoreInvalidMembersDuringQuery.get()));
&& (load
? props.IgnoreInvalidMembers.get()
: props.IgnoreInvalidMembersDuringQuery.get());
}

/**
Expand Down
33 changes: 1 addition & 32 deletions src/main/mondrian/olap/fun/BuiltinFunTable.java
Expand Up @@ -562,38 +562,7 @@ public Member evaluateMember(Evaluator evaluator) {
}
});

// StrToMember(<String Expression>)
builder.define(
new FunDefBase(
"StrToMember",
"Returns a member from a unique name String in MDX format.",
"fmS")
{
public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler)
{
final StringCalc memberNameCalc =
compiler.compileString(call.getArg(0));
return new AbstractMemberCalc(
call, new Calc[] {memberNameCalc})
{
public Member evaluateMember(Evaluator evaluator) {
String memberName =
memberNameCalc.evaluateString(evaluator);
return strToMember(evaluator, memberName);
}
};
}

Member strToMember(Evaluator evaluator, String memberName) {
Cube cube = evaluator.getCube();
SchemaReader schemaReader = evaluator.getSchemaReader();
List<Id.Segment> uniqueNameParts =
Util.parseIdentifier(memberName);
return (Member) schemaReader.lookupCompound(
cube, uniqueNameParts, true, Category.Member);
}
});

builder.define(StrToMemberFunDef.INSTANCE);
builder.define(ValidMeasureFunDef.instance);

//
Expand Down
41 changes: 38 additions & 3 deletions src/main/mondrian/olap/fun/FunUtil.java
Expand Up @@ -1878,7 +1878,7 @@ public static int compareSiblingMembers(Member m1, Member m2) {
/**
* Returns whether one of the members in a tuple is null.
*/
static boolean tupleContainsNullMember(Member[] tuple) {
public static boolean tupleContainsNullMember(Member[] tuple) {
for (Member member : tuple) {
if (member.isNull()) {
return true;
Expand Down Expand Up @@ -2243,7 +2243,7 @@ static List<Member[]> parseTupleList(
* @param hierarchies Hierarchies of the members
* @return Position where parsing ended in string
*/
static int parseTuple(
private static int parseTuple(
final Evaluator evaluator,
String string,
int i,
Expand All @@ -2264,6 +2264,27 @@ public void tupleComplete() {
return IdentifierParser.parseTuple(builder, string, i);
}

/**
* Parses a tuple, such as "([Gender].[M], [Marital Status].[S])".
*
* @param evaluator Evaluator, provides a {@link mondrian.olap.SchemaReader}
* and {@link Cube}
* @param string String to parse
* @param hierarchies Hierarchies of the members
* @return Tuple represented as array of members
*/
static Member[] parseTuple(
Evaluator evaluator, String string, Hierarchy[] hierarchies)
{
final Member[] members = new Member[hierarchies.length];
int i = parseTuple(evaluator, string, 0, members, hierarchies);
// todo: check for garbage at end of string
if (FunUtil.tupleContainsNullMember(members)) {
return null;
}
return members;
}

static List<Member> parseMemberList(
Evaluator evaluator,
String string,
Expand All @@ -2278,7 +2299,7 @@ static List<Member> parseMemberList(
return builder.memberList;
}

static int parseMember(
private static int parseMember(
Evaluator evaluator,
String string,
int i,
Expand All @@ -2298,6 +2319,20 @@ public void memberComplete() {
return IdentifierParser.parseMember(builder, string, i);
}

static Member parseMember(
Evaluator evaluator, String string, Hierarchy hierarchy)
{
Member[] members = {null};
int i = parseMember(evaluator, string, 0, members, hierarchy);
// todo: check for garbage at end of string
final Member member = members[0];
if (member == null) {
throw MondrianResource.instance().MdxChildObjectNotFound.ex(
string, evaluator.getCube().getQualifiedName());
}
return member;
}

// ~ Inner classes ---------------------------------------------------------

/**
Expand Down
49 changes: 49 additions & 0 deletions src/main/mondrian/olap/fun/StrToMemberFunDef.java
@@ -0,0 +1,49 @@
/*
// $Id$
// 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) 2010-2010 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.olap.fun;

import mondrian.calc.*;
import mondrian.calc.impl.AbstractMemberCalc;
import mondrian.mdx.ResolvedFunCall;
import mondrian.olap.*;

/**
* Definition of the <code>StrToMember</code> MDX function.
*
* <p>Syntax:
* <blockquote><code>StrToMember(&lt;String Expression&gt;)
* </code></blockquote>
*
* @version $Id$
*/
class StrToMemberFunDef extends FunDefBase {
public static final FunDef INSTANCE = new StrToMemberFunDef();

private StrToMemberFunDef() {
super(
"StrToMember",
"Returns a member from a unique name String in MDX format.",
"fmS");
}

public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
final StringCalc memberNameCalc =
compiler.compileString(call.getArg(0));
return new AbstractMemberCalc(call, new Calc[] {memberNameCalc}) {
public Member evaluateMember(Evaluator evaluator) {
String memberName =
memberNameCalc.evaluateString(evaluator);
return parseMember(evaluator, memberName, null);
}
};
}
}

// End StrToMemberFunDef.java
27 changes: 0 additions & 27 deletions src/main/mondrian/olap/fun/StrToTupleFunDef.java
Expand Up @@ -69,33 +69,6 @@ public Member[] evaluateTuple(Evaluator evaluator) {
}
}

/**
* Parses a tuple, such as "([Gender].[M], [Marital Status].[S])".
*
* @param evaluator Evaluator, provides a {@link mondrian.olap.SchemaReader}
* and {@link Cube}
* @param string String to parse
* @param hierarchies Hierarchies of the members
* @return Tuple represented as array of members
*/
private Member[] parseTuple(
Evaluator evaluator, String string, Hierarchy[] hierarchies)
{
final Member[] members = new Member[hierarchies.length];
int i = parseTuple(evaluator, string, 0, members, hierarchies);
// todo: check for garbage at end of string
return members;
}

private Member parseMember(
Evaluator evaluator, String string, Hierarchy hierarchy)
{
Member[] members = {null};
int i = parseMember(evaluator, string, 0, members, hierarchy);
// todo: check for garbage at end of string
return members[0];
}

public Exp createCall(Validator validator, Exp[] args) {
final int argCount = args.length;
if (argCount <= 1) {
Expand Down

0 comments on commit 69f3df6

Please sign in to comment.