use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.
the class SqlConstraintUtils method getColumnString.
/**
* Returns the column expression for the level, assuring
* appropriate tables are added to the from clause of
* sqlQuery if required.
* Determines the correct table and field based on the cube
* and whether an AggStar is present.
*/
private static String getColumnString(SqlQuery sqlQuery, AggStar aggStar, RolapLevel level, RolapCube baseCube) {
String columnString;
RolapStar.Column column = null;
if (level instanceof RolapCubeLevel) {
// this method can be called within the context of shared members,
// outside of the normal rolap star, therefore we need to
// check the level to see if it is a shared or cube level.
column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
}
// REVIEW: The following code mostly uses the name column (or name
// expression) of the level. Shouldn't it use the key column (or key
// expression)?
RolapHierarchy hierarchy = level.getHierarchy();
if (column != null) {
if (aggStar != null) {
// this assumes that the name column is identical to the
// id column
int bitPos = column.getBitPosition();
AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
AggStar.Table table = aggColumn.getTable();
table.addToFrom(sqlQuery, false, true);
columnString = aggColumn.generateExprString(sqlQuery);
} else {
RolapStar.Table targetTable = column.getTable();
hierarchy.addToFrom(sqlQuery, targetTable);
columnString = column.generateExprString(sqlQuery);
}
} else {
assert (aggStar == null);
hierarchy.addToFrom(sqlQuery, level.getKeyExp());
MondrianDef.Expression nameExp = level.getNameExp();
if (nameExp == null) {
nameExp = level.getKeyExp();
}
columnString = nameExp.getExpression(sqlQuery);
}
return columnString;
}
use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.
the class SqlMemberSource method makeChildMemberSql.
/**
* Generates the SQL statement to access the children of
* <code>member</code>. For example, <blockquote>
*
* <pre>SELECT "city"
* FROM "customer"
* WHERE "country" = 'USA'
* AND "state_province" = 'BC'
* GROUP BY "city"</pre>
* </blockquote> retrieves the children of the member
* <code>[Canada].[BC]</code>.
* <p>Note that this method is never called in the context of
* virtual cubes, it is only called on regular cubes.
*
* <p>See also {@link SqlTupleReader#makeLevelMembersSql}.
*/
Pair<String, List<SqlStatement.Type>> makeChildMemberSql(RolapMember member, DataSource dataSource, MemberChildrenConstraint constraint) {
SqlQuery sqlQuery = SqlQuery.newQuery(dataSource, "while generating query to retrieve children of member " + member);
// If this is a non-empty constraint, it is more efficient to join to
// an aggregate table than to the fact table. See whether a suitable
// aggregate table exists.
AggStar aggStar = chooseAggStar(constraint, member);
// Create the condition, which is either the parent member or
// the full context (non empty).
constraint.addMemberConstraint(sqlQuery, null, aggStar, member);
RolapLevel level = (RolapLevel) member.getLevel().getChildLevel();
boolean levelCollapsed = (aggStar != null) && isLevelCollapsed(aggStar, (RolapCubeLevel) level);
boolean multipleCols = SqlMemberSource.levelContainsMultipleColumns(level);
if (levelCollapsed && !multipleCols) {
// if this is a single column collapsed level, there is
// no need to join it with dimension tables
RolapStar.Column starColumn = ((RolapCubeLevel) level).getStarKeyColumn();
int bitPos = starColumn.getBitPosition();
AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
String q = aggColumn.generateExprString(sqlQuery);
final String qAlias = sqlQuery.addSelectGroupBy(q, starColumn.getInternalType());
sqlQuery.addOrderBy(q, qAlias, true, false, true, true);
aggColumn.getTable().addToFrom(sqlQuery, false, true);
return sqlQuery.toSqlAndTypes();
}
hierarchy.addToFrom(sqlQuery, level.getKeyExp());
String q = level.getKeyExp().getExpression(sqlQuery);
String idAlias = sqlQuery.addSelectGroupBy(q, level.getInternalType());
// in non empty mode the level table must be joined to the fact
// table
constraint.addLevelConstraint(sqlQuery, null, aggStar, level);
if (levelCollapsed) {
// if this is a collapsed level, add a join between key and aggstar
RolapStar.Column starColumn = ((RolapCubeLevel) level).getStarKeyColumn();
int bitPos = starColumn.getBitPosition();
AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
RolapStar.Condition condition = new RolapStar.Condition(level.getKeyExp(), aggColumn.getExpression());
sqlQuery.addWhere(condition.toString(sqlQuery));
hierarchy.addToFromInverse(sqlQuery, level.getKeyExp());
// also may need to join parent levels to make selection unique
RolapCubeLevel parentLevel = (RolapCubeLevel) level.getParentLevel();
boolean isUnique = level.isUnique();
while (parentLevel != null && !parentLevel.isAll() && !isUnique) {
hierarchy.addToFromInverse(sqlQuery, parentLevel.getKeyExp());
starColumn = parentLevel.getStarKeyColumn();
bitPos = starColumn.getBitPosition();
aggColumn = aggStar.lookupColumn(bitPos);
condition = new RolapStar.Condition(parentLevel.getKeyExp(), aggColumn.getExpression());
sqlQuery.addWhere(condition.toString(sqlQuery));
parentLevel = parentLevel.getParentLevel();
}
}
if (level.hasCaptionColumn()) {
MondrianDef.Expression captionExp = level.getCaptionExp();
if (!levelCollapsed) {
hierarchy.addToFrom(sqlQuery, captionExp);
}
String captionSql = captionExp.getExpression(sqlQuery);
sqlQuery.addSelectGroupBy(captionSql, null);
}
if (!levelCollapsed) {
hierarchy.addToFrom(sqlQuery, level.getOrdinalExp());
}
final String orderBy = level.getOrdinalExp().getExpression(sqlQuery);
if (!orderBy.equals(q)) {
String orderAlias = sqlQuery.addSelectGroupBy(orderBy, null);
sqlQuery.addOrderBy(orderBy, orderAlias, true, false, true, true);
} else {
sqlQuery.addOrderBy(q, idAlias, true, false, true, true);
}
RolapProperty[] properties = level.getProperties();
for (RolapProperty property : properties) {
final MondrianDef.Expression exp = property.getExp();
if (!levelCollapsed) {
hierarchy.addToFrom(sqlQuery, exp);
}
final String s = exp.getExpression(sqlQuery);
String alias = sqlQuery.addSelect(s, null);
// group by that are functionally dependent on the level value
if (!sqlQuery.getDialect().allowsSelectNotInGroupBy() || !property.dependsOnLevelValue()) {
sqlQuery.addGroupBy(s, alias);
}
}
return sqlQuery.toSqlAndTypes();
}
Aggregations