Search in sources :

Example 1 with ListColumnPredicate

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;
}
Also used : Table(mondrian.rolap.RolapStar.Table) ListColumnPredicate(mondrian.rolap.agg.ListColumnPredicate) Dialect(mondrian.spi.Dialect) AggStar(mondrian.rolap.aggmatcher.AggStar) Column(mondrian.rolap.RolapStar.Column) Table(mondrian.rolap.RolapStar.Table)

Aggregations

Column (mondrian.rolap.RolapStar.Column)1 Table (mondrian.rolap.RolapStar.Table)1 ListColumnPredicate (mondrian.rolap.agg.ListColumnPredicate)1 AggStar (mondrian.rolap.aggmatcher.AggStar)1 Dialect (mondrian.spi.Dialect)1