Skip to content

Commit

Permalink
MONDRIAN: Add RolapStar.generateSql, for generating SQL to populate a…
Browse files Browse the repository at this point in the history
…n aggregate table.

    Re-order the parameters of SqlQuery.Dialect.quoteIdentifier, using varargs to quote multi-part identifiers.
    Add UnionIterator, to make it easier to iterate over two lists in one for-each loop.

[git-p4: depot-paths = "//open/mondrian/": change = 10974]
  • Loading branch information
julianhyde committed Apr 28, 2008
1 parent e419c9c commit 34a4caf
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 71 deletions.
66 changes: 63 additions & 3 deletions src/main/mondrian/olap/Util.java
Expand Up @@ -36,8 +36,7 @@
import mondrian.resource.MondrianResource;
import mondrian.spi.UserDefinedFunction;
import mondrian.mdx.*;
import mondrian.util.UtilCompatible;
import mondrian.util.Pair;
import mondrian.util.*;

/**
* Utility functions used throughout mondrian. All methods are static.
Expand Down Expand Up @@ -1302,6 +1301,67 @@ public static <T> String commaList(
return buf.toString();
}

/**
* Returns the union of a list of iterables.
*
* <p>You can use it like this:
* <blockquote><pre>
* Iterable&lt;String&gt; iter1;
* Iterable&lt;String&gt; iter2;
* for (String s : union(iter1, iter2)) {
* print(s);
* }</pre></blockquote>
*
* @param iterables Array of one or more iterables
* @return iterable over the union
*/
public static <T> Iterable<T> union(
final Iterable<? extends T>... iterables) {
return new Iterable<T>() {
public Iterator<T> iterator() {
return new UnionIterator<T>(iterables);
}
};
}

/**
* Makes a name distinct from other names which have already been used
* and shorter than a length limit, adds it to the list, and returns it.
*
* @param name Suggested name, may not be unique
* @param maxLength Maximum length of generated name
* @param nameList Collection of names already used
*
* @return Unique name
*/
public static String uniquify(
String name,
int maxLength,
Collection<String> nameList)
{
assert name != null;
if (name.length() > maxLength) {
name = name.substring(0, maxLength);
}
if (nameList.contains(name)) {
String aliasBase = name;
int j = 0;
while (true) {
name = aliasBase + j;
if (name.length() > maxLength) {
aliasBase = aliasBase.substring(0, aliasBase.length() - 1);
continue;
}
if (!nameList.contains(name)) {
break;
}
j++;
}
}
nameList.add(name);
return name;
}

public static class ErrorCellValue {
public String toString() {
return "#ERR";
Expand Down Expand Up @@ -2206,7 +2266,7 @@ public static UserDefinedFunction createUdf(Class<?> udfClass) {
}

return udf;
}
}
}

// End Util.java
103 changes: 99 additions & 4 deletions src/main/mondrian/rolap/RolapStar.java
Expand Up @@ -889,6 +889,45 @@ public RolapSchema getSchema() {
return schema;
}

/**
* Generates a SQL statement to read all instances of the given attributes.
*
* <p>The SQL statement is of the form {@code SELECT ... FROM ... JOIN ...
* GROUP BY ...}. It is useful for populating an aggregate table.
*
* @param columnList List of columns (attributes and measures)
* @param columnNameList List of column names (must have same cardinality
* as {@code columnList})
* @return SQL SELECT statement
*/
public String generateSql(
List<Column> columnList,
List<String> columnNameList)
{
final SqlQuery query = new SqlQuery(sqlQueryDialect, true);
query.addFrom(
factTable.relation,
factTable.relation.getAlias(),
false);
int k = -1;
for (Column column : columnList) {
++k;
column.table.addToFrom(query, false, true);
String columnExpr = column.generateExprString(query);
if (column instanceof Measure) {
Measure measure = (Measure) column;
columnExpr = measure.getAggregator().getExpression(columnExpr);
}
final String columnName = columnNameList.get(k);
query.addSelect(columnExpr, columnName);
if (!(column instanceof Measure)) {
query.addGroupBy(columnExpr);
}
}
// remove whitespace from query - in particular, the trailing newline
return query.toString().trim();
}

public String toString() {
StringWriter sw = new StringWriter(256);
PrintWriter pw = new PrintWriter(sw);
Expand Down Expand Up @@ -1252,7 +1291,10 @@ public String toString() {
}

/**
* Prints this table and its children.
* Prints this column.
*
* @param pw Print writer
* @param prefix Prefix to print first, such as spaces for indentation
*/
public void print(PrintWriter pw, String prefix) {
SqlQuery sqlQuery = getSqlQuery();
Expand All @@ -1267,6 +1309,62 @@ public void print(PrintWriter pw, String prefix) {
public SqlQuery.Datatype getDatatype() {
return datatype;
}

/**
* Returns a string representation of the datatype of this column, in
* the dialect specified. For example, 'DECIMAL(10, 2) NOT NULL'.
*
* @param dialect Dialect
* @return String representation of column's datatype
*/
public String getDatatypeString(SqlQuery.Dialect dialect) {
final SqlQuery query = new SqlQuery(dialect);
query.addFrom(
table.star.factTable.relation, table.star.factTable.alias,
false);
query.addFrom(table.relation, table.alias, false);
query.addSelect(expression.getExpression(query));
final String sql = query.toString();
Connection jdbcConnection = null;
try {
jdbcConnection = table.star.dataSource.getConnection();
final PreparedStatement pstmt =
jdbcConnection.prepareStatement(sql);
final ResultSetMetaData resultSetMetaData =
pstmt.getMetaData();
assert resultSetMetaData.getColumnCount() == 1;
final String type = resultSetMetaData.getColumnTypeName(1);
int precision = resultSetMetaData.getPrecision(1);
final int scale = resultSetMetaData.getScale(1);
if (type.equals("DOUBLE")) {
precision = 0;
}
String typeString;
if (precision == 0) {
typeString = type;
} else if (scale == 0) {
typeString = type + "(" + precision + ")";
} else {
typeString = type + "(" + precision + ", " + scale + ")";
}
pstmt.close();
jdbcConnection.close();
jdbcConnection = null;
return typeString;
} catch (SQLException e) {
throw Util.newError(
e,
"Error while deriving type of column " + toString());
} finally {
if (jdbcConnection != null) {
try {
jdbcConnection.close();
} catch (SQLException e) {
// ignore
}
}
}
}
}

/**
Expand Down Expand Up @@ -1320,9 +1418,6 @@ public int hashCode() {
return h;
}

/**
* Prints this table and its children.
*/
public void print(PrintWriter pw, String prefix) {
SqlQuery sqlQuery = getSqlQuery();
pw.print(prefix);
Expand Down

0 comments on commit 34a4caf

Please sign in to comment.