1 /*
2    Copyright (c) 2010, 2021, Oracle and/or its affiliates.
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, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 package com.mysql.clusterj.core.query;
26 
27 import com.mysql.clusterj.ClusterJException;
28 import com.mysql.clusterj.ClusterJFatalInternalException;
29 import com.mysql.clusterj.ClusterJUserException;
30 import com.mysql.clusterj.Query;
31 
32 import com.mysql.clusterj.Query.Ordering;
33 import com.mysql.clusterj.core.query.PredicateImpl.ScanType;
34 import com.mysql.clusterj.core.spi.DomainFieldHandler;
35 import com.mysql.clusterj.core.spi.DomainTypeHandler;
36 import com.mysql.clusterj.core.spi.QueryExecutionContext;
37 import com.mysql.clusterj.core.spi.SessionSPI;
38 import com.mysql.clusterj.core.spi.ValueHandlerBatching;
39 
40 import com.mysql.clusterj.core.store.Blob;
41 import com.mysql.clusterj.core.store.Column;
42 import com.mysql.clusterj.core.store.Index;
43 import com.mysql.clusterj.core.store.IndexOperation;
44 import com.mysql.clusterj.core.store.IndexScanOperation;
45 import com.mysql.clusterj.core.store.Operation;
46 import com.mysql.clusterj.core.store.ResultData;
47 import com.mysql.clusterj.core.store.ScanOperation;
48 
49 import com.mysql.clusterj.core.util.I18NHelper;
50 import com.mysql.clusterj.core.util.Logger;
51 import com.mysql.clusterj.core.util.LoggerFactoryService;
52 
53 import com.mysql.clusterj.query.Predicate;
54 import com.mysql.clusterj.query.PredicateOperand;
55 import com.mysql.clusterj.query.QueryDefinition;
56 import com.mysql.clusterj.query.QueryDomainType;
57 
58 import java.math.BigDecimal;
59 import java.math.BigInteger;
60 import java.util.ArrayList;
61 import java.util.HashMap;
62 import java.util.List;
63 import java.util.Map;
64 
65 public class QueryDomainTypeImpl<T> implements QueryDomainType<T> {
66 
67     /** My message translator */
68     static final I18NHelper local = I18NHelper.getInstance(QueryDomainTypeImpl.class);
69 
70     /** My logger */
71     static final Logger logger = LoggerFactoryService.getFactory().getInstance(QueryDomainTypeImpl.class);
72 
73     /** My class. */
74     protected Class<T> cls;
75 
76     /** My DomainTypeHandler. */
77     protected DomainTypeHandler<T> domainTypeHandler;
78 
79     /** My where clause. */
80     protected PredicateImpl where;
81 
82     /** My parameters. These encapsulate the parameter names not the values. */
83     protected Map<String, ParameterImpl> parameters =
84             new HashMap<String, ParameterImpl>();
85 
86     /** My properties. These encapsulate the property names not the values. */
87     protected Map<String, PropertyImpl> properties =
88             new HashMap<String, PropertyImpl>();
89 
90     /** My index for this query */
91     CandidateIndexImpl index = null;
92 
93     /** My ordering fields for this query */
94     String[] orderingFields = null;
95 
96     /** My ordering for this query */
97     Ordering ordering = null;
98 
QueryDomainTypeImpl(DomainTypeHandler<T> domainTypeHandler, Class<T> cls)99     public QueryDomainTypeImpl(DomainTypeHandler<T> domainTypeHandler, Class<T> cls) {
100         this.cls = cls;
101         this.domainTypeHandler = domainTypeHandler;
102     }
103 
QueryDomainTypeImpl(DomainTypeHandler<T> domainTypeHandler)104     public QueryDomainTypeImpl(DomainTypeHandler<T> domainTypeHandler) {
105         this.domainTypeHandler = domainTypeHandler;
106     }
107 
get(String propertyName)108     public PredicateOperand get(String propertyName) {
109         // if called multiple times for the same property,
110         // return the same PropertyImpl instance
111         PropertyImpl property = properties.get(propertyName);
112         if (property != null) {
113             return property;
114         } else {
115             DomainFieldHandler fmd = domainTypeHandler.getFieldHandler(propertyName);
116             property = new PropertyImpl(this, fmd);
117             properties.put(propertyName, property);
118             return property;
119         }
120     }
121 
122     /** Set the where clause. Mark parameters used by this query.
123      * @param predicate the predicate
124      * @return the query definition (this)
125      */
where(Predicate predicate)126     public QueryDefinition<T> where(Predicate predicate) {
127         if (predicate == null) {
128             throw new ClusterJUserException(
129                     local.message("ERR_Query_Where_Must_Not_Be_Null"));
130         }
131         if (!(predicate instanceof PredicateImpl)) {
132             throw new UnsupportedOperationException(
133                     local.message("ERR_NotImplemented"));
134         }
135         // if a previous where clause, unmark the parameters
136         if (where != null) {
137             where.unmarkParameters();
138             where = null;
139         }
140         this.where = (PredicateImpl)predicate;
141         where.markParameters();
142         // statically analyze the where clause, looking for:
143         // primary keys all specified with equal
144         // unique keys all specified with equal
145         // btree index keys partly specified with ranges
146         // none of the above
147         where.prepare();
148         return this;
149     }
150 
param(String parameterName)151     public PredicateOperand param(String parameterName) {
152         final ParameterImpl parameter = parameters.get(parameterName);
153         if (parameter != null) {
154             return parameter;
155         } else {
156             ParameterImpl result = new ParameterImpl(this, parameterName);
157             parameters.put(parameterName, result);
158             return result;
159         }
160     }
161 
162     /** Convenience method to negate a predicate.
163      * @param predicate the predicate to negate
164      * @return the inverted predicate
165      */
not(Predicate predicate)166     public Predicate not(Predicate predicate) {
167         return predicate.not();
168     }
169 
170     /** Query.getResultList delegates to this method.
171      * @param skip the number of rows to skip
172      * @param limit the limit of rows to return after skipping
173      * @param orderingFields
174      * @param ordering
175      *
176      * @return the results of executing the query
177      */
getResultList(QueryExecutionContext context, long skip, long limit, Ordering ordering, String[] orderingFields)178     public List<T> getResultList(QueryExecutionContext context, long skip, long limit,
179             Ordering ordering, String[] orderingFields) {
180         assertAllParametersBound(context);
181 
182         SessionSPI session = context.getSession();
183         session.startAutoTransaction();
184         // set up results and table information
185         List<T> resultList = new ArrayList<T>();
186         try {
187             // execute the query
188             ResultData resultData = getResultData(context, skip, limit, ordering, orderingFields);
189             // put the result data into the result list
190             while (resultData.next()) {
191                 T row = session.newInstance(resultData, domainTypeHandler);
192                 resultList.add(row);
193             }
194             session.endAutoTransaction();
195             return resultList;
196         } catch (ClusterJException ex) {
197             session.failAutoTransaction();
198             throw ex;
199         } catch (Exception ex) {
200             session.failAutoTransaction();
201             throw new ClusterJException(
202                     local.message("ERR_Exception_On_Query"), ex);
203         }
204     }
205 
206     /** Execute the query and return the result data. The type of operation
207      * (primary key lookup, unique key lookup, index scan, or table scan)
208      * depends on the where clause and the bound parameter values.
209      *
210      * @param context the query context, including the bound parameters
211      * @param skip the number of rows to skip
212      * @param limit the limit of rows to return after skipping
213      * @param orderingFields
214      * @param ordering
215      * @return the raw result data from the query
216      * @throws ClusterJUserException if not all parameters are bound
217      */
getResultData(QueryExecutionContext context, long skip, long limit, Ordering ordering, String[] orderingFields)218     public ResultData getResultData(QueryExecutionContext context, long skip, long limit,
219             Ordering ordering, String[] orderingFields) {
220         SessionSPI session = context.getSession();
221         this.ordering = ordering;
222         this.orderingFields = orderingFields;
223         // execute query based on what kind of scan is needed
224         // if no where clause, scan the entire table
225         index = getCandidateIndex(context);
226         ScanType scanType = index.getScanType();
227 
228         if (logger.isDebugEnabled()) logger.debug("using index " + index.getIndexName() + " with scanType " + scanType);
229         Map<String, Object> explain = newExplain(index, scanType);
230         context.setExplain(explain);
231         ResultData result = null;
232         Index storeIndex;
233         Operation op = null;
234 
235         try {
236             switch (scanType) {
237 
238                 case PRIMARY_KEY: {
239                     // if skipping any results or limit is zero, return no results
240                     if (skip > 0 || limit < 1) {
241                         return resultDataEmpty;
242                     }
243                     // perform a select operation
244                     op = session.getSelectOperation(domainTypeHandler.getStoreTable());
245                     op.beginDefinition();
246                     // set key values into the operation
247                     index.operationSetKeys(context, op);
248                     // set the expected columns into the operation
249                     domainTypeHandler.operationGetValues(op);
250                     op.endDefinition();
251                     // execute the select and get results
252                     result = op.resultData();
253                     break;
254                 }
255 
256                 case INDEX_SCAN: {
257                     storeIndex = index.getStoreIndex();
258                     // perform an index scan operation
259                     if (index.isMultiRange()) {
260                         op = session.getIndexScanOperationMultiRange(storeIndex, domainTypeHandler.getStoreTable());
261 
262                     } else {
263                         op = session.getIndexScanOperation(storeIndex, domainTypeHandler.getStoreTable());
264 
265                     }
266                     op.beginDefinition();
267                     // set ordering if not already set to allow skip and limit to work
268                     if (ordering == null && (skip != 0 || limit != Long.MAX_VALUE)) {
269                         ordering = Ordering.ASCENDING;
270                     }
271                     ((ScanOperation)op).setOrdering(ordering);
272                     // set the expected columns into the operation
273                     domainTypeHandler.operationGetValues(op);
274                     // set the bounds into the operation
275                     index.operationSetBounds(context, (IndexScanOperation)op);
276                     // set additional filter conditions
277                     if (where != null) {
278                         where.filterCmpValue(context, (IndexScanOperation)op);
279                     }
280                     op.endDefinition();
281                     // execute the scan and get results
282                     result = ((ScanOperation)op).resultData(true, skip, limit);
283                     break;
284                 }
285 
286                 case TABLE_SCAN: {
287                     if (ordering != null) {
288                         throw new ClusterJUserException(local.message("ERR_Cannot_Use_Ordering_With_Table_Scan"));
289                     }
290                     // perform a table scan operation
291                     op = session.getTableScanOperation(domainTypeHandler.getStoreTable());
292                     op.beginDefinition();
293                     // set the expected columns into the operation
294                     domainTypeHandler.operationGetValues(op);
295                     // set filter conditions into the operation
296                     if (where != null) {
297                         where.filterCmpValue(context, (ScanOperation)op);
298                     }
299                     op.endDefinition();
300                     // execute the scan and get results
301                     result = ((ScanOperation)op).resultData(true, skip, limit);
302                     break;
303                 }
304 
305                 case UNIQUE_KEY: {
306                     // if skipping any results or limit is zero, return no results
307                     if (skip > 0 || limit < 1) {
308                         return resultDataEmpty;
309                     }
310                     storeIndex = index.getStoreIndex();
311                     // perform a unique lookup operation
312                     op = session.getUniqueIndexOperation(storeIndex, domainTypeHandler.getStoreTable());
313                     op.beginDefinition();
314                     // set the keys of the indexName into the operation
315                     where.operationEqual(context, op);
316                     // set the expected columns into the operation
317                     //domainTypeHandler.operationGetValuesExcept(op, indexName);
318                     domainTypeHandler.operationGetValues(op);
319                     op.endDefinition();
320                     // execute the select and get results
321                     result = op.resultData();
322                     break;
323                 }
324 
325                 default:
326                     session.failAutoTransaction();
327                     throw new ClusterJFatalInternalException(
328                             local.message("ERR_Illegal_Scan_Type", scanType));
329             }
330         }
331         catch (ClusterJException ex) {
332             if (op != null) {
333                 op.freeResourcesAfterExecute();
334             }
335             session.failAutoTransaction();
336             throw ex;
337         } catch (Exception ex) {
338             if (op != null) {
339                 op.freeResourcesAfterExecute();
340             }
341             session.failAutoTransaction();
342             throw new ClusterJException(
343                     local.message("ERR_Exception_On_Query"), ex);
344         }
345         return result;
346     }
347 
348     /** Delete the instances that satisfy the query and return the number
349      * of instances deleted. The type of operation used to find the instances
350      * (primary key lookup, unique key lookup, index scan, or table scan)
351      * depends on the where clause and the bound parameter values.
352      *
353      * @param context the query context, including the bound parameters
354      * @return the number of instances deleted
355      * @throws ClusterJUserException if not all parameters are bound
356      */
deletePersistentAll(QueryExecutionContext context)357     public int deletePersistentAll(QueryExecutionContext context) {
358         SessionSPI session = context.getSession();
359         // calculate what kind of scan is needed
360         // if no where clause, scan the entire table
361         index = getCandidateIndex(context);
362         ScanType scanType = index.getScanType();
363         Map<String, Object> explain = newExplain(index, scanType);
364         context.setExplain(explain);
365         int result = 0;
366         int errorCode = 0;
367         Index storeIndex;
368         session.startAutoTransaction();
369         Operation op = null;
370         try {
371             switch (scanType) {
372 
373                 case PRIMARY_KEY: {
374                     // perform a delete by primary key operation
375                     if (logger.isDetailEnabled()) logger.detail("Using delete by primary key.");
376                     op = session.getDeleteOperation(domainTypeHandler.getStoreTable());
377                     op.beginDefinition();
378                     // set key values into the operation
379                     index.operationSetKeys(context, op);
380                     op.endDefinition();
381                     // execute the delete operation
382                     session.executeNoCommit(false, true);
383                     errorCode = op.errorCode();
384                     // a non-zero result means the row was not deleted
385                     result = (errorCode == 0?1:0);
386                     break;
387                 }
388 
389                 case UNIQUE_KEY: {
390                     storeIndex = index.getStoreIndex();
391                     if (logger.isDetailEnabled()) logger.detail(
392                             "Using delete by unique key  " + index.getIndexName());
393                     // perform a delete by unique key operation
394                     op = session.getUniqueIndexDeleteOperation(storeIndex,
395                             domainTypeHandler.getStoreTable());
396                     // set the keys of the indexName into the operation
397                     where.operationEqual(context, op);
398                     // execute the delete operation
399                     session.executeNoCommit(false, true);
400                     errorCode = op.errorCode();
401                     // a non-zero result means the row was not deleted
402                     result = (errorCode == 0?1:0);
403                     break;
404                 }
405 
406                 case INDEX_SCAN: {
407                     storeIndex = index.getStoreIndex();
408                     if (logger.isDetailEnabled()) logger.detail(
409                             "Using delete by index scan with index " + index.getIndexName());
410                     // perform an index scan operation
411                     op = session.getIndexScanDeleteOperation(storeIndex,
412                             domainTypeHandler.getStoreTable());
413                     // set the expected columns into the operation
414                     domainTypeHandler.operationGetValues(op);
415                     // set the bounds into the operation
416                     index.operationSetBounds(context, (IndexScanOperation)op);
417                     // set additional filter conditions
418                     where.filterCmpValue(context, (IndexScanOperation)op);
419                     // delete results of the scan; don't abort if no row found
420                     result = session.deletePersistentAll((IndexScanOperation)op, false);
421                     break;
422                 }
423 
424                 case TABLE_SCAN: {
425                     if (logger.isDetailEnabled()) logger.detail("Using delete by table scan");
426                     // perform a table scan operation
427                     op = session.getTableScanDeleteOperation(domainTypeHandler.getStoreTable());
428                     // set the expected columns into the operation
429                     domainTypeHandler.operationGetValues(op);
430                     // set the bounds into the operation
431                     if (where != null) {
432                         where.filterCmpValue(context, (ScanOperation)op);
433                     }
434                     // delete results of the scan; don't abort if no row found
435                     result = session.deletePersistentAll((ScanOperation)op, false);
436                     break;
437                 }
438 
439                 default:
440                     throw new ClusterJFatalInternalException(
441                             local.message("ERR_Illegal_Scan_Type", scanType));
442             }
443             session.endAutoTransaction();
444             return result;
445         } catch (ClusterJException e) {
446             if (op != null) {
447                 op.freeResourcesAfterExecute();
448             }
449             session.failAutoTransaction();
450             throw e;
451         } catch (Exception e) {
452             if (op != null) {
453                 op.freeResourcesAfterExecute();
454             }
455             session.failAutoTransaction();
456             throw new ClusterJException(local.message("ERR_Exception_On_Query"), e);
457         }
458     }
459 
460     /** Update the instances that satisfy the query and return the number
461      * of instances updated. The type of operation used to update the instances
462      * (primary key lookup, unique key lookup, index scan, or table scan)
463      * depends on the where clause and the bound parameter values.
464      * Currently only update by primary key or unique key are supported.
465      *
466      * @param context the query context, including the batch of parameters
467      * @return the number of instances updated for each set in the batch of parameters
468      * @throws ClusterJUserException if not all parameters are bound
469      */
updatePersistentAll(QueryExecutionContext context, ValueHandlerBatching valueHandler)470     public long[] updatePersistentAll(QueryExecutionContext context, ValueHandlerBatching valueHandler) {
471         SessionSPI session = context.getSession();
472         // calculate what kind of scan is needed
473         // if no where clause, scan the entire table
474         index = getCandidateIndex(context);
475         ScanType scanType = index.getScanType();
476         Map<String, Object> explain = newExplain(index, scanType);
477         context.setExplain(explain);
478         long[] result = null;
479         List<Operation> ops = new ArrayList<Operation>();
480 
481         try {
482             switch (scanType) {
483 
484                 case PRIMARY_KEY: {
485                     result = new long[valueHandler.getNumberOfStatements()];
486                     session.startAutoTransaction();
487                     // perform an update by primary key operation
488                     if (logger.isDetailEnabled()) logger.detail("Update by primary key.");
489                     // iterate the valueHandlerBatching and for each set of parameters, update one row
490                     while (valueHandler.next()) {
491                         Operation op = session.getUpdateOperation(domainTypeHandler.getStoreTable());
492                         // set key values into the operation
493                         index.operationSetKeys(context, op);
494                         // set modified field values into the operation
495                         domainTypeHandler.operationSetModifiedNonPKValues(valueHandler, op);
496                         ops.add(op);
497                     }
498                     // execute the update operations
499                     session.endAutoTransaction();
500                     if (session.currentTransaction().isActive()) {
501                         // autotransaction is not set; need to explicitly execute the transaction
502                         session.executeNoCommit(false, true);
503                     }
504                     for (int i = 0; i < result.length; i++) {
505                         // evaluate the results
506                         int errorCode = ops.get(i).errorCode();
507                         // a non-zero result means the row was not updated
508                         result[i] = (errorCode == 0 ? 1 : 0);
509                     }
510                     break;
511                 }
512 
513                 case UNIQUE_KEY: {
514                     result = new long[valueHandler.getNumberOfStatements()];
515                     session.startAutoTransaction();
516                     Index storeIndex = index.getStoreIndex();
517                     if (logger.isDetailEnabled()) logger.detail("Update by unique key.");
518                     // iterate the valueHandlerBatching and for each set of parameters, update one row
519                     while (valueHandler.next()) {
520                         IndexOperation op = session.getUniqueIndexUpdateOperation(storeIndex,
521                             domainTypeHandler.getStoreTable());
522                         // set the keys of the indexName into the operation
523                         index.operationSetKeys(context, op);
524                         // set modified field values into the operation
525                         domainTypeHandler.operationSetModifiedNonPKValues(valueHandler, op);
526                         ops.add(op);
527                     }
528                     // execute the update operations
529                     session.endAutoTransaction();
530                     if (session.currentTransaction().isActive()) {
531                         // autotransaction is not set; need to explicitly execute the transaction
532                         session.executeNoCommit(false, true);
533                     }
534                     for (int i = 0; i < result.length; i++) {
535                         // evaluate the results
536                         int errorCode = ops.get(i).errorCode();
537                         // a non-zero result means the row was not updated
538                         result[i] = (errorCode == 0 ? 1 : 0);
539                     }
540                     break;
541                 }
542 
543                 case INDEX_SCAN: {
544                     // not supported
545                     break;
546                 }
547 
548                 case TABLE_SCAN: {
549                     // not supported
550                     break;
551                 }
552 
553                 default:
554                     throw new ClusterJFatalInternalException(
555                             local.message("ERR_Illegal_Scan_Type", scanType));
556             }
557             return result;
558         } catch (ClusterJException e) {
559             for (Operation op: ops) {
560                 op.freeResourcesAfterExecute();
561             }
562             session.failAutoTransaction();
563             throw e;
564         } catch (Exception e) {
565             for (Operation op: ops) {
566                 op.freeResourcesAfterExecute();
567             }
568             session.failAutoTransaction();
569             throw new ClusterJException(local.message("ERR_Exception_On_Query"), e);
570         }
571     }
572 
createCandidateIndexes()573     protected CandidateIndexImpl[] createCandidateIndexes() {
574         return domainTypeHandler.createCandidateIndexes();
575     }
576 
577     /** Explain how this query will be or was executed and store
578      * the result in the context.
579      *
580      * @param context the context, including bound parameters
581      */
explain(QueryExecutionContext context)582     public void explain(QueryExecutionContext context) {
583         assertAllParametersBound(context);
584         CandidateIndexImpl index = getCandidateIndex(context);
585         ScanType scanType = index.getScanType();
586         Map<String, Object> explain = newExplain(index, scanType);
587         context.setExplain(explain);
588     }
589 
getCandidateIndex(QueryExecutionContext context)590     private CandidateIndexImpl getCandidateIndex(QueryExecutionContext context) {
591         if (where == null) {
592             // there is no filter, so without ordering this is a table scan
593             // with ordering, choose an index that contains all ordering fields
594             CandidateIndexImpl[] candidateIndexImpls = domainTypeHandler.createCandidateIndexes();
595             for (CandidateIndexImpl candidateIndexImpl: candidateIndexImpls) {
596                 // choose the first index that contains all ordering fields
597                 if (candidateIndexImpl.containsAllOrderingFields(orderingFields)) {
598                     index = candidateIndexImpl;
599                     return index;
600                 }
601             }
602             index = CandidateIndexImpl.getIndexForNullWhereClause();
603         } else {
604             // there is a filter; choose the best index that contains all ordering fields
605             index = where.getBestCandidateIndex(context, orderingFields);
606         }
607         return index;
608     }
609 
610     /** Create a new explain for this query.
611      * @param index the index used
612      * @param scanType the scan type
613      * @return the explain
614      */
newExplain(CandidateIndexImpl index, ScanType scanType)615     protected Map<String, Object> newExplain(CandidateIndexImpl index,
616             ScanType scanType) {
617         Map<String, Object> explain = new HashMap<String, Object>();
618         explain.put(Query.SCAN_TYPE, scanType.toString());
619         explain.put(Query.INDEX_USED, index.getIndexName());
620         return explain;
621     }
622 
623     /** Assert that all parameters used by this query are bound.
624      * @param context the context, including the parameter map
625      * @throws ClusterJUserException if not all parameters are bound
626      */
assertAllParametersBound(QueryExecutionContext context)627     protected void assertAllParametersBound(QueryExecutionContext context) {
628         if (where != null) {
629             // Make sure all marked parameters (used in the query) are bound.
630             for (ParameterImpl param: parameters.values()) {
631                 if (param.isMarkedAndUnbound(context)) {
632                     throw new ClusterJUserException(
633                             local.message("ERR_Parameter_Not_Bound", param.getName()));
634                 }
635             }
636         }
637     }
638 
getType()639     public Class<T> getType() {
640         return cls;
641     }
642 
643     private ResultData resultDataEmpty = new ResultData() {
644 
645         public boolean next() {
646             // this ResultData has no results
647             return false;
648         }
649 
650         public BigInteger getBigInteger(Column columnName) {
651             return null;
652         }
653 
654         public BigInteger getBigInteger(int columnNumber) {
655             return null;
656         }
657 
658         public Blob getBlob(Column storeColumn) {
659             return null;
660         }
661 
662         public Blob getBlob(int columnNumber) {
663             return null;
664         }
665 
666         public boolean getBoolean(Column storeColumn) {
667             return false;
668         }
669 
670         public boolean getBoolean(int columnNumber) {
671             return false;
672         }
673 
674         public boolean[] getBooleans(Column storeColumn) {
675             return null;
676         }
677 
678         public boolean[] getBooleans(int columnNumber) {
679             return null;
680         }
681 
682         public byte getByte(Column storeColumn) {
683             return 0;
684         }
685 
686         public byte getByte(int columnNumber) {
687             return 0;
688         }
689 
690         public byte[] getBytes(Column storeColumn) {
691             return null;
692         }
693 
694         public byte[] getBytes(int columnNumber) {
695             return null;
696         }
697 
698         public Column[] getColumns() {
699             return null;
700         }
701 
702         public BigDecimal getDecimal(Column storeColumn) {
703             return null;
704         }
705 
706         public BigDecimal getDecimal(int columnNumber) {
707             return null;
708         }
709 
710         public double getDouble(Column storeColumn) {
711             return 0;
712         }
713 
714         public double getDouble(int columnNumber) {
715             return 0;
716         }
717 
718         public float getFloat(Column storeColumn) {
719             return 0;
720         }
721 
722         public float getFloat(int columnNumber) {
723             return 0;
724         }
725 
726         public int getInt(Column storeColumn) {
727             return 0;
728         }
729 
730         public int getInt(int columnNumber) {
731             return 0;
732         }
733 
734         public long getLong(Column storeColumn) {
735             return 0;
736         }
737 
738         public long getLong(int columnNumber) {
739             return 0;
740         }
741 
742         public Object getObject(Column storeColumn) {
743             return null;
744         }
745 
746         public Object getObject(int column) {
747             return null;
748         }
749 
750         public Boolean getObjectBoolean(Column storeColumn) {
751             return null;
752         }
753 
754         public Boolean getObjectBoolean(int columnNumber) {
755             return null;
756         }
757 
758         public Byte getObjectByte(Column storeColumn) {
759             return null;
760         }
761 
762         public Byte getObjectByte(int columnNumber) {
763             return null;
764         }
765 
766         public Double getObjectDouble(Column storeColumn) {
767             return null;
768         }
769 
770         public Double getObjectDouble(int columnNumber) {
771             return null;
772         }
773 
774         public Float getObjectFloat(Column storeColumn) {
775             return null;
776         }
777 
778         public Float getObjectFloat(int columnNumber) {
779             return null;
780         }
781 
782         public Integer getObjectInteger(Column storeColumn) {
783             return null;
784         }
785 
786         public Integer getObjectInteger(int columnNumber) {
787             return null;
788         }
789 
790         public Long getObjectLong(Column storeColumn) {
791             return null;
792         }
793 
794         public Long getObjectLong(int columnNumber) {
795             return null;
796         }
797 
798         public Short getObjectShort(Column storeColumn) {
799             return null;
800         }
801 
802         public Short getObjectShort(int columnNumber) {
803             return null;
804         }
805 
806         public short getShort(Column storeColumn) {
807             return 0;
808         }
809 
810         public short getShort(int columnNumber) {
811             return 0;
812         }
813 
814         public String getString(Column storeColumn) {
815             return null;
816         }
817 
818         public String getString(int columnNumber) {
819             return null;
820         }
821 
822     };
823 }
824