Search in sources :

Example 11 with AggStar

use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.

the class TestAggregationManager method testAggStarWithIgnoredColumnsAndCountDistinct.

public void testAggStarWithIgnoredColumnsAndCountDistinct() {
    propSaver.set(propSaver.properties.ReadAggregates, true);
    propSaver.set(propSaver.properties.UseAggregates, true);
    propSaver.set(propSaver.properties.GenerateFormattedSql, true);
    final TestContext context = TestContext.instance().withSchema("<Schema name=\"FoodMart\">" + "  <Dimension name=\"Time\" type=\"TimeDimension\">\n" + "    <Hierarchy hasAll=\"false\" primaryKey=\"time_id\">\n" + "      <Table name=\"time_by_day\"/>\n" + "      <Level name=\"Year\" column=\"the_year\" type=\"Numeric\" uniqueMembers=\"true\"\n" + "          levelType=\"TimeYears\"/>\n" + "      <Level name=\"Quarter\" column=\"quarter\" uniqueMembers=\"false\"\n" + "          levelType=\"TimeQuarters\"/>\n" + "    </Hierarchy>\n" + "  </Dimension>\n" + "<Cube name=\"Sales\" defaultMeasure=\"Unit Sales\">\n" + "  <Table name=\"sales_fact_1997\">\n" + "    <AggExclude name=\"agg_c_special_sales_fact_1997\" />\n" + "    <AggExclude name=\"agg_lc_100_sales_fact_1997\" />\n" + "    <AggExclude name=\"agg_lc_10_sales_fact_1997\" />\n" + "    <AggExclude name=\"agg_pc_10_sales_fact_1997\" />\n" + "    <AggName name=\"agg_g_ms_pcat_sales_fact_1997\">\n" + "        <AggFactCount column=\"FACT_COUNT\"/>\n" + "        <AggIgnoreColumn column=\"Quarter\"/>\n" + "        <AggIgnoreColumn column=\"MONTH_OF_YEAR\"/>\n" + "        <AggMeasure name=\"[Measures].[Customer Count]\" column=\"customer_count\" />\n" + "        <AggLevel name=\"[Time].[Year]\" column=\"the_year\" />\n" + "    </AggName>\n" + "  </Table>\n" + "  <DimensionUsage name=\"Time\" source=\"Time\" foreignKey=\"time_id\"/>\n" + "  <Measure name=\"Unit Sales\" column=\"unit_sales\" aggregator=\"sum\"\n" + "      formatString=\"Standard\"/>\n" + "  <Measure name=\"Customer Count\" column=\"customer_id\" aggregator=\"distinct-count\"\n" + "      formatString=\"Standard\"/>\n" + "</Cube>\n" + "</Schema>");
    RolapStar star = context.getConnection().getSchemaReader().getSchema().getStar("sales_fact_1997");
    AggStar aggStarSpy = spy(getAggStar(star, "agg_g_ms_pcat_sales_fact_1997"));
    // make sure the test AggStar will be prioritized first
    when(aggStarSpy.getSize()).thenReturn(0l);
    context.getConnection().getSchemaReader().getSchema().getStar("sales_fact_1997").addAggStar(aggStarSpy);
    boolean[] rollup = { false };
    AggStar returnedStar = AggregationManager.findAgg(star, aggStarSpy.getLevelBitKey(), aggStarSpy.getMeasureBitKey(), rollup);
    assertNull("Should not find an agg star given that ignored or unused " + "columns are present, and loading distinct count measure", returnedStar);
    String sqlOra = "select\n" + "    \"time_by_day\".\"the_year\" as \"c0\",\n" + "    count(distinct \"sales_fact_1997\".\"customer_id\") as \"m0\"\n" + "from\n" + "    \"time_by_day\" \"time_by_day\",\n" + "    \"sales_fact_1997\" \"sales_fact_1997\"\n" + "where\n" + "    \"sales_fact_1997\".\"time_id\" = \"time_by_day\".\"time_id\"\n" + "and\n" + "    \"time_by_day\".\"the_year\" = 1997\n" + "group by\n" + "    \"time_by_day\".\"the_year\"";
    String sqlMysql = "select\n" + "    `time_by_day`.`the_year` as `c0`,\n" + "    count(distinct `sales_fact_1997`.`customer_id`) as `m0`\n" + "from\n" + "    `time_by_day` as `time_by_day`,\n" + "    `sales_fact_1997` as `sales_fact_1997`\n" + "where\n" + "    `sales_fact_1997`.`time_id` = `time_by_day`.`time_id`\n" + "and\n" + "    `time_by_day`.`the_year` = 1997\n" + "group by\n" + "    `time_by_day`.`the_year`";
    assertQuerySqlOrNot(context, "select Time.[1997] on 0 from sales where " + "measures.[Customer Count]", new SqlPattern[] { new SqlPattern(Dialect.DatabaseProduct.MYSQL, sqlMysql, sqlMysql.length()), new SqlPattern(Dialect.DatabaseProduct.ORACLE, sqlOra, sqlOra.length()) }, false, false, true);
}
Also used : TestContext(mondrian.test.TestContext) SqlPattern(mondrian.test.SqlPattern) AggStar(mondrian.rolap.aggmatcher.AggStar)

