Skip to content

Commit

Permalink
MONDRIAN: Fixes for
Browse files Browse the repository at this point in the history
* DB2 loader and regression tests: unquoted identifiers are required
* add AllMembers as a function with supporting regression tests
* fix rounding problem in UdfTest.testComplexFun
* better regression test reporting for XmlaTest

[git-p4: depot-paths = "//open/mondrian/": change = 4002]
  • Loading branch information
Sherman Wood committed Aug 22, 2005
1 parent 59753e5 commit 6edfd20
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 125 deletions.
4 changes: 2 additions & 2 deletions demo/FoodMart.xml
Expand Up @@ -182,7 +182,7 @@ fname + ' ' + lname
"customer"."fullname"
</SQL>
<SQL dialect="db2">
CONCAT(CONCAT("fname", ' '), "lname")
CONCAT(CONCAT(fname, ' '), lname)
</SQL>
<SQL dialect="generic">
fullname
Expand Down Expand Up @@ -516,7 +516,7 @@ fname + ' ' + lname
"customer"."fullname"
</SQL>
<SQL dialect="db2">
CONCAT(CONCAT("fname", ' '), "lname")
CONCAT(CONCAT(fname, ' '), lname)
</SQL>
<SQL dialect="generic">
fullname
Expand Down
48 changes: 48 additions & 0 deletions src/main/mondrian/olap/fun/BuiltinFunTable.java
Expand Up @@ -1584,6 +1584,22 @@ public Object evaluate(Evaluator evaluator, Exp[] args) {
}
});

/*
* Clone of <Dimension>.Members for compatibility with MSAS
*/

define(new FunDefBase(
"AllMembers",
"<Dimension>.AllMembers",
"Returns the set of all members in a dimension.",
"pxd") {
public Object evaluate(Evaluator evaluator, Exp[] args) {
Dimension dimension = (Dimension) getArg(evaluator, args, 0);
Hierarchy hierarchy = dimension.getHierarchy();
return addMembers(evaluator.getSchemaReader(), new ArrayList(), hierarchy);
}
});

define(new FunDefBase(
"Members",
"<Hierarchy>.Members",
Expand All @@ -1596,6 +1612,22 @@ public Object evaluate(Evaluator evaluator, Exp[] args) {
}
});

/*
* Clone of <Hierarchy>.Members for compatibility with MSAS
*/

define(new FunDefBase(
"AllMembers",
"<Hierarchy>.AllMembers",
"Returns the set of all members in a hierarchy.",
"pxh") {
public Object evaluate(Evaluator evaluator, Exp[] args) {
Hierarchy hierarchy = (Hierarchy) getArg(evaluator, args, 0);
return addMembers(evaluator.getSchemaReader(),
new ArrayList(), hierarchy);
}
});

define(new FunDefBase(
"Members",
"<Level>.Members",
Expand All @@ -1606,6 +1638,22 @@ public Object evaluate(Evaluator evaluator, Exp[] args) {
return Arrays.asList(evaluator.getSchemaReader().getLevelMembers(level));
}
});

/*
* Clone of <Level>.Members for compatibility with MSAS
*/

define(new FunDefBase(
"AllMembers",
"<Level>.AllMembers",
"Returns the set of all members in a level.",
"pxl") {
public Object evaluate(Evaluator evaluator, Exp[] args) {
Level level = (Level) getArg(evaluator, args, 0);
return Arrays.asList(evaluator.getSchemaReader().getLevelMembers(level));
}
});

