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);
}
}
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 });
}
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;
}
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();
}
}
}
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 });
}
Aggregations