Search in sources :

Example 1 with DescendantsCrossJoinArg

use of mondrian.rolap.sql.DescendantsCrossJoinArg in project mdx-kylin by Kyligence.

the class RolapNativeDescendants method createEvaluator.

NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args, RolapNative from, Util.Function3<CrossJoinArg[], SchemaReader, TupleConstraint, NativeEvaluator> createEvaluator) {
    if (!fun.getName().equalsIgnoreCase("Descendants")) {
        return null;
    }
    final List<RolapMeasureGroup> measureGroupList = new ArrayList<RolapMeasureGroup>();
    if (!SqlContextConstraint.checkValidContext(evaluator, true, Collections.<RolapCubeLevel>emptyList(), restrictMemberTypes(), measureGroupList)) {
        return null;
    }
    CrossJoinArg[] cjArgs = crossJoinArgFactory().checkDescendants(evaluator, evaluator.getSchemaReader().getRole(), fun, args);
    if (cjArgs == null || !(cjArgs[0] instanceof DescendantsCrossJoinArg && ((DescendantsCrossJoinArg) cjArgs[0]).isLeaves()))
        return null;
    else {
        ((DescendantsCrossJoinArg) cjArgs[0]).pullUpMember();
    }
    if (isPreferInterpreter(cjArgs, false)) {
        return null;
    }
    final SqlQuery sqlQuery = SqlQuery.newQuery(evaluator.getDialect(), "NativeFilter");
    RolapNativeSql sql = new RolapNativeSql(sqlQuery, null, evaluator, cjArgs[0]);
    final int savepoint = evaluator.savepoint();
    try {
        overrideContext(evaluator, cjArgs, sql.getStoredMeasure());
        // Make it a special case of Filter(Descendants)) that has null filter condition
        TupleConstraint constraint = new RolapNativeFilter.FilterDescendantsConstraint(cjArgs, evaluator, measureGroupList, null);
        return createEvaluator.apply(cjArgs, evaluator.getSchemaReader(), constraint);
    } finally {
        evaluator.restore(savepoint);
    }
}
Also used : TupleConstraint(mondrian.rolap.sql.TupleConstraint) SqlQuery(mondrian.rolap.sql.SqlQuery) ArrayList(java.util.ArrayList) DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) CrossJoinArg(mondrian.rolap.sql.CrossJoinArg) DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) TupleConstraint(mondrian.rolap.sql.TupleConstraint)

Example 2 with DescendantsCrossJoinArg

use of mondrian.rolap.sql.DescendantsCrossJoinArg in project mondrian by pentaho.

the class SqlTupleReader method chooseAggStar.

/**
 * Obtains the AggStar instance which corresponds to an aggregate table which can be used to support the member
 * constraint.
 *
 * @param constraint The tuple constraint to apply.
 * @param evaluator  the current evaluator to obtain the cube and members to be queried  @return AggStar for aggregate
 *                   table
 * @param baseCube   The base cube from which to choose an aggregation star. Can be null, in which case we use the
 *                   evaluator's cube.
 */
