]> review.fuel-infra Code Review - packages/trusty/mysql-wsrep-5.6.git/blob
688eafbb737f9bc86fcf830e404a1234ff976100
[packages/trusty/mysql-wsrep-5.6.git] /
1 /*
2    Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
16 */
17
18 package com.mysql.clusterj.core.query;
19
20 import java.util.List;
21
22 import com.mysql.clusterj.ClusterJException;
23 import com.mysql.clusterj.ClusterJUserException;
24 import com.mysql.clusterj.core.spi.QueryExecutionContext;
25 import com.mysql.clusterj.core.store.IndexScanOperation;
26 import com.mysql.clusterj.core.store.ScanFilter;
27 import com.mysql.clusterj.core.store.ScanOperation;
28 import com.mysql.clusterj.core.store.IndexScanOperation.BoundType;
29 import com.mysql.clusterj.core.store.ScanFilter.BinaryCondition;
30 import com.mysql.clusterj.core.store.ScanFilter.Group;
31
32 public class InPredicateImpl extends PredicateImpl {
33
34     /** The property */
35     protected PropertyImpl property;
36
37     /** The parameter containing the values */
38     protected ParameterImpl parameter;
39
40     public InPredicateImpl(QueryDomainTypeImpl<?> dobj,
41             PropertyImpl property, ParameterImpl parameter) {
42         super(dobj);
43         this.property = property;
44         this.parameter = parameter;
45         parameter.setProperty(property);
46         // mark this property as having complex values
47         property.setComplexParameter();
48     }
49
50     @Override
51     public void markParameters() {
52         parameter.mark();
53     }
54
55     @Override
56     public void unmarkParameters() {
57         parameter.unmark();
58     }
59
60     @Override
61     void markBoundsForCandidateIndices(QueryExecutionContext context,
62             CandidateIndexImpl[] candidateIndices) {
63         if (parameter.getParameterValue(context) == null) {
64             // null parameters cannot be used with index scans
65             return;
66         }
67         property.markInBound(candidateIndices, this);
68     }
69
70     /** Set bound for the multi-valued parameter identified by the index.
71      * 
72      * @param context the query execution context
73      * @param op the operation to set bounds on
74      * @param index the index into the parameter list
75      * @param lastColumn if true, can set strict bound
76      */
77     public void operationSetBound(
78             QueryExecutionContext context, IndexScanOperation op, int index, boolean lastColumn) {
79         if (lastColumn) {
80             // last column can be strict
81             operationSetBound(context, op, index, BoundType.BoundEQ);
82         } else {
83             // not last column cannot be strict
84             operationSetBound(context, op, index, BoundType.BoundLE);
85             operationSetBound(context, op, index, BoundType.BoundGE);
86         }
87     }
88
89     public void operationSetUpperBound(QueryExecutionContext context, IndexScanOperation op, int index) {
90         operationSetBound(context, op, index, BoundType.BoundGE);
91     }
92
93     public void operationSetLowerBound(QueryExecutionContext context, IndexScanOperation op, int index) {
94         operationSetBound(context, op, index, BoundType.BoundLE);
95     }
96
97     private void operationSetBound(
98             QueryExecutionContext context, IndexScanOperation op, int index, BoundType boundType) {
99     Object parameterValue = parameter.getParameterValue(context);
100         if (parameterValue == null) {
101             throw new ClusterJUserException(
102                     local.message("ERR_Parameter_Cannot_Be_Null", "operator in", parameter.parameterName));
103         } else if (parameterValue instanceof List<?>) {
104             List<?> parameterList = (List<?>)parameterValue;
105             Object value = parameterList.get(index);
106             property.operationSetBounds(value, boundType, op);
107             if (logger.isDetailEnabled()) logger.detail("InPredicateImpl.operationSetBound for " + property.fmd.getName() + " List index: " + index + " value: " + value + " boundType: " + boundType);
108         } else if (parameterValue.getClass().isArray()) {
109             Object[] parameterArray = (Object[])parameterValue;
110             Object value = parameterArray[index];
111             property.operationSetBounds(value, boundType, op);
112             if (logger.isDetailEnabled()) logger.detail("InPredicateImpl.operationSetBound for " + property.fmd.getName() + "  array index: " + index + " value: " + value + " boundType: " + boundType);
113         } else {
114             throw new ClusterJUserException(
115                     local.message("ERR_Parameter_Wrong_Type", parameter.parameterName,
116                             parameterValue.getClass().getName(), "List<?> or Object[]"));
117         }
118     }
119
120     /** Set bounds for the multi-valued parameter identified by the index.
121      * There is only one column in the bound, so set each bound and then end the bound.
122      * 
123      * @param context the query execution context
124      * @param op the operation to set bounds on
125      * @param index the index into the parameter list
126      */
127     public void operationSetAllBounds(QueryExecutionContext context,
128             IndexScanOperation op) {
129         Object parameterValue = parameter.getParameterValue(context);
130         int index = 0;
131         if (parameterValue == null) {
132             throw new ClusterJUserException(
133                     local.message("ERR_Parameter_Cannot_Be_Null", "operator in", parameter.parameterName));
134         } else if (parameterValue instanceof List<?>) {
135             List<?> parameterList = (List<?>)parameterValue;
136             for (Object value: parameterList) {
137                 property.operationSetBounds(value, BoundType.BoundEQ, op);
138                 if (logger.isDetailEnabled()) logger.detail("InPredicateImpl.operationSetAllBounds for List index: " + index + " value: " + value);
139                 op.endBound(index++);
140             }
141         } else if (parameterValue.getClass().isArray()) {
142             Object[] parameterArray = (Object[])parameterValue;
143             for (Object value: parameterArray) {
144                 property.operationSetBounds(value, BoundType.BoundEQ, op);
145                 if (logger.isDetailEnabled()) logger.detail("InPredicateImpl.operationSetAllBounds for array index: " + index + " value: " + value);
146                 op.endBound(index++);
147             }
148         } else {
149             throw new ClusterJUserException(
150                     local.message("ERR_Parameter_Wrong_Type", parameter.parameterName,
151                             parameterValue.getClass().getName(), "List<?> or Object[]"));
152         }
153     }
154
155     /** Create a filter for the operation. Call the property to set the filter
156      * from the parameter values.
157      * @param context the query execution context with the parameter values
158      * @param op the operation
159      */
160     public void filterCmpValue(QueryExecutionContext context,
161             ScanOperation op) {
162         try {
163             ScanFilter filter = op.getScanFilter(context);
164             filterCmpValue(context, op, filter);
165         } catch (ClusterJException ex) {
166             throw ex;
167         } catch (Exception ex) {
168             throw new ClusterJException(
169                     local.message("ERR_Get_NdbFilter"), ex);
170         }
171     }
172
173     /** Use an existing filter for the operation. Call the property to set the filter
174      * from the parameter values.
175      * @param context the query execution context with the parameter values
176      * @param op the operation
177      * @param filter the existing filter
178      */
179     public void filterCmpValue(QueryExecutionContext context, ScanOperation op, ScanFilter filter) {
180         try {
181             filter.begin(Group.GROUP_OR);
182             Object parameterValue = parameter.getParameterValue(context);
183             if (parameterValue == null) {
184                 throw new ClusterJUserException(
185                         local.message("ERR_Parameter_Cannot_Be_Null", "operator in", parameter.parameterName));
186             } else if (parameterValue instanceof Iterable<?>) {
187                 Iterable<?> iterable = (Iterable<?>)parameterValue;
188                 for (Object value: iterable) {
189                     property.filterCmpValue(value, BinaryCondition.COND_EQ, filter);
190                 }
191             } else if (parameterValue.getClass().isArray()) {
192                 Object[] parameterArray = (Object[])parameterValue;
193                 for (Object parameter: parameterArray) {
194                     property.filterCmpValue(parameter, BinaryCondition.COND_EQ, filter);
195                 }
196             } else {
197                 throw new ClusterJUserException(
198                         local.message("ERR_Parameter_Wrong_Type", parameter.parameterName,
199                                 parameterValue.getClass().getName(), "Iterable<?> or Object[]"));
200             }
201             filter.end();
202         } catch (ClusterJException ex) {
203             throw ex;
204         } catch (Exception ex) {
205             throw new ClusterJException(
206                     local.message("ERR_Get_NdbFilter"), ex);
207         }
208     }
209
210     public int getParameterSize(QueryExecutionContext context) {
211         int result = 1;
212         Object parameterValue = parameter.getParameterValue(context);
213         if (parameterValue instanceof List<?>) {
214             result = ((List<?>)parameterValue).size();
215         }
216         Class<?> cls = parameterValue.getClass();
217         if (cls.isArray()) {
218             if (!Object.class.isAssignableFrom(cls.getComponentType())) {
219                 throw new ClusterJUserException(local.message("ERR_Wrong_Parameter_Type_For_In",
220                         property.fmd.getName()));
221             }
222             Object[] parameterArray = (Object[])parameterValue;
223             result = parameterArray.length;
224         }
225         if (result > 4096) {
226             throw new ClusterJUserException(local.message("ERR_Parameter_Too_Big_For_In",
227                         property.fmd.getName(), result));
228         }
229         // single value parameter
230         return result;
231     }
232
233 }