Skip to content

Commit

Permalink
MONDRIAN: fix bug with SQL generation of invalid
Browse files Browse the repository at this point in the history
DATE/TIME/TIMESTAMP/BOOLEAN literals (suppress them the same
way invalid NUMERIC literals are suppressed); fix bug
with SQL predicate generation for the special case of
one null and one non-null member (c = X or c IS NULL);
change FoodMart.xml to declare type="Boolean" 
for [Has coffee bar] dimension in Store cube

[git-p4: depot-paths = "//open/mondrian/": change = 8429]
  • Loading branch information
jsichi committed Jan 2, 2007
1 parent 34b5921 commit ca5eed3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 2 deletions.
3 changes: 2 additions & 1 deletion demo/FoodMart.xml
Expand Up @@ -375,7 +375,8 @@ Iif("sales_fact_1997"."promotion_id" = 0, 0, "sales_fact_1997"."store_sales")

<Dimension name="Has coffee bar">
<Hierarchy hasAll="true">
<Level name="Has coffee bar" column="coffee_bar" uniqueMembers="true"/>
<Level name="Has coffee bar" column="coffee_bar" uniqueMembers="true"
type="Boolean"/>
</Hierarchy>
</Dimension>

Expand Down
4 changes: 3 additions & 1 deletion src/main/mondrian/rolap/RolapStar.java
Expand Up @@ -779,12 +779,14 @@ public static String createInExpr(
int notNullCount = 0;
StringBuilder buf = new StringBuilder(expr);
buf.append(" in (");
Object lastNotNull = null;
for (int i = 0; i < constraints.length; i++) {
final ColumnConstraint constraint = constraints[i];
Object key = constraint.getValue();
if (key == RolapUtil.sqlNullValue) {
continue;
}
lastNotNull = key;
if (notNullCount > 0) {
buf.append(", ");
}
Expand All @@ -806,7 +808,7 @@ public static String createInExpr(
buf.append('(');
buf.append(expr);
buf.append(" = ");
dialect.quote(buf, constraints[0].getValue(), datatype);
dialect.quote(buf, lastNotNull, datatype);
buf.append(" or ");
buf.append(expr);
buf.append(" is null)");
Expand Down
34 changes: 34 additions & 0 deletions src/main/mondrian/rolap/sql/SqlQuery.java
Expand Up @@ -850,6 +850,15 @@ public void quoteNumericLiteral(StringBuilder buf, String value) {
* <p>In the default dialect, boolean literals are printed as is.
*/
public void quoteBooleanLiteral(StringBuilder buf, String value) {
// NOTE jvs 1-Jan-2007: See quoteDateLiteral for explanation.
// In addition, note that we leave out UNKNOWN (even though
// it is a valid SQL:2003 literal) because it's really
// NULL in disguise, and NULL is always treated specially.
if (!value.equalsIgnoreCase("TRUE")
&& !(value.equalsIgnoreCase("FALSE"))) {
throw new NumberFormatException(
"Illegal BOOLEAN literal: " + value);
}
buf.append(value);
}

Expand All @@ -861,6 +870,17 @@ public void quoteBooleanLiteral(StringBuilder buf, String value) {
* appends <code>DATE '1969-03-17'</code>.
*/
public void quoteDateLiteral(StringBuilder buf, String value) {
// NOTE jvs 1-Jan-2007: Check that the supplied literal is in valid
// SQL:2003 date format. A hack in
// RolapSchemaReader.lookupMemberChildByName looks for
// NumberFormatException to suppress it, so that is why
// we convert the exception here.
try {
java.sql.Date.valueOf(value);
} catch (IllegalArgumentException ex) {
throw new NumberFormatException(
"Illegal DATE literal: " + value);
}
buf.append("DATE ");
Util.singleQuoteString(value, buf);
}
Expand All @@ -873,6 +893,13 @@ public void quoteDateLiteral(StringBuilder buf, String value) {
* appends <code>TIME '12:34:56'</code>.
*/
public void quoteTimeLiteral(StringBuilder buf, String value) {
// NOTE jvs 1-Jan-2007: See quoteDateLiteral for explanation.
try {
java.sql.Time.valueOf(value);
} catch (IllegalArgumentException ex) {
throw new NumberFormatException(
"Illegal TIME literal: " + value);
}
buf.append("TIME ");
Util.singleQuoteString(value, buf);
}
Expand All @@ -885,6 +912,13 @@ public void quoteTimeLiteral(StringBuilder buf, String value) {
* appends <code>TIMESTAMP '1969-03-17 12:34:56'</code>.
*/
public void quoteTimestampLiteral(StringBuilder buf, String value) {
// NOTE jvs 1-Jan-2007: See quoteTimestampLiteral for explanation.
try {
java.sql.Timestamp.valueOf(value);
} catch (IllegalArgumentException ex) {
throw new NumberFormatException(
"Illegal TIMESTAMP literal: " + value);
}
buf.append("TIMESTAMP ");
Util.singleQuoteString(value, buf);
}
Expand Down
19 changes: 19 additions & 0 deletions testsrc/main/mondrian/test/BasicQueryTest.java
Expand Up @@ -5011,6 +5011,25 @@ public void testNullMember() {
"Row #0: 33,307.69\n"));
}

public void testNullMemberWithOneNonNull() {
assertQueryReturns(
"SELECT \n" +
"{[Measures].[Store Cost]} ON columns, \n" +
"{[Store Size in SQFT].[All Store Size in SQFTs].[#null],[Store Size in SQFT].[ALL Store Size in SQFTs].[39696]} ON rows \n" +
"FROM [Sales] \n" +
"WHERE [Time].[1997]",
fold(
"Axis #0:\n" +
"{[Time].[1997]}\n" +
"Axis #1:\n" +
"{[Measures].[Store Cost]}\n" +
"Axis #2:\n" +
"{[Store Size in SQFT].[All Store Size in SQFTs].[#null]}\n" +
"{[Store Size in SQFT].[All Store Size in SQFTs].[39696]}\n" +
"Row #0: 33,307.69\n" +
"Row #1: 21,121.96\n"));
}

/**
* Tests whether the agg mgr behaves correctly if a cell request causes
* a column to be constrained multiple times. This happens if two levels
Expand Down
17 changes: 17 additions & 0 deletions testsrc/main/mondrian/test/TestCalculatedMembers.java
Expand Up @@ -711,6 +711,23 @@ public void testChildrenOfCalcMembers() {
"{[Product].[All Products].[Non-Consumable]}\n"));
}

public void testNonCharacterMembers() {
assertQueryReturns(
"with member [Has Coffee Bar].[Maybe] as " + nl
+ "'SUM([Has Coffee Bar].members)' " + nl
+ "SELECT {[Has Coffee Bar].[Maybe]} on rows, " + nl
+ "{[Measures].[Store Sqft]} on columns " + nl
+ "FROM [Store]",
fold(
"Axis #0:\n" +
"{}\n" +
"Axis #1:\n" +
"{[Measures].[Store Sqft]}\n" +
"Axis #2:\n" +
"{[Has coffee bar].[Maybe]}\n" +
"Row #0: 1,143,192\n"));
}

public void testFormatString() {
// Verify that
// (a) a calculated member without a format string does not
Expand Down

0 comments on commit ca5eed3

Please sign in to comment.