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