001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/RolapNativeFilter.java#21 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2005-2008 Julian Hyde 007 // Copyright (C) 2004-2005 TONBELLER AG 008 // All Rights Reserved. 009 // You must accept the terms of that agreement to use this software. 010 */ 011 package mondrian.rolap; 012 013 import java.util.ArrayList; 014 import java.util.List; 015 016 import javax.sql.DataSource; 017 018 import mondrian.olap.*; 019 import mondrian.rolap.sql.SqlQuery; 020 import mondrian.rolap.sql.TupleConstraint; 021 022 /** 023 * Computes a Filter(set, condition) in SQL. 024 * 025 * @author av 026 * @since Nov 21, 2005 027 * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapNativeFilter.java#21 $ 028 */ 029 public class RolapNativeFilter extends RolapNativeSet { 030 031 public RolapNativeFilter() { 032 super.setEnabled(MondrianProperties.instance().EnableNativeFilter.get()); 033 } 034 035 static class FilterConstraint extends SetConstraint { 036 String filterExpr; 037 038 public FilterConstraint(CrossJoinArg[] args, RolapEvaluator evaluator, String filterByExpr) { 039 super(args, evaluator, true); 040 this.filterExpr = filterByExpr; 041 } 042 043 /** 044 * we alwas need to join the fact table because we want to evalutate 045 * the filter expression against a fact. 046 */ 047 protected boolean isJoinRequired() { 048 return true; 049 } 050 051 public void addConstraint(SqlQuery sqlQuery, RolapCube baseCube) { 052 sqlQuery.addHaving(filterExpr); 053 super.addConstraint(sqlQuery, baseCube); 054 } 055 056 public Object getCacheKey() { 057 List<Object> key = new ArrayList<Object>(); 058 key.add(super.getCacheKey()); 059 key.add(filterExpr); 060 return key; 061 } 062 } 063 064 protected boolean restrictMemberTypes() { 065 return true; 066 } 067 068 NativeEvaluator createEvaluator(RolapEvaluator evaluator, FunDef fun, Exp[] args) { 069 if (!isEnabled()) { 070 return null; 071 } 072 if (!FilterConstraint.isValidContext(evaluator)) { 073 return null; 074 } 075 // is this "Filter(<set>, <numeric expr>)" 076 String funName = fun.getName(); 077 if (!"Filter".equalsIgnoreCase(funName)) { 078 return null; 079 } 080 081 if (args.length != 2) { 082 return null; 083 } 084 085 // extract the set expression 086 CrossJoinArg[] cargs = checkCrossJoinArg(evaluator, args[0]); 087 if (cargs == null) { 088 return null; 089 } 090 if (isPreferInterpreter(cargs, false)) { 091 return null; 092 } 093 094 // extract "order by" expression 095 SchemaReader schemaReader = evaluator.getSchemaReader(); 096 DataSource ds = schemaReader.getDataSource(); 097 098 // generate the WHERE condition 099 SqlQuery sqlQuery = SqlQuery.newQuery(ds, "NativeFilter"); 100 RolapNativeSql sql = new RolapNativeSql(sqlQuery); 101 String filterExpr = sql.generateFilterCondition(args[1]); 102 if (filterExpr == null) { 103 return null; 104 } 105 106 // check to see if evaluator contains a calculated member. 107 // this is necessary due to the SqlConstraintsUtils.addContextConstraint() 108 // method which gets called when generating the native SQL 109 if (SqlConstraintUtils.containsCalculatedMember(evaluator.getMembers())) { 110 return null; 111 } 112 113 LOGGER.debug("using native filter"); 114 115 evaluator = overrideContext(evaluator, cargs, sql.getStoredMeasure()); 116 117 TupleConstraint constraint = new FilterConstraint(cargs, evaluator, filterExpr); 118 return new SetEvaluator(cargs, schemaReader, constraint); 119 } 120 121 } 122 123 // End RolapNativeFilter.java