use of mondrian.rolap.agg.ListColumnPredicate in project mondrian by pentaho.
the class SqlConstraintUtils method generateSingleValueInExpr.
/**
* Generates a multi-value IN expression corresponding to a list of
* member expressions, and adds the expression to the WHERE clause
* of a query, provided the member values are all non-null
*
* @param sqlQuery query containing the where clause
* @param baseCube base cube if virtual
* @param aggStar aggregate star if available
* @param members list of constraining members
* @param fromLevel lowest parent level that is unique
* @param restrictMemberTypes defines the behavior when calculated members
* are present
* @param exclude whether to exclude the members. Default is false.
* @param includeParentLevels whether to include IN list constraint
* for parent levels.
* @return a non-empty String if IN list was generated for the members.
*/
private static String generateSingleValueInExpr(SqlQuery sqlQuery, RolapCube baseCube, AggStar aggStar, List<RolapMember> members, RolapLevel fromLevel, boolean restrictMemberTypes, boolean exclude, boolean includeParentLevels) {
int maxConstraints = MondrianProperties.instance().MaxConstraints.get();
Dialect dialect = sqlQuery.getDialect();
String condition = "";
boolean firstLevel = true;
for (Collection<RolapMember> c = members; !c.isEmpty(); c = getUniqueParentMembers(c)) {
RolapMember m = c.iterator().next();
if (m.isAll()) {
continue;
}
if (m.isNull()) {
return "1 = 0";
}
if (m.isCalculated() && !m.isParentChildLeaf()) {
if (restrictMemberTypes) {
throw Util.newInternal("addMemberConstraint: cannot " + "restrict SQL to calculated member :" + m);
}
continue;
}
boolean containsNullKey = false;
Iterator<RolapMember> it = c.iterator();
while (it.hasNext()) {
m = it.next();
if (m.getKey() == RolapUtil.sqlNullValue) {
containsNullKey = true;
}
}
RolapLevel level = m.getLevel();
RolapHierarchy hierarchy = level.getHierarchy();
// 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.
RolapStar.Column column = null;
if (level instanceof RolapCubeLevel) {
column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
}
String q;
if (column != null) {
if (aggStar != null) {
int bitPos = column.getBitPosition();
AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
if (aggColumn == null) {
throw Util.newInternal("AggStar " + aggStar + " has no column for " + column + " (bitPos " + bitPos + ")");
}
AggStar.Table table = aggColumn.getTable();
table.addToFrom(sqlQuery, false, true);
q = aggColumn.generateExprString(sqlQuery);
} else {
RolapStar.Table targetTable = column.getTable();
hierarchy.addToFrom(sqlQuery, targetTable);
q = column.generateExprString(sqlQuery);
}
} else {
assert (aggStar == null);
hierarchy.addToFrom(sqlQuery, level.getKeyExp());
q = level.getKeyExp().getExpression(sqlQuery);
}
StarColumnPredicate cc = getColumnPredicates(column, c);
if (!dialect.supportsUnlimitedValueList() && cc instanceof ListColumnPredicate && ((ListColumnPredicate) cc).getPredicates().size() > maxConstraints) {
// Simply get them all, do not create where-clause.
// Below are two alternative approaches (and code). They
// both have problems.
LOG.debug(MondrianResource.instance().NativeSqlInClauseTooLarge.str(level.getUniqueName(), maxConstraints + ""));
sqlQuery.setSupported(false);
} else {
String where = RolapStar.Column.createInExpr(q, cc, level.getDatatype(), sqlQuery);
if (!where.equals("true")) {
if (!firstLevel) {
if (exclude) {
condition += " or ";
} else {
condition += " and ";
}
} else {
firstLevel = false;
}
if (exclude) {
where = "not (" + where + ")";
if (!containsNullKey) {
// Null key fails all filters so should add it here
// if not already excluded. E.g., if the original
// exclusion filter is :
//
// not(year = '1997' and quarter in ('Q1','Q3'))
//
// then with IS NULL checks added, the filter
// becomes:
//
// (not(year = '1997') or year is null) or
// (not(quarter in ('Q1','Q3')) or quarter is null)
where = "(" + where + " or " + "(" + q + " is null))";
}
}
condition += where;
}
}
if (m.getLevel().isUnique() || m.getLevel() == fromLevel || !includeParentLevels) {
// no further qualification needed
break;
}
}
return condition;
}
Aggregations