Example 12 with AggStar

use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.

the class RolapStar method addAggStar.

/**
 * Adds an {@link AggStar} to this star.
 *
 * <p>Internally the AggStars are added in sort order, smallest row count
 * to biggest, so that the most efficient AggStar is encountered first;
 * ties do not matter.
 */
public void addAggStar(AggStar aggStar) {
    // Add it before the first AggStar which is larger, if there is one.
    long size = aggStar.getSize();
    ListIterator<AggStar> lit = aggStars.listIterator();
    while (lit.hasNext()) {
        AggStar as = lit.next();
        if (as.getSize() >= size) {
            lit.previous();
            lit.add(aggStar);
            return;
        }
    }
    // There is no larger star. Add at the end of the list.
    aggStars.add(aggStar);
}
Also used : AggStar(mondrian.rolap.aggmatcher.AggStar)

Example 13 with AggStar

use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.

the class SqlConstraintUtils method joinLevelTableToFactTable.

/**
 * Ensures that the table of <code>level</code> is joined to the fact
 * table
 *
 * @param sqlQuery sql query under construction
 * @param aggStar The aggStar to use, if any.
 * @param e evaluator corresponding to query
 * @param level level to be added to query
 */
public static void joinLevelTableToFactTable(SqlQuery sqlQuery, RolapCube baseCube, AggStar aggStar, Evaluator e, RolapCubeLevel level) {
    RolapStar.Column starColumn = level.getBaseStarKeyColumn(baseCube);
    if (aggStar != null) {
        int bitPos = starColumn.getBitPosition();
        AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
        AggStar.Table table = aggColumn.getTable();
        table.addToFrom(sqlQuery, false, true);
    } else {
        RolapStar.Table table = starColumn.getTable();
        assert table != null;
        table.addToFrom(sqlQuery, false, true);
    }
}
Also used : Table(mondrian.rolap.RolapStar.Table) AggStar(mondrian.rolap.aggmatcher.AggStar) Column(mondrian.rolap.RolapStar.Column) Table(mondrian.rolap.RolapStar.Table)

Example 14 with AggStar

use of mondrian.rolap.aggmatcher.AggStar 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)

Example 15 with AggStar

use of mondrian.rolap.aggmatcher.AggStar in project mondrian by pentaho.

the class SqlConstraintUtils method getLevelColumn.

/**
 * Gets the column, using AggStar if available, and ensures the table is in
 * the query.
 */
private static RolapStar.Column getLevelColumn(RolapLevel level, RolapCube baseCube, AggStar aggStar, SqlQuery sqlQuery) {
    final RolapStar.Column column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
    if (aggStar != null) {
        int bitPos = column.getBitPosition();
        final AggStar.Table.Column aggColumn = aggStar.lookupColumn(bitPos);
        AggStar.Table table = aggColumn.getTable();
        table.addToFrom(sqlQuery, false, true);
        // create a delegate to use the aggregated column's expression
        return new Column(aggColumn.getDatatype()) {

            public String generateExprString(SqlQuery query) {
                // used by predicates for sql generation
                return aggColumn.generateExprString(query);
            }

            public int getBitPosition() {
                // this is the same as the one in RolapStar.Column
                return aggColumn.getBitPosition();
            }

            public Table getTable() {
                return column.getTable();
            }

            public RolapStar getStar() {
                return column.getStar();
            }
        };
    } else {
        column.getTable().addToFrom(sqlQuery, false, true);
        return column;
    }
}
Also used : Table(mondrian.rolap.RolapStar.Table) SqlQuery(mondrian.rolap.sql.SqlQuery) Column(mondrian.rolap.RolapStar.Column) AggStar(mondrian.rolap.aggmatcher.AggStar) Column(mondrian.rolap.RolapStar.Column)

Aggregations

AggStar (mondrian.rolap.aggmatcher.AggStar)17 Table (mondrian.rolap.RolapStar.Table)6 Column (mondrian.rolap.RolapStar.Column)5 SqlPattern (mondrian.test.SqlPattern)3 TestContext (mondrian.test.TestContext)3 HashMap (java.util.HashMap)2 MondrianDef (mondrian.olap.MondrianDef)2 SqlQuery (mondrian.rolap.sql.SqlQuery)2 ArrayList (java.util.ArrayList)1 Iterator (java.util.Iterator)1 LinkedHashMap (java.util.LinkedHashMap)1 List (java.util.List)1 TupleList (mondrian.calc.TupleList)1 ListColumnPredicate (mondrian.rolap.agg.ListColumnPredicate)1 JdbcSchema (mondrian.rolap.aggmatcher.JdbcSchema)1 TupleConstraint (mondrian.rolap.sql.TupleConstraint)1 Dialect (mondrian.spi.Dialect)1 FilteredIterableList (mondrian.util.FilteredIterableList)1