define(new XtdFunDef.Resolver(
"Mtd",
"Mtd([<Member>])",
Expand Down
6 changes: 5 additions & 1 deletion src/main/mondrian/rolap/sql/SqlQuery.java
Expand Up @@ -749,7 +749,11 @@ public void quoteIdentifier(final String qual,
}

public String getQuoteIdentifierString() {
return quoteIdentifierString;
if (isDB2()) {
return null;
} else {
return quoteIdentifierString;
}
}

/**
Expand Down
67 changes: 48 additions & 19 deletions testsrc/main/mondrian/test/BasicQueryTest.java
Expand Up @@ -627,9 +627,6 @@ public void testDrillThrough() {
" {[Product].Children} on rows" + nl +
"from Sales");
String sql = result.getCell(new int[] {0, 0}).getDrillThroughSQL(false);
// the following replacement is for databases in ANSI mode
// using '"' to quote identifiers
sql = sql.replace('"', '`');

String tableQualifier = "as ";
RolapConnection conn = (RolapConnection) getConnection();
Expand All @@ -638,18 +635,32 @@ public void testDrillThrough() {
// " + tableQualifier + "
tableQualifier = "";
}
assertEquals("select `time_by_day`.`the_year` as `Year`," +
" `product_class`.`product_family` as `Product Family`," +
" `sales_fact_1997`.`unit_sales` as `Unit Sales` " +
"from `time_by_day` " + tableQualifier + "`time_by_day`," +
" `sales_fact_1997` " + tableQualifier + "`sales_fact_1997`," +
" `product_class` " + tableQualifier + "`product_class`," +
" `product` " + tableQualifier + "`product` " +
"where `sales_fact_1997`.`time_id` = `time_by_day`.`time_id`" +
" and `time_by_day`.`the_year` = 1997" +
" and `sales_fact_1997`.`product_id` = `product`.`product_id`" +
" and `product`.`product_class_id` = `product_class`.`product_class_id`" +
" and `product_class`.`product_family` = 'Drink'", sql);

// the following replacement is for databases in ANSI mode
// using '"' to quote identifiers
sql = sql.replace('"', '`');

String expectedSQL = "select `time_by_day`.`the_year` as `Year`," +
" `product_class`.`product_family` as `Product Family`," +
" `sales_fact_1997`.`unit_sales` as `Unit Sales` " +
"from `time_by_day` " + tableQualifier + "`time_by_day`," +
" `sales_fact_1997` " + tableQualifier + "`sales_fact_1997`," +
" `product_class` " + tableQualifier + "`product_class`," +
" `product` " + tableQualifier + "`product` " +
"where `sales_fact_1997`.`time_id` = `time_by_day`.`time_id`" +
" and `time_by_day`.`the_year` = 1997" +
" and `sales_fact_1997`.`product_id` = `product`.`product_id`" +
" and `product`.`product_class_id` = `product_class`.`product_class_id`" +
" and `product_class`.`product_family` = 'Drink'";

/*
* DB2 does not have quotes on identifiers
*/
if (jdbc_url.toLowerCase().indexOf(":db2:") >= 0) {
expectedSQL = expectedSQL.replaceAll("`", "");
}

assertEquals(expectedSQL, sql);
sql = result.getCell(new int[] {1, 1}).getDrillThroughSQL(false);
assertNull(sql); // because it is a calculated member
}
Expand All @@ -674,14 +685,17 @@ public void testDrillThrough2() {
} else if (jdbc_url.toLowerCase().indexOf("derby") >= 0 ||
jdbc_url.toLowerCase().indexOf("cloudscape") >= 0) {
fname_plus_lname = " `customer`.`fullname` as `Name`,";
} else if (jdbc_url.toLowerCase().indexOf(":db2:") >= 0) {
fname_plus_lname = " CONCAT(CONCAT(fname, ' '), lname) as Name,";
} else {
fname_plus_lname = " fname + ' ' + lname as `Name`,";
}
/*
* What about generic?
<SQL dialect="generic">
fullname
</SQL>
*/ }
*/
// the following replacement is for databases in ANSI mode
// using '"' to quote identifiers
sql = sql.replace('"', '`');
Expand All @@ -691,7 +705,8 @@ public void testDrillThrough2() {
// " + tableQualifier + "
tableQualifier = "";
}
assertEquals("select `store`.`store_name` as `Store Name`," +

String expectedSQL = "select `store`.`store_name` as `Store Name`," +
" `store`.`store_city` as `Store City`," +
" `store`.`store_state` as `Store State`," +
" `store`.`store_country` as `Store Country`," +
Expand Down Expand Up @@ -731,8 +746,16 @@ public void testDrillThrough2() {
" and `product`.`product_class_id` = `product_class`.`product_class_id`" +
" and `product_class`.`product_family` = 'Drink'" +
" and `sales_fact_1997`.`promotion_id` = `promotion`.`promotion_id`" +
" and `sales_fact_1997`.`customer_id` = `customer`.`customer_id`",
sql);
" and `sales_fact_1997`.`customer_id` = `customer`.`customer_id`";

/*
* DB2 does not have quotes on identifiers
*/
if (jdbc_url.toLowerCase().indexOf(":db2:") >= 0) {
expectedSQL = expectedSQL.replaceAll("`", "");
}

assertEquals(expectedSQL, sql);
sql = result.getCell(new int[] {1, 1}).getDrillThroughSQL(true);
assertNull(sql); // because it is a calculated member
}
Expand Down Expand Up @@ -2617,6 +2640,12 @@ public void testCatalogHierarchyBasedOnView2() {
"<Dimension name=\"ProductView\" foreignKey=\"product_id\">" + nl +
" <Hierarchy hasAll=\"true\" primaryKey=\"product_id\" primaryKeyTable=\"productView\">" + nl +
" <View alias=\"productView\">" + nl +
" <SQL dialect=\"db2\"><![CDATA[" + nl +
"SELECT *" + nl +
"FROM product, product_class" + nl +
"WHERE product.product_class_id = product_class.product_class_id" + nl +
"]]>" + nl +
" </SQL>" + nl +
" <SQL dialect=\"generic\"><![CDATA[" + nl +
"SELECT *" + nl +
"FROM \"product\", \"product_class\"" + nl +
Expand Down
8 changes: 8 additions & 0 deletions testsrc/main/mondrian/test/ParentChildHierarchyTest.java
Expand Up @@ -512,6 +512,14 @@ private void checkDrillThroughSql(Result result,
assertEquals(expectedCell, cell.getFormattedValue());
String sql = cell.getDrillThroughSQL(extendedContext);
sql = sql.replace('"', '`');
/*
* DB2 does not have quotes on identifiers
*/
RolapConnection conn = (RolapConnection) getConnection();
String jdbc_url = conn.getConnectInfo().get("Jdbc");
if (jdbc_url.toLowerCase().indexOf(":db2:") >= 0) {
expectedSql = expectedSql.replaceAll("`", "");
}
assertEquals(expectedSql, sql);
}
}
Expand Down
7 changes: 6 additions & 1 deletion testsrc/main/mondrian/test/TestCalculatedMembers.java
Expand Up @@ -180,13 +180,18 @@ public void testCalculatedMemberInCubeAndQuery() {
}