AggStar chooseAggStar(TupleConstraint constraint, Evaluator evaluator, RolapCube baseCube) {
    if (!MondrianProperties.instance().UseAggregates.get()) {
        return null;
    }
    if (evaluator == null || !constraint.supportsAggTables()) {
        return null;
    }
    if (baseCube == null) {
        baseCube = (RolapCube) evaluator.getCube();
    }
    // Current cannot support aggregate tables for virtual cubes
    if (baseCube.isVirtual()) {
        return null;
    }
    RolapStar star = baseCube.getStar();
    final int starColumnCount = star.getColumnCount();
    BitKey measureBitKey = BitKey.Factory.makeBitKey(starColumnCount);
    BitKey levelBitKey = BitKey.Factory.makeBitKey(starColumnCount);
    // Convert global ordinal to cube based ordinal (the 0th dimension
    // is always [Measures]). In the case of filter constraint this will
    // be the measure on which the filter will be done.
    // Since we support aggregated members as arguments, we'll expand
    // this too.
    // Failing to do so could result in chosing the wrong aggstar, as the
    // level would not be passed to the bitkeys
    final Member[] members = SqlConstraintUtils.expandSupportedCalculatedMembers(Arrays.asList(evaluator.getNonAllMembers()), evaluator).getMembersArray();
    // if measure is calculated, we can't continue
    if (!(members[0] instanceof RolapBaseCubeMeasure)) {
        return null;
    }
    RolapBaseCubeMeasure measure = (RolapBaseCubeMeasure) members[0];
    int bitPosition = ((RolapStar.Measure) measure.getStarMeasure()).getBitPosition();
    // set a bit for each level which is constrained in the context
    final CellRequest request = RolapAggregationManager.makeRequest(members);
    if (request == null) {
        // One or more calculated members. Cannot use agg table.
        return null;
    }
    // TODO: RME why is this using the array of constrained columns
    // from the CellRequest rather than just the constrained columns
    // BitKey (method getConstrainedColumnsBitKey)?
    RolapStar.Column[] columns = request.getConstrainedColumns();
    for (RolapStar.Column column1 : columns) {
        levelBitKey.set(column1.getBitPosition());
    }
    // set the masks
    for (TargetBase target : targets) {
        RolapLevel level = target.level;
        if (!level.isAll()) {
            RolapStar.Column column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
            if (column != null) {
                levelBitKey.set(column.getBitPosition());
            }
        }
    }
    // Set the bits for limited rollup members
    RolapUtil.constraintBitkeyForLimitedMembers(evaluator, evaluator.getMembers(), baseCube, levelBitKey);
    measureBitKey.set(bitPosition);
    if (constraint instanceof RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) {
        // Cannot evaluate NonEmptyCrossJoinConstraint using an agg
        // table if one of its args is a DescendantsConstraint.
        RolapNativeCrossJoin.NonEmptyCrossJoinConstraint necj = (RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) constraint;
        for (CrossJoinArg arg : necj.args) {
            if (arg instanceof DescendantsCrossJoinArg || arg instanceof MemberListCrossJoinArg) {
                final RolapLevel level = arg.getLevel();
                if (level != null && !level.isAll()) {
                    RolapStar.Column column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
                    if (column == null) {
                        // target group.
                        continue;
                    }
                    levelBitKey.set(column.getBitPosition());
                }
            }
        }
    } else if (constraint instanceof RolapNativeFilter.FilterConstraint) {
        for (Member slicer : ((RolapEvaluator) evaluator).getSlicerMembers()) {
            final Level level = slicer.getLevel();
            if (level != null && !level.isAll()) {
                final RolapStar.Column column = ((RolapCubeLevel) level).getBaseStarKeyColumn(baseCube);
                levelBitKey.set(column.getBitPosition());
            }
        }
    }
    // find the aggstar using the masks
    return AggregationManager.findAgg(star, levelBitKey, measureBitKey, new boolean[] { false });
}
Also used : DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) MemberListCrossJoinArg(mondrian.rolap.sql.MemberListCrossJoinArg) CrossJoinArg(mondrian.rolap.sql.CrossJoinArg) DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) TupleConstraint(mondrian.rolap.sql.TupleConstraint) MemberChildrenConstraint(mondrian.rolap.sql.MemberChildrenConstraint) CellRequest(mondrian.rolap.agg.CellRequest) Level(mondrian.olap.Level) MemberListCrossJoinArg(mondrian.rolap.sql.MemberListCrossJoinArg) Member(mondrian.olap.Member)

Example 3 with DescendantsCrossJoinArg

use of mondrian.rolap.sql.DescendantsCrossJoinArg in project mdx-kylin by Kyligence.

the class RolapNativeCount method createEvaluator.

