001 /* 002 // This software is subject to the terms of the Common Public License 003 // Agreement, available at the following URL: 004 // http://www.opensource.org/licenses/cpl.html. 005 // Copyright (C) 2004-2005 TONBELLER AG 006 // All Rights Reserved. 007 // You must accept the terms of that agreement to use this software. 008 */ 009 package mondrian.rolap; 010 011 import java.util.List; 012 013 import mondrian.olap.Id; 014 import mondrian.olap.Evaluator; 015 import mondrian.olap.Level; 016 import mondrian.olap.MondrianProperties; 017 import mondrian.rolap.sql.MemberChildrenConstraint; 018 import mondrian.rolap.sql.TupleConstraint; 019 020 /** 021 * Creates the right constraint for common tasks. 022 * 023 * @author av 024 * @since Nov 21, 2005 025 */ 026 public class SqlConstraintFactory { 027 028 boolean enabled = MondrianProperties.instance().EnableNativeNonEmpty.get(); 029 030 private static final SqlConstraintFactory instance = new SqlConstraintFactory(); 031 032 /** singleton */ 033 private SqlConstraintFactory() { 034 } 035 036 public static SqlConstraintFactory instance() { 037 return instance; 038 } 039 040 public MemberChildrenConstraint getMemberChildrenConstraint(Evaluator context) { 041 if (!enabled || !SqlContextConstraint.isValidContext(context)) 042 return DefaultMemberChildrenConstraint.instance(); 043 return new SqlContextConstraint((RolapEvaluator) context, false); 044 } 045 046 public TupleConstraint getLevelMembersConstraint(Evaluator context) { 047 boolean[] satisfied = {false}; 048 return getLevelMembersConstraint(context, null, satisfied); 049 } 050 051 /** 052 * Returns a constraint that restricts the members of a level to those that 053 * are non-empty in the given context. If the constraint cannot be 054 * implemented (say if native constraints are disabled) returns null. 055 * 056 * @param context Context within which members must be non-empty 057 * @param levels levels being referenced in the current context 058 * @param satisfied Set to false if constraint does not satisfy non-empty 059 * context and caller still has to do it 060 * @return Constraint 061 */ 062 public TupleConstraint getLevelMembersConstraint( 063 Evaluator context, 064 Level [] levels, 065 boolean[] satisfied) 066 { 067 if (context == null) { 068 satisfied[0] = true; 069 return DefaultTupleConstraint.instance(); 070 } 071 if (!enabled) { 072 // Cannot implement constraint in SQL; caller must still implement 073 // it 074 satisfied[0] = false; 075 return DefaultTupleConstraint.instance(); 076 } 077 satisfied[0] = true; 078 if (!SqlContextConstraint.isValidContext(context, false, levels)) { 079 return DefaultTupleConstraint.instance(); 080 } 081 return new SqlContextConstraint((RolapEvaluator) context, false); 082 } 083 084 public MemberChildrenConstraint getChildByNameConstraint( 085 RolapMember parent, 086 Id.Segment childName) 087 { 088 // Ragged hierarchies span multiple levels, so SQL WHERE does not work 089 // there 090 if (!enabled || parent.getHierarchy().isRagged()) { 091 return DefaultMemberChildrenConstraint.instance(); 092 } 093 return new ChildByNameConstraint(childName); 094 } 095 096 /** 097 * Returns a constraint that allows to read all children of multiple parents 098 * at once using a LevelMember query style. This does not work 099 * for parent/child hierarchies. 100 * 101 * @param parentMembers List of parents (all must belong to same level) 102 * @param mcc The constraint that would return the children for 103 * each single parent 104 * @return constraint 105 */ 106 public TupleConstraint getDescendantsConstraint( 107 List<RolapMember> parentMembers, 108 MemberChildrenConstraint mcc) 109 { 110 return new DescendantsConstraint(parentMembers, mcc); 111 } 112 } 113 114 // End SqlConstraintFactory.java