rolapstar.java
来自「数据仓库展示程序」· Java 代码 · 共 1,660 行 · 第 1/4 页
JAVA
1,660 行
public Column[] lookupColumns(String tableAlias, String columnName) {
final Table table = factTable.findDescendant(tableAlias);
return (table == null) ? null : table.lookupColumns(columnName);
}
public Column[] lookupColumns(BitKey bitKey) {
List list = new ArrayList();
factTable.loadColumns(bitKey, list);
return (Column[]) list.toArray(new Column[0]);
}
/**
* This is used by TestAggregationManager only
*
* @param tableAlias
* @param columnName
* @return
*/
public Column lookupColumn(String tableAlias, String columnName) {
final Table table = factTable.findDescendant(tableAlias);
return (table == null) ? null : table.lookupColumn(columnName);
}
/**
* Returns a list of all aliases used in this star.
*/
public List getAliasList() {
List aliasList = new ArrayList();
if (factTable != null) {
collectAliases(aliasList, factTable);
}
return aliasList;
}
/**
* Finds all of the table aliases in a table and its children.
*/
private static void collectAliases(List aliasList, Table table) {
aliasList.add(table.getAlias());
for (int i = 0; i < table.children.size(); i++) {
Table child = (Table) table.children.get(i);
collectAliases(aliasList, child);
}
}
/**
* Reads a cell of <code>measure</code>, where <code>columns</code> are
* constrained to <code>values</code>. <code>values</code> must be the
* same length as <code>columns</code>; null values are left unconstrained.
**/
Object getCell(CellRequest request) {
Connection jdbcConnection = getJdbcConnection();
try {
return getCell(request, jdbcConnection);
} finally {
try {
jdbcConnection.close();
} catch (SQLException e) {
//ignore
}
}
}
private Object getCell(CellRequest request, Connection jdbcConnection) {
Measure measure = request.getMeasure();
Column[] columns = request.getColumns();
Object[] values = request.getSingleValues();
Util.assertTrue(columns.length == values.length);
SqlQuery sqlQuery = getSqlQuery();
// add measure
Util.assertTrue(measure.getTable() == factTable);
factTable.addToFrom(sqlQuery, true, true);
sqlQuery.addSelect(
measure.aggregator.getExpression(measure.getExpression(sqlQuery)));
// add constraining dimensions
for (int i = 0; i < columns.length; i++) {
Object value = values[i];
if (value == null) {
continue; // not constrained
}
Column column = columns[i];
Table table = column.getTable();
if (table.isFunky()) {
// this is a funky dimension -- ignore for now
continue;
}
table.addToFrom(sqlQuery, true, true);
}
String sql = sqlQuery.toString();
ResultSet resultSet = null;
try {
resultSet = RolapUtil.executeQuery(
jdbcConnection, sql, "RolapStar.getCell");
Object o = null;
if (resultSet.next()) {
o = resultSet.getObject(1);
}
if (o == null) {
o = Util.nullValue; // convert to placeholder
}
return o;
} catch (SQLException e) {
throw Util.newInternal(e,
"while computing single cell; sql=[" + sql + "]");
} finally {
try {
if (resultSet != null) {
resultSet.getStatement().close();
resultSet.close();
}
} catch (SQLException e) {
// ignore
}
}
}
private boolean containsColumn(String tableName, String columnName) {
final Connection jdbcConnection = getJdbcConnection();
try {
final DatabaseMetaData metaData = jdbcConnection.getMetaData();
final ResultSet columns =
metaData.getColumns(null, null, tableName, columnName);
final boolean hasNext = columns.next();
return hasNext;
} catch (SQLException e) {
throw Util.newInternal("Error while retrieving metadata for table '" +
tableName + "', column '" + columnName + "'");
} finally {
try {
jdbcConnection.close();
} catch (SQLException e) {
// ignore
}
}
}
public RolapSchema getSchema() {
return schema;
}
public String toString() {
StringWriter sw = new StringWriter(256);
PrintWriter pw = new PrintWriter(sw);
print(pw, "");
pw.flush();
return sw.toString();
}
public void print(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.println("RolapStar:");
String subprefix = prefix + " ";
factTable.print(pw, subprefix);
for (Iterator it = getAggStars(); it.hasNext(); ) {
AggStar aggStar = (AggStar) it.next();
aggStar.print(pw, subprefix);
}
}
/**
* A column in a star schema.
*/
public static class Column {
private final Table table;
private final MondrianDef.Expression expression;
private final boolean isNumeric;
private final String name;
/**
* When a Column is a column, and not a Measure, the parent column
* is the coloumn associated with next highest Level.
*/
private final Column parentColumn;
/**
* This is used during both aggregate table recognition and aggregate
* table generation. For multiple dimension usages or multiple shared
* dimension with the same column names, this is used to disambiguate
* aggregate column names.
*/
private final String usagePrefix;
/**
* This is only used in RolapAggregationManager and adds
* non-constraining columns making the drill-through queries easier for
* humans to understand.
*/
private final Column nameColumn;
private boolean isNameColumn;
/** this has a unique value per star */
private final int bitPosition;
private int cardinality = -1;
private Column(String name,
Table table,
MondrianDef.Expression expression,
boolean isNumeric) {
this(name, table, expression, isNumeric, null, null, null);
}
private Column(String name,
Table table,
MondrianDef.Expression expression,
boolean isNumeric,
Column nameColumn,
Column parentColumn,
String usagePrefix
) {
this.name = name;
this.table = table;
this.expression = expression;
this.isNumeric = isNumeric;
this.bitPosition = table.star.nextColumnCount();
this.nameColumn = nameColumn;
this.parentColumn = parentColumn;
this.usagePrefix = usagePrefix;
if (nameColumn != null) {
nameColumn.isNameColumn = true;
}
}
public boolean equals(Object obj) {
if (! (obj instanceof RolapStar.Column)) {
return false;
}
RolapStar.Column other = (RolapStar.Column) obj;
// Note: both columns have to be from the same table
return (other.table == this.table) &&
other.expression.equals(this.expression) &&
(other.isNumeric == this.isNumeric) &&
other.name.equals(this.name);
}
public String getName() {
return name;
}
public boolean isNumeric() {
return isNumeric;
}
public int getBitPosition() {
return bitPosition;
}
public RolapStar getStar() {
return table.star;
}
public RolapStar.Table getTable() {
return table;
}
public SqlQuery getSqlQuery() {
return getTable().getStar().getSqlQuery();
}
public RolapStar.Column getNameColumn() {
return nameColumn;
}
public RolapStar.Column getParentColumn() {
return parentColumn;
}
public String getUsagePrefix() {
return usagePrefix;
}
public boolean isNameColumn() {
return isNameColumn;
}
public MondrianDef.Expression getExpression() {
return expression;
}
public String getExpression(SqlQuery query) {
return expression.getExpression(query);
}
private static void quoteValue(
Object o,
StringBuffer buf,
boolean isNumeric) {
String s = o.toString();
if (isNumeric) {
buf.append(s);
} else {
if (s == null) {
buf.append("NULL");
} else {
Util.singleQuoteString(s, buf);
}
}
}
public int getCardinality() {
if (cardinality == -1) {
Connection jdbcConnection = getStar().getJdbcConnection();
try {
cardinality = getCardinality(jdbcConnection);
} finally {
try {
jdbcConnection.close();
} catch (SQLException e) {
//ignore
}
}
}
return cardinality;
}
private int getCardinality(Connection jdbcConnection) {
SqlQuery sqlQuery = getSqlQuery();
if (sqlQuery.getDialect().allowsCountDistinct()) {
// e.g. "select count(distinct product_id) from product"
sqlQuery.addSelect("count(distinct "
+ getExpression(sqlQuery) + ")");
// no need to join fact table here
table.addToFrom(sqlQuery, true, false);
} else if (sqlQuery.getDialect().allowsFromQuery()) {
// Some databases (e.g. Access) don't like 'count(distinct)',
// so use, e.g., "select count(*) from (select distinct
// product_id from product)"
SqlQuery inner = sqlQuery.cloneEmpty();
inner.setDistinct(true);
inner.addSelect(getExpression(inner));
boolean failIfExists = true,
joinToParent = false;
table.addToFrom(inner, failIfExists, joinToParent);
sqlQuery.addSelect("count(*)");
sqlQuery.addFrom(inner, "init", failIfExists);
} else {
throw Util.newInternal("Cannot compute cardinality: this " +
"database neither supports COUNT DISTINCT nor SELECT in " +
"the FROM clause.");
}
String sql = sqlQuery.toString();
ResultSet resultSet = null;
try {
resultSet = RolapUtil.executeQuery(
jdbcConnection, sql,
"RolapStar.Column.getCardinality");
Util.assertTrue(resultSet.next());
return resultSet.getInt(1);
} catch (SQLException e) {
throw Util.newInternal(e,
"while counting distinct values of column '" +
expression.getGenericExpression() +
"'; sql=[" + sql + "]");
} finally {
try {
if (resultSet != null) {
resultSet.getStatement().close();
resultSet.close();
}
} catch (SQLException e) {
// ignore
}
}
}
/**
* Generates a predicate that a column matches one of a list of values.
*
* <p>
* Several possible outputs, depending upon whether the there are
* nulls:<ul>
*
* <li>One not-null value: <code>foo.bar = 1</code>
*
* <li>All values not null: <code>foo.bar in (1, 2, 3)</code></li
*
* <li>Null and not null values:
* <code>(foo.bar is null or foo.bar in (1, 2))</code></li>
*
* <li>Only null values:
* <code>foo.bar is null</code></li>
*
* <li>String values: <code>foo.bar in ('a', 'b', 'c')</code></li></ul>
*/
public static String createInExpr(
String expr,
ColumnConstraint[] constraints,
boolean isNumeric) {
if (constraints.length == 1) {
final ColumnConstraint constraint = constraints[0];
Object key = constraint.getValue();
if (key != RolapUtil.sqlNullValue) {
StringBuffer buf = new StringBuffer(64);
buf.append(expr);
buf.append(" = ");
quoteValue(key, buf, isNumeric);
return buf.toString();
}
}
int notNullCount = 0;
StringBuffer sb = new StringBuffer(expr);
sb.append(" in (");
for (int i = 0; i < constraints.length; i++) {
final ColumnConstraint constraint = constraints[i];
Object key = constraint.getValue();
if (key == RolapUtil.sqlNullValue) {
continue;
}
if (notNullCount > 0) {
sb.append(", ");
}
++notNullCount;
quoteValue(key, sb, isNumeric);
}
sb.append(')');
if (notNullCount < constraints.length) {
// There was at least one null.
StringBuffer buf;
switch (notNullCount) {
case 0:
// Special case -- there were no values besides null.
// Return, for example, "x is null".
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?