public void _testWhole() {

/*
* "allmembers" tests compatibility with MSAS
*/

execute(
"with" + nl +
"member [Measures].[Total Store Sales by Product Name] as" + nl +
" 'Sum([Product].[Product Name].members, [Measures].[Store Sales])'" + nl +
"" + nl +
"member [Measures].[Average Store Sales by Product Name] as" + nl +
" 'Avg([Product].[Product Name].members, [Measures].[Store Sales])'" + nl +
" 'Avg([Product].[Product Name].allmembers, [Measures].[Store Sales])'" + nl +
"" + nl +
"member [Measures].[Number of Product Name members] as" + nl +
" 'Count([Product].[Product Name].members)'" + nl +
Expand Down
2 changes: 1 addition & 1 deletion testsrc/main/mondrian/test/UdfTest.java
Expand Up @@ -193,7 +193,7 @@ public void testComplexFun() {
"Row #1: 0.4628" + nl +
"Row #2: (null)" + nl +
"Row #3: 0.6251" + nl +
"Row #4: 0.5208" + nl +
"Row #4: 0.5209" + nl +
"Row #5: 0.5036" + nl);
}

Expand Down
73 changes: 46 additions & 27 deletions testsrc/main/mondrian/test/loader/MondrianFoodMartLoader.java
Expand Up @@ -61,7 +61,7 @@
* <blockquote><code>
* $ mysqladmin create foodmart<br/>
* $ java -cp 'classes;testclasses' mondrian.test.loader.MondrianFoodMartLoader
* -verbose -tables -data -indexes -jdbcDrivers=com.mysql.jdbc.Driver
* -tables -data -indexes -jdbcDrivers=com.mysql.jdbc.Driver
* -inputJdbcURL=jdbc:odbc:MondrianFoodMart -outputJdbcURL=jdbc:mysql://localhost/foodmart
* </code></blockquote>
*
Expand All @@ -74,7 +74,7 @@
* SQL&gt; QUIT;<br/>
* $ java -cp "/mondrian/lib/mondrian.jar:/mondrian/lib/log4j-1.2.9.jar:/mondrian/lib/eigenbase-xom.jar:/mondrian/lib/eigenbase-resgen.jar:/jdbc/fb/firebirdsql-full.jar"
* mondrian.test.loader.MondrianFoodMartLoader
* -verbose -tables -data -indexes
* -tables -data -indexes
* -jdbcDrivers="org.firebirdsql.jdbc.FBDriver"
* -inputFile="/mondrian/demo/FoodMartCreateData.sql"
* -outputJdbcURL="jdbc:firebirdsql:localhost/3050:/mondrian/foodmart.gdb"
Expand Down Expand Up @@ -207,7 +207,6 @@ public void usage() {
System.out.println(" <batch size> size of JDBC batch updates - default to 50 inserts");
System.out.println(" <jdbcDrivers> Comma-separated list of JDBC drivers.");
System.out.println(" They must be on the classpath.");
System.out.println(" -verbose Verbose mode.");
System.out.println(" -tables If specified, drop and create the tables.");
System.out.println(" -data If specified, load the data.");
System.out.println(" -indexes If specified, drop and create the tables.");
Expand Down Expand Up @@ -560,7 +559,9 @@ private void loadFromSQLInserts() throws Exception {
String toQuoteChar = null;
if (sqlQuery.getDialect().isMySQL()) {
toQuoteChar = "`";
} else {
} else if (sqlQuery.getDialect().isDB2()) {
toQuoteChar = "";
} else {
toQuoteChar = "\"";
}

Expand Down Expand Up @@ -620,6 +621,11 @@ private void loadFromSQLInserts() throws Exception {
*/
private int loadTable(String name, Column[] columns) throws Exception {
int rowsAdded = 0;

final DatabaseMetaData metaData = inputConnection.getMetaData();

SqlQuery inputSqlQuery = new SqlQuery(metaData);

StringBuffer buf = new StringBuffer();

buf.append("select ");
Expand All @@ -628,10 +634,10 @@ private int loadTable(String name, Column[] columns) throws Exception {
if (i > 0) {
buf.append(",");
}
buf.append(quoteId(column.name));
buf.append(quoteId(inputSqlQuery, column.name));
}
buf.append(" from ")
.append(quoteId(name));
.append(quoteId(inputSqlQuery, name));
String ddl = buf.toString();
Statement statement = inputConnection.createStatement();
LOGGER.debug("Input table SQL: " + ddl);
Expand Down Expand Up @@ -859,31 +865,31 @@ private void createIndexes() throws Exception {
createIndex(false, "time_by_day", "i_time_quarter", new String[] {"quarter"});
createIndex(false, "time_by_day", "i_time_month", new String[] {"month_of_year"});

createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls_97_pl_01_cust", new String[] {"customer_id"});
createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls_97_pl_01_prod", new String[] {"product_id"});
createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls_97_pl_01_time", new String[] {"time_id"});
createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls97pl01cust", new String[] {"customer_id"});
createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls97pl01prod", new String[] {"product_id"});
createIndex(false, "agg_pl_01_sales_fact_1997", "i_sls97pl01time", new String[] {"time_id"});

createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls_97_ll_01_cust", new String[] {"customer_id"});
createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls_97_ll_01_prod", new String[] {"product_id"});
createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls_97_ll_01_time", new String[] {"time_id"});
createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls97ll01cust", new String[] {"customer_id"});
createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls97ll01prod", new String[] {"product_id"});
createIndex(false, "agg_ll_01_sales_fact_1997", "i_sls97ll01time", new String[] {"time_id"});

createIndex(false, "agg_l_05_sales_fact_1997", "i_sls_97_l_05_cust", new String[] {"customer_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls_97_l_05_prod", new String[] {"product_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls_97_l_05_promo", new String[] {"promotion_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls_97_l_05_store", new String[] {"store_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls97l05cust", new String[] {"customer_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls97l05prod", new String[] {"product_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls97l05promo", new String[] {"promotion_id"});
createIndex(false, "agg_l_05_sales_fact_1997", "i_sls97l05store", new String[] {"store_id"});

createIndex(false, "agg_c_14_sales_fact_1997", "i_sls_97_c_14_cust", new String[] {"customer_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls_97_c_14_prod", new String[] {"product_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls_97_c_14_promo", new String[] {"promotion_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls_97_c_14_store", new String[] {"store_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls97c14cust", new String[] {"customer_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls97c14prod", new String[] {"product_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls97c14promo", new String[] {"promotion_id"});
createIndex(false, "agg_c_14_sales_fact_1997", "i_sls97c14store", new String[] {"store_id"});

createIndex(false, "agg_lc_100_sales_fact_1997", "i_sls_97_lc_100_cust", new String[] {"customer_id"});
createIndex(false, "agg_lc_100_sales_fact_1997", "i_sls_97_lc_100_prod", new String[] {"product_id"});
createIndex(false, "agg_lc_100_sales_fact_1997", "i_sls97lc100cust", new String[] {"customer_id"});
createIndex(false, "agg_lc_100_sales_fact_1997", "i_sls97lc100prod", new String[] {"product_id"});

createIndex(false, "agg_c_special_sales_fact_1997", "i_sls_97_spec_cust", new String[] {"customer_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls_97_spec_prod", new String[] {"product_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls_97_spec_promo", new String[] {"promotion_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls_97_spec_store", new String[] {"store_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls97speccust", new String[] {"customer_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls97specprod", new String[] {"product_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls97specpromo", new String[] {"promotion_id"});
createIndex(false, "agg_c_special_sales_fact_1997", "i_sls97specstore", new String[] {"store_id"});

if (outputDirectory != null) {
fileOutput.close();
Expand Down Expand Up @@ -1458,11 +1464,24 @@ private void executeDDL(String ddl) throws Exception {

/**
* Quote the given SQL identifier suitable for the output DBMS.
*
* @param name
* @return
*/

private String quoteId(String name) {
return sqlQuery.getDialect().quoteIdentifier(name);
return quoteId(sqlQuery, name);
}

/**
* Quote the given SQL identifier suitable for the given DBMS type.
*
* @param givenQueryType
* @param name
* @return
*/
private String quoteId(SqlQuery givenQueryType, String name) {
return givenQueryType.getDialect().quoteIdentifier(name);
}

/**
Expand Down

0 comments on commit 6edfd20

Please sign in to comment.