public void addConstraint(SqlQuery sqlQuery, RolapCube baseCube, AggStar aggStar) { // Use aggregate table to generate filter condition RolapNativeSql sql = new RolapNativeSql(sqlQuery, aggStar, getEvaluator(), args[0].getLevel()); String filterSql = sql.generateFilterCondition(filterExpr); if (filterSql != null) { sqlQuery.addHaving(filterSql); } if (getEvaluator().isNonEmpty() || isJoinRequired()) { // only apply context constraint if non empty, or // if a join is required to fulfill the filter condition super.addConstraint(sqlQuery, baseCube, aggStar); } }
NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) { if (!isEnabled()) { return null; } if (!FilterConstraint.isValidContext(evaluator, restrictMemberTypes())) { return null; } // is this "Filter(<set>, <numeric expr>)" String funName = fun.getName(); if (!"Filter".equalsIgnoreCase(funName)) { return null; } if (args.length != 2) { return null; } // extract the set expression List<CrossJoinArg[]> allArgs = crossJoinArgFactory().checkCrossJoinArg(evaluator, args[0]); // checkCrossJoinArg returns a list of CrossJoinArg arrays. The first // array is the CrossJoin dimensions. The second array, if any, // contains additional constraints on the dimensions. If either the // list or the first array is null, then native cross join is not // feasible. if (allArgs == null || allArgs.isEmpty() || allArgs.get(0) == null) { return null; } CrossJoinArg[] cjArgs = allArgs.get(0); if (isPreferInterpreter(cjArgs, false)) { return null; } // extract "order by" expression SchemaReader schemaReader = evaluator.getSchemaReader(); DataSource ds = schemaReader.getDataSource(); // generate the WHERE condition // Need to generate where condition here to determine whether // or not the filter condition can be created. The filter // condition could change to use an aggregate table later in evaluation SqlQuery sqlQuery = SqlQuery.newQuery(ds, "NativeFilter"); RolapNativeSql sql = new RolapNativeSql(sqlQuery, null, evaluator, cjArgs[0].getLevel()); final Exp filterExpr = args[1]; String filterExprStr = sql.generateFilterCondition(filterExpr); if (filterExprStr == null) { return null; } // Check to see if evaluator contains a calculated member that can't be // expanded. This is necessary due to the SqlConstraintsUtils. // addContextConstraint() // method which gets called when generating the native SQL. if (SqlConstraintUtils.containsCalculatedMember(evaluator.getNonAllMembers(), true)) { return null; } LOGGER.debug("using native filter"); final int savepoint = evaluator.savepoint(); try { overrideContext(evaluator, cjArgs, sql.getStoredMeasure()); // Now construct the TupleConstraint that contains both the CJ // dimensions and the additional filter on them. CrossJoinArg[] combinedArgs = cjArgs; if (allArgs.size() == 2) { CrossJoinArg[] predicateArgs = allArgs.get(1); if (predicateArgs != null) { // Combined the CJ and the additional predicate args. combinedArgs = Util.appendArrays(cjArgs, predicateArgs); } } TupleConstraint constraint = new FilterConstraint(combinedArgs, evaluator, filterExpr); return new SetEvaluator(cjArgs, schemaReader, constraint); } finally { evaluator.restore(savepoint); } }