]> review.fuel-infra Code Review - packages/trusty/mysql-wsrep-5.6.git/blob
d07600b589d97ec07a2c39cc1d1f7f69ccd60b45
[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.metadata;
19
20 import java.util.ArrayList;
21 import java.util.BitSet;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Set;
27
28 import com.mysql.clusterj.ClusterJException;
29 import com.mysql.clusterj.ClusterJFatalInternalException;
30 import com.mysql.clusterj.ClusterJUserException;
31 import com.mysql.clusterj.core.CacheManager;
32 import com.mysql.clusterj.core.query.CandidateIndexImpl;
33 import com.mysql.clusterj.core.spi.DomainFieldHandler;
34 import com.mysql.clusterj.core.spi.DomainTypeHandler;
35 import com.mysql.clusterj.core.spi.ValueHandler;
36 import com.mysql.clusterj.core.store.Column;
37 import com.mysql.clusterj.core.store.Dictionary;
38 import com.mysql.clusterj.core.store.IndexOperation;
39 import com.mysql.clusterj.core.store.Operation;
40 import com.mysql.clusterj.core.store.PartitionKey;
41 import com.mysql.clusterj.core.store.ResultData;
42 import com.mysql.clusterj.core.store.Table;
43 import com.mysql.clusterj.core.util.I18NHelper;
44 import com.mysql.clusterj.core.util.Logger;
45 import com.mysql.clusterj.core.util.LoggerFactoryService;
46
47 /** Abstract class implementing DomainTypeHandler. This class implements common
48  * behavior to manage persistent representations of tables, including field
49  * handlers for persistent field values. Subclasses will implement behavior
50  * specific to the actual representations of persistence.
51  */
52 public abstract class AbstractDomainTypeHandlerImpl<T> implements DomainTypeHandler<T> {
53
54     /** My message translator */
55     protected static final I18NHelper local = I18NHelper.getInstance(AbstractDomainTypeHandlerImpl.class);
56
57     /** My logger */
58     protected static final Logger logger = LoggerFactoryService.getFactory().getInstance(AbstractDomainTypeHandlerImpl.class);
59
60     /** The name of the class. */
61     protected String name;
62
63     /** The table for the class. */
64     protected String tableName;
65
66     /** The NDB table for the class. */
67     protected Table table;
68
69     /** The number of id fields for the class. */
70     protected int numberOfIdFields;
71
72     /** The field numbers of the id fields. */
73     protected int[] idFieldNumbers;
74
75     /** The id field(s) for the class, mapped to primary key columns */
76     protected DomainFieldHandler[] idFieldHandlers;
77
78     /** The PrimaryKey column names. */
79     protected String[] primaryKeyColumnNames;
80
81     /** The number of partition key columns */
82     protected int numberOfPartitionKeyColumns = 0;
83
84     /** The partition key fields */
85     protected DomainFieldHandler[] partitionKeyFieldHandlers;
86
87     /** The names of the partition key columns */
88     protected String[] partitionKeyColumnNames;
89
90     /** The number of fields. Dynamically created as fields are added. */
91     protected int numberOfFields = 0;
92
93     /** Persistent fields. */
94     protected List<DomainFieldHandler> persistentFieldHandlers = new ArrayList<DomainFieldHandler>();
95
96     /** Non PK fields. */
97     protected List<DomainFieldHandler> nonPKFieldHandlers = new ArrayList<DomainFieldHandler>();
98
99     /** Primitive fields. */
100     protected List<DomainFieldHandler> primitiveFieldHandlers = new ArrayList<DomainFieldHandler>();
101
102     /** Map of field names to field numbers. */
103     protected Map<String, Integer> fieldNameToNumber = new HashMap<String, Integer>();
104
105     /** Field names */
106     protected String[] fieldNames;
107
108     /** All index handlers defined for the mapped class. The position in this
109      * array is significant. Each DomainFieldHandlerImpl contains the index into
110      * this array and the index into the fields array within the
111      * IndexHandlerImpl.
112      */
113     protected List<IndexHandlerImpl> indexHandlerImpls = new ArrayList<IndexHandlerImpl>();
114
115     /** Set of index names to check for duplicates. */
116     protected Set<String> indexNames = new HashSet<String>();
117
118     /** Register a primary key column field. This is used to associate
119      * primary key and partition key column names with field handlers.
120      * This method is called by the DomainFieldHandlerImpl constructor
121      * after the mapped column name is known. It is only called by fields
122      * that are mapped to primary key columns.
123      * @param fmd the field handler instance calling us
124      * @param columnName the name of the column
125      */
126     public void registerPrimaryKeyColumn(DomainFieldHandler fmd, String columnName) {
127         // find the primary key column that matches the primary key column
128         for (int i = 0; i < primaryKeyColumnNames.length; ++i) {
129             if (primaryKeyColumnNames[i].equals(columnName)) {
130                 idFieldHandlers[i] = fmd;
131                 idFieldNumbers[i] = fmd.getFieldNumber();
132                 if (logger.isDetailEnabled()) logger.detail("registerPrimaryKeyColumn found primary key " + columnName);
133             }
134         }
135         // find the partition key column that matches the primary key column
136         for (int j = 0; j < partitionKeyColumnNames.length; ++j) {
137             if (partitionKeyColumnNames[j].equals(columnName)) {
138                 partitionKeyFieldHandlers[j] = fmd;
139                 if (logger.isDetailEnabled()) logger.detail("registerPrimaryKeyColumn found partition key " + columnName);
140             }
141         }
142         return;
143     }
144
145     /** Create and register an index from a field and return a special int[][] that
146      * contains all indexHandlerImpls in which the
147      * field participates. The int[][] is used by the query optimizer to determine
148      * which if any index can be used. This method is called by the
149      * DomainFieldHandlerImpl constructor after the mapped column name is known.
150      * @see AbstractDomainFieldHandlerImpl#indices
151      * @param fmd the FieldHandler
152      * @param columnName the column name mapped to the field
153      * @return the array of array identifying the indexes into the IndexHandler
154      * list and columns in the IndexHandler corresponding to the field
155      */
156     public int[][] registerIndices(AbstractDomainFieldHandlerImpl fmd, String columnName) {
157         // Find all the indexes that this field belongs to, by iterating
158         // the list of indexes and comparing column names.
159         List<int[]> result =new ArrayList<int[]>();
160         for (int i = 0; i < indexHandlerImpls.size(); ++i) {
161             IndexHandlerImpl indexHandler = indexHandlerImpls.get(i);
162             String[] columns = indexHandler.getColumnNames();
163             for (int j = 0; j < columns.length; ++j) {
164                 if (fmd.getColumnName().equals(columns[j])) {
165                     if (logger.isDetailEnabled()) logger.detail("Found field " + fmd.getName()
166                             + " column " + fmd.getColumnName() + " matching " + indexHandler.getIndexName());
167                     indexHandler.setDomainFieldHandlerFor(j, fmd);
168                     result.add(new int[]{i,j});
169                 }
170             }
171         }
172     
173         if (logger.isDebugEnabled()) logger.debug("Found " + result.size() + " indexes for " + columnName);
174         return result.toArray(new int[result.size()][]);
175     }
176
177     /** Return the list of index names corresponding to the array of indexes.
178      * This method is called by the DomainFieldHandlerImpl constructor after the
179      * registerIndices method is called.
180      * @param indexArray the result of registerIndices
181      * @return all index names for the corresponding indexes
182      */
183     public Set<String> getIndexNames(int[][] indexArray) {
184         Set<String> result = new HashSet<String>();
185         for (int[] index: indexArray) {
186             result.add(indexHandlerImpls.get(index[0]).getIndexName());
187         }
188         return result;
189     }
190
191     /** Extract the column names from store Columns.
192      * 
193      * @param indexName the index name (for error messages)
194      * @param columns the store Column instances
195      * @return an array of column names
196      */
197     protected String[] getColumnNames(String indexName, Column[] columns) {
198         Set<String> columnNames = new HashSet<String>();
199         for (Column column : columns) {
200             String columnName = column.getName();
201             if (columnNames.contains(columnName)) {
202                 // error: the column name is duplicated
203                 throw new ClusterJUserException(
204                         local.message("ERR_Duplicate_Column",
205                         name, indexName, columnName));
206             }
207             columnNames.add(columnName);
208         }
209         return columnNames.toArray(new String[columnNames.size()]);
210     }
211
212     /** Create a list of candidate indexes to evaluate query terms and
213      * decide what type of operation to use. The result must correspond
214      * one to one with the indexHandlerImpls.
215      * @return a new array of CandidateIndexImpl
216      */
217     public CandidateIndexImpl[] createCandidateIndexes() {
218         CandidateIndexImpl[] result = new CandidateIndexImpl[indexHandlerImpls.size()];
219         int i = 0;
220         for (IndexHandlerImpl indexHandler: indexHandlerImpls) {
221             result[i++] = indexHandler.toCandidateIndexImpl();
222         }
223         return result;
224     }
225
226     public String getTableName() {
227         return tableName;
228     }
229
230     public int getNumberOfFields() {
231         return numberOfFields;
232     }
233
234     public DomainFieldHandler[] getIdFieldHandlers() {
235         return idFieldHandlers;
236     }
237
238     public DomainFieldHandler getFieldHandler(String fieldName) {
239         for (DomainFieldHandler fmd: persistentFieldHandlers) {
240             if (fmd.getName().equals(fieldName)) {
241                 return fmd;
242             }
243         }
244         throw new ClusterJUserException(
245                 local.message("ERR_Not_A_Member", fieldName, name));
246     }
247
248     public int getFieldNumber(String fieldName) {
249         Integer fieldNumber = fieldNameToNumber.get(fieldName);
250         if (fieldNumber == null) {
251             throw new ClusterJFatalInternalException(
252                     local.message("ERR_No_Field_Number", fieldName, name));
253         }
254         return fieldNumber.intValue();
255     }
256
257     public void operationSetNonPKValues(ValueHandler handler, Operation op) {
258         for (DomainFieldHandler fmd: nonPKFieldHandlers) {
259             if (handler.isModified(fmd.getFieldNumber())) {
260                 fmd.operationSetValue(handler, op);
261             }
262         }
263     }
264
265     public void operationSetValues(ValueHandler handler, Operation op) {
266         for (DomainFieldHandler fmd: persistentFieldHandlers) {
267             if (logger.isDetailEnabled()) logger.detail("operationSetValues field: " + fmd.getName());
268             fmd.operationSetValue(handler, op);
269         }
270     }
271
272     public void operationSetModifiedNonPKValues(ValueHandler handler, Operation op) {
273         for (DomainFieldHandler fmd: nonPKFieldHandlers) {
274             fmd.operationSetModifiedValue(handler, op);
275         }
276             }
277
278     public void operationSetModifiedValues(ValueHandler handler, Operation op) {
279         for (DomainFieldHandler fmd: persistentFieldHandlers) {
280             fmd.operationSetModifiedValue(handler, op);
281         }
282     }
283
284     public void operationSetKeys(ValueHandler handler, Operation op) {
285         for (DomainFieldHandler fmd: idFieldHandlers) {
286             fmd.operationSetValue(handler, op);
287         }        
288     }
289
290     public void operationGetValues(Operation op) {
291         for (DomainFieldHandler fmd: persistentFieldHandlers) {
292             fmd.operationGetValue(op);
293         }
294     }
295
296     public void operationGetValues(Operation op, BitSet fields) {
297         if (fields == null) {
298             operationGetValues(op);
299         } else {
300             int i = 0;
301             for (DomainFieldHandler fmd: persistentFieldHandlers) {
302                 if (fields.get(i++)) {
303                     fmd.operationGetValue(op);
304                 }
305             }
306         }
307     }
308
309     public void operationGetValuesExcept(IndexOperation op, String index) {
310         for (DomainFieldHandler fmd: persistentFieldHandlers) {
311             if (!fmd.includedInIndex(index)) {
312                 if (logger.isDetailEnabled()) logger.detail("operationGetValuesExcept index: " + index);
313                 fmd.operationGetValue(op);
314             }
315         }
316     }
317
318     public void objectSetValues(ResultData rs, ValueHandler handler) {
319         for (DomainFieldHandler fmd: persistentFieldHandlers) {
320             fmd.objectSetValue(rs, handler);
321         }
322     }
323
324     public void objectSetValuesExcept(ResultData rs, ValueHandler handler, String indexName) {
325         for (DomainFieldHandler fmd: persistentFieldHandlers) {
326             fmd.objectSetValueExceptIndex(rs, handler, indexName);
327         }
328     }
329
330     protected Table getTable(Dictionary dictionary) {
331         Table result;
332         try {
333             result = dictionary.getTable(tableName);
334         } catch (Exception ex) {
335             throw new ClusterJException(
336                     local.message("ERR_Get_NdbTable", name, tableName), ex);
337         }
338         return result;
339     }
340
341     public int[] getKeyFieldNumbers() {
342         return idFieldNumbers;
343     }
344
345     public Table getStoreTable() {
346         return table;
347     }
348
349     /** Create a partition key for a find by primary key. 
350      * @param handler the handler that contains the values of the primary key
351      */
352     public PartitionKey createPartitionKey(ValueHandler handler) {
353         // create the partition key based on the mapped table
354         PartitionKey result = table.createPartitionKey();
355         // add partition key part value for each partition key field
356         for (DomainFieldHandler fmd: partitionKeyFieldHandlers) {
357             if (logger.isDetailEnabled()) logger.detail(
358                         "Field number " + fmd.getFieldNumber()
359                         + " column name " + fmd.getName() + " field name " + fmd.getName());
360             fmd.partitionKeySetPart(result, handler);
361         }
362         return result;
363     }
364
365     public String getName() {
366         return name;
367     }
368
369     public Set<String> getColumnNames(BitSet fields) {
370         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
371     }
372
373     public Set<com.mysql.clusterj.core.store.Column> getStoreColumns(BitSet fields) {
374         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
375     }
376
377     public ValueHandler createKeyValueHandler(Object keys) {
378         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
379     }
380
381     public T getInstance(ValueHandler handler) {
382         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
383     }
384
385     public Class<?> getOidClass() {
386         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
387     }
388
389     public Class<T> getProxyClass() {
390         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
391     }
392
393     public ValueHandler getValueHandler(Object instance) {
394         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
395     }
396
397     public boolean isSupportedType() {
398         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
399     }
400
401     public T newInstance() {
402         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
403     }
404
405     public void objectMarkModified(ValueHandler handler, String fieldName) {
406         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
407     }
408
409     public void objectResetModified(ValueHandler handler) {
410         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
411     }
412
413     public void objectSetCacheManager(CacheManager cm, Object instance) {
414         throw new ClusterJFatalInternalException(local.message("ERR_Implementation_Should_Not_Occur"));
415     }
416
417     protected String removeUniqueSuffix(String indexName) {
418         int beginIndex = indexName.lastIndexOf("$unique");
419         if (beginIndex < 0) {
420             // there's no $unique suffix
421             return indexName;
422         }
423         String result = indexName.substring(0, beginIndex);
424         return result;
425     }
426
427     public String[] getFieldNames() {
428         return fieldNames;
429     }
430
431 }