@Override
NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) {
    if (!isEnabled()) {
        return null;
    }
    if (!(fun.getName().equalsIgnoreCase("Count") && (args[0] instanceof ResolvedFunCall))) {
        return null;
    }
    ResolvedFunCall countTargetFun = (ResolvedFunCall) args[0];
    fun = countTargetFun.getFunDef();
    args = countTargetFun.getArgs();
    // Use native cache instead of Cache function
    if (fun.getName().equalsIgnoreCase("Cache") && args.length == 1 && (args[0] instanceof ResolvedFunCall)) {
        countTargetFun = (ResolvedFunCall) args[0];
        fun = countTargetFun.getFunDef();
        args = countTargetFun.getArgs();
    }
    RolapNative nativeFilter = evaluator.getSchemaReader().getSchema().getNativeRegistry().getRolapNative(fun);
    NativeEvaluator nativeEvaluator;
    if (nativeFilter instanceof RolapNativeFilter) {
        nativeEvaluator = ((RolapNativeFilter) nativeFilter).createEvaluator(evaluator, fun, args, this, CountEvaluator::new);
    } else if (nativeFilter instanceof RolapNativeDescendants) {
        nativeEvaluator = ((RolapNativeDescendants) nativeFilter).createEvaluator(evaluator, fun, args, this, CountEvaluator::new);
    } else {
        return null;
    }
    if (nativeEvaluator == null || nativeEvaluator instanceof CountEvaluator && (((CountEvaluator) nativeEvaluator).args[0] == null || !(((CountEvaluator) nativeEvaluator).args[0] instanceof DescendantsCrossJoinArg))) {
        return null;
    }
    return nativeEvaluator;
}
Also used : DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) ResolvedFunCall(mondrian.mdx.ResolvedFunCall)

Example 4 with DescendantsCrossJoinArg

use of mondrian.rolap.sql.DescendantsCrossJoinArg in project mdx-kylin by Kyligence.

the class SqlTupleReader method prepareTuples.

private void prepareTuples(Dialect dialect, DataSource dataSource, TupleList partialResult, List<List<RolapMember>> newPartialResult) {
    String message = "Populating member cache with members for " + targets;
    SqlStatement stmt = null;
    final ResultSet resultSet;
    boolean execQuery = Objects.isNull(partialResult);
    try {
        if (execQuery) {
            List<Target> partialTargets = getPartialTargets();
            boolean shouldHasLimit = true;
            if (constraint instanceof RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) {
                RolapNativeCrossJoin.NonEmptyCrossJoinConstraint nonEmptyCrossJoinConstraint = (RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) constraint;
                if (nonEmptyCrossJoinConstraint.args[0] instanceof DescendantsCrossJoinArg && ((DescendantsCrossJoinArg) nonEmptyCrossJoinConstraint.args[0]).isLeaves() && nonEmptyCrossJoinConstraint.args[1] instanceof DescendantsCrossJoinArg && ((DescendantsCrossJoinArg) nonEmptyCrossJoinConstraint.args[1]).isLeaves())
                    shouldHasLimit = false;
            }
            if (constraint instanceof RolapNativeFilter.FilterDescendantsConstraint) {
                if (((RolapNativeFilter.FilterDescendantsConstraint) constraint).isLeaves()) {
                    shouldHasLimit = false;
                }
            }
            final Pair<String, List<SqlStatement.Type>> pair = makeLevelMembersSql(dialect, shouldHasLimit);
            String sql = pair.left;
            List<SqlStatement.Type> types = pair.right;
            assert sql != null && !sql.equals("");
            if (!sql.contains("limit") && (XmlaRequestContext.getContext().filterRowLimitFlag || (sql.contains("LIKE '%") && MondrianProperties.instance().FilterRowLimit.get() > 0))) {
                sql = sql + " limit " + MondrianProperties.instance().FilterRowLimit.get();
            }
            stmt = RolapUtil.executeQuery(dataSource, sql, types, maxRows, 0, new SqlStatement.StatementLocus(getExecution(), "SqlTupleReader.prepareTuples " + partialTargets, message, SqlStatementEvent.Purpose.TUPLES, 0), -1, -1, null);
            resultSet = stmt.getResultSet();
        } else {
            resultSet = null;
        }
        for (Target target : targets) {
            target.open();
        }
        int limit = MondrianProperties.instance().ResultLimit.get();
        int fetchCount = 0;
        // determine how many enum targets we have
        int enumTargetCount = getEnumTargetCount();
        int[] srcMemberIdxes = null;
        if (enumTargetCount > 0) {
            srcMemberIdxes = new int[enumTargetCount];
        }
        boolean moreRows;
        int currPartialResultIdx = 0;
        if (execQuery) {
            moreRows = resultSet.next();
            if (moreRows) {
                ++stmt.rowCount;
            }
        } else {
            moreRows = currPartialResultIdx < partialResult.size();
        }
        while (moreRows) {
            if (limit > 0 && limit < ++fetchCount) {
                // result limit exceeded, throw an exception
                throw MondrianResource.instance().MemberFetchLimitExceeded.ex((long) limit);
            }
            if (enumTargetCount == 0) {
                if (constraint instanceof RolapNativeFilter.FilterDescendantsConstraint && ((RolapNativeFilter.FilterDescendantsConstraint) constraint).isLeaves()) {
                    // Only read the lowest-level member from one result row, this member should be a leaf
                    List<Target> targets2 = new ArrayList<>(targets);
                    Collections.sort(targets2);
                    Collections.reverse(targets2);
                    for (Target target : targets2) {
                        target.setCurrMember(null);
                        if (target.addRow(stmt) != null)
                            break;
                    }
                } else {
                    for (Target target : targets) {
                        target.setCurrMember(null);
                        target.addRow(stmt);
                    }
                }
            } else {
                // find the first enum target, then call addTargets()
                // to form the cross product of the row from resultSet
                // with each of the list of members corresponding to
                // the enumerated targets
                int firstEnumTarget = 0;
                for (; firstEnumTarget < targets.size(); firstEnumTarget++) {
                    if (targets.get(firstEnumTarget).srcMembers != null) {
                        break;
                    }
                }
                List<RolapMember> partialRow;
                if (execQuery) {
                    partialRow = null;
                } else {
                    partialRow = Util.cast(partialResult.get(currPartialResultIdx));
                }
                resetCurrMembers(partialRow);
                addTargets(0, firstEnumTarget, enumTargetCount, srcMemberIdxes, stmt, message);
                if (newPartialResult != null) {
                    savePartialResult(newPartialResult);
                }
            }
            if (execQuery) {
                moreRows = resultSet.next();
                if (moreRows) {
                    ++stmt.rowCount;
                }
            } else {
                currPartialResultIdx++;
                moreRows = currPartialResultIdx < partialResult.size();
            }
        }
    } catch (SQLException e) {
        if (stmt == null) {
            throw Util.newError(e, message);
        } else {
            throw stmt.handle(e);
        }
    } finally {
        if (stmt != null) {
            stmt.close();
        }
    }
}
Also used : SQLException(java.sql.SQLException) DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) ArrayList(java.util.ArrayList) TupleConstraint(mondrian.rolap.sql.TupleConstraint) ResultSet(java.sql.ResultSet) ListTupleList(mondrian.calc.impl.ListTupleList) ArrayList(java.util.ArrayList) UnaryTupleList(mondrian.calc.impl.UnaryTupleList) TupleList(mondrian.calc.TupleList) List(java.util.List)

Example 5 with DescendantsCrossJoinArg

use of mondrian.rolap.sql.DescendantsCrossJoinArg in project mdx-kylin by Kyligence.

the class SqlTupleReader method chooseAggStar.

/**
 * Obtains the AggStar instance which corresponds to an aggregate table
 * which can be used to support the member constraint.
 *
 * @param constraint Constraint
 * @param measureGroup1 Measure group
 * @param evaluator the current evaluator to obtain the cube and members to
 *        be queried
 * @return AggStar for aggregate table
 */
AggStar chooseAggStar(TupleConstraint constraint, RolapMeasureGroup measureGroup1, Evaluator evaluator) {
    if (!MondrianProperties.instance().UseAggregates.get()) {
        return null;
    }
    if (evaluator == null) {
        return null;
    }
    // Convert global ordinal to cube based ordinal (the 0th dimension
    // is always [Measures]). In the case of filter constraint this will
    // be the measure on which the filter will be done.
    final Member[] members = evaluator.getNonAllMembers();
    // if measure is calculated, we can't continue
    if (!(members[0] instanceof RolapBaseCubeMeasure)) {
        return null;
    }
    RolapBaseCubeMeasure measure = (RolapBaseCubeMeasure) members[0];
    int bitPosition = measure.getStarMeasure().getBitPosition();
    // set a bit for each level which is constrained in the context
    final CellRequest request = RolapAggregationManager.makeRequest(members);
    if (request == null) {
        // One or more calculated members. Cannot use agg table.
        return null;
    }
    // TODO: RME why is this using the array of constrained columns
    // from the CellRequest rather than just the constrained columns
    // BitKey (method getConstrainedColumnsBitKey)?
    final RolapMeasureGroup measureGroup = measure.getMeasureGroup();
    final RolapStar star = measureGroup.getStar();
    final int starColumnCount = star.getColumnCount();
    BitKey measureBitKey = BitKey.Factory.makeBitKey(starColumnCount);
    BitKey levelBitKey = BitKey.Factory.makeBitKey(starColumnCount);
    RolapStar.Column[] columns = request.getConstrainedColumns();
    for (RolapStar.Column column1 : columns) {
        levelBitKey.set(column1.getBitPosition());
    }
    // set the masks
    for (Target target : targets) {
        RolapCubeLevel level = target.level;
        if (!level.isAll()) {
            RolapStar.Column starColumn = level.getBaseStarKeyColumn(measureGroup);
            if (starColumn != null) {
                levelBitKey.set(starColumn.getBitPosition());
            }
        }
    }
    measureBitKey.set(bitPosition);
    if (constraint instanceof RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) {
        // Cannot evaluate NonEmptyCrossJoinConstraint using an agg
        // table if one of its args is a DescendantsConstraint.
        RolapNativeCrossJoin.NonEmptyCrossJoinConstraint necj = (RolapNativeCrossJoin.NonEmptyCrossJoinConstraint) constraint;
        for (CrossJoinArg arg : necj.args) {
            if (arg instanceof DescendantsCrossJoinArg || arg instanceof MemberListCrossJoinArg) {
                final RolapLevel level = arg.getLevel();
                if (level != null && !level.isAll()) {
                    final RolapCubeLevel cubeLevel = (RolapCubeLevel) level;
                    for (RolapSchema.PhysColumn physColumn : cubeLevel.attribute.getKeyList()) {
                        RolapStar.Column column = measureGroup1.getRolapStarColumn(cubeLevel.cubeDimension, physColumn, true);
                        levelBitKey.set(column.getBitPosition());
                    }
                }
            }
        }
    }
    // find the aggstar using the masks
    return AggregationManager.findAgg(star, levelBitKey, measureBitKey, new boolean[] { false });
}
Also used : DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) MemberListCrossJoinArg(mondrian.rolap.sql.MemberListCrossJoinArg) CrossJoinArg(mondrian.rolap.sql.CrossJoinArg) DescendantsCrossJoinArg(mondrian.rolap.sql.DescendantsCrossJoinArg) TupleConstraint(mondrian.rolap.sql.TupleConstraint) CellRequest(mondrian.rolap.agg.CellRequest) MemberListCrossJoinArg(mondrian.rolap.sql.MemberListCrossJoinArg) Member(mondrian.olap.Member)

Aggregations

DescendantsCrossJoinArg (mondrian.rolap.sql.DescendantsCrossJoinArg)6 CrossJoinArg (mondrian.rolap.sql.CrossJoinArg)4 TupleConstraint (mondrian.rolap.sql.TupleConstraint)4 ArrayList (java.util.ArrayList)2 Member (mondrian.olap.Member)2 CellRequest (mondrian.rolap.agg.CellRequest)2 MemberListCrossJoinArg (mondrian.rolap.sql.MemberListCrossJoinArg)2 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 List (java.util.List)1 TupleList (mondrian.calc.TupleList)1 ListTupleList (mondrian.calc.impl.ListTupleList)1 UnaryTupleList (mondrian.calc.impl.UnaryTupleList)1 ResolvedFunCall (mondrian.mdx.ResolvedFunCall)1 Level (mondrian.olap.Level)1 MemberChildrenConstraint (mondrian.rolap.sql.MemberChildrenConstraint)1 SqlQuery (mondrian.rolap.sql.SqlQuery)1