Skip to content

Commit

Permalink
MONDRIAN: Fix MONDRIAN-539, "Problem with the MID function getting la…
Browse files Browse the repository at this point in the history
…st character

    in a string."

    Fix the String function. It was expecting an integer argument, should have
    been a string.

    Add more tests for Mid, Left, Right, String functions. In some cases we
    intentionally differ from SSAS behavior where SSAS is inconsistent with
    the VBA spec (which it purports to implement).

[git-p4: depot-paths = "//open/mondrian/": change = 12617]
  • Loading branch information
julianhyde committed Apr 17, 2009
1 parent 9b101aa commit d14e653
Show file tree
Hide file tree
Showing 8 changed files with 481 additions and 185 deletions.
30 changes: 14 additions & 16 deletions src/main/mondrian/olap/fun/JavaFunDef.java
Expand Up @@ -43,7 +43,7 @@ public class JavaFunDef extends FunDefBase {
mapClazzToCategory.put(float.class, Category.Numeric);
mapClazzToCategory.put(long.class, Category.Numeric);
mapClazzToCategory.put(double[].class, Category.Array);
mapClazzToCategory.put(char.class, Category.Integer);
mapClazzToCategory.put(char.class, Category.String);
mapClazzToCategory.put(byte.class, Category.Integer);
}

Expand Down Expand Up @@ -183,21 +183,19 @@ public Object evaluate(Evaluator evaluator) {
};
}
} else if (clazz == char.class) {
final IntegerCalc integerCalc = compiler.compileInteger(exp);
if (integerCalc.getResultStyle() == ResultStyle.VALUE_NOT_NULL) {
return new AbstractCalc2(exp, integerCalc) {
public Object evaluate(Evaluator evaluator) {
return (char) integerCalc.evaluateInteger(evaluator);
}
};
} else {
return new AbstractCalc2(exp, integerCalc) {
public Object evaluate(Evaluator evaluator) {
Integer i = (Integer) integerCalc.evaluate(evaluator);
return i == null ? null : (char) i.intValue();
}
};
}
final StringCalc stringCalc = compiler.compileString(exp);
return new AbstractCalc2(exp, stringCalc) {
public Object evaluate(Evaluator evaluator) {
final String string =
stringCalc.evaluateString(evaluator);
return
Character.valueOf(
string == null
|| string.length() < 1
? (char) 0
: string.charAt(0));
}
};
} else if (clazz == short.class) {
final IntegerCalc integerCalc = compiler.compileInteger(exp);
if (integerCalc.getResultStyle() == ResultStyle.VALUE_NOT_NULL) {
Expand Down
29 changes: 18 additions & 11 deletions src/main/mondrian/olap/fun/vba/Vba.java
Expand Up @@ -2,7 +2,7 @@
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// Copyright (C) 2007-2008 Julian Hyde
// Copyright (C) 2007-2009 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
Expand All @@ -21,6 +21,10 @@
* Implementations of functions in the Visual Basic for Applications (VBA)
* specification.
*
* <p>The functions are defined in
* <a href="http://msdn.microsoft.com/en-us/library/32s6akha(VS.80).aspx">MSDN
* </a>.
*
* @author jhyde
* @version $Id$
* @since Dec 31, 2007
Expand All @@ -29,7 +33,7 @@ public class Vba {
private static final long MILLIS_IN_A_DAY = 24 * 60 * 60 * 1000;

private static final DateFormatSymbols DATE_FORMAT_SYMBOLS
= new DateFormatSymbols(Locale.getDefault());
= new DateFormatSymbols(Locale.getDefault());

// Conversion

Expand Down Expand Up @@ -1659,22 +1663,25 @@ public static String mid(String value, int beginIndex) {
@Signature("Mid(value, beginIndex[, length])")
@Description("Returns a specified number of characters from a string.")
public static String mid(String value, int beginIndex, int length) {
if (beginIndex < 0) {
throw new InvalidArgumentException("Invalid parameter. "
+ "Start parameter of Mid function can't " + "be negative");
// Arguments are 1-based. Spec says that the function gives an error if
// Start <= 0 or Length < 0.
if (beginIndex <= 0) {
throw new InvalidArgumentException(
"Invalid parameter. "
+ "Start parameter of Mid function must be positive");
}
if (length < 0) {
throw new InvalidArgumentException("Invalid parameter. "
+ "Length parameter of Mid function can't " + "be negative");
throw new InvalidArgumentException(
"Invalid parameter. "
+ "Length parameter of Mid function must be non-negative");
}

if (beginIndex >= value.length()) {
if (beginIndex > value.length()) {
return "";
}

if (beginIndex != 0) {
--beginIndex;
}
// Shift from 1-based to 0-based.
--beginIndex;
int endIndex = beginIndex + length;
return endIndex >= value.length() ? value.substring(beginIndex) : value
.substring(beginIndex, endIndex);
Expand Down
18 changes: 18 additions & 0 deletions src/main/mondrian/util/Bug.java
Expand Up @@ -23,6 +23,24 @@
* @since Oct 11, 2006
*/
public class Bug {
/**
* Whether Mondrian is 100% compatible with Microsoft Analysis Services
* 2005. We know that it is not, so this constant is {@code false}.
*
* <p>Use this
* field to flag test cases whose behavior is intentionally different from
* SSAS. If the behavior is <em>un</em>intentionally different and something
* we want to fix, log a bug, add a new {@code BugMondrianXxxFixed} constant
* to this class, and make the test case conditional on that constant
* instead.
*
* <p>See also the property
* {@link mondrian.olap.MondrianProperties#SsasCompatibleNaming},
* which allows the user to choose certain behaviors which are compatible
* with SSAS 2005 but incompatible with Mondrian's previous behavior.
*/
public static final boolean Ssas2005Compatible = false;

/**
* Whether
* <a href="http://jira.pentaho.com/browse/MONDRIAN-229">MONDRIAN-229, "NON EMPTY when hierarchy's default member is not 'all'"</a>
Expand Down

0 comments on commit d14e653

Please sign in to comment.