KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdbc > query > JdbcCompiledQuery


1
2 /*
3  * Copyright (c) 1998 - 2005 Versant Corporation
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  * Versant Corporation - initial API and implementation
11  */

12 package com.versant.core.jdbc.query;
13
14 import com.versant.core.jdo.QueryDetails;
15 import com.versant.core.metadata.*;
16 import com.versant.core.jdo.query.GroupingNode;
17 import com.versant.core.server.CompiledQuery;
18 import com.versant.core.jdbc.FgDs;
19 import com.versant.core.jdbc.JdbcQueryResult;
20 import com.versant.core.jdbc.ProjectionQueryDecoder;
21 import com.versant.core.jdbc.metadata.JdbcColumn;
22 import com.versant.core.jdbc.metadata.JdbcField;
23 import com.versant.core.jdbc.metadata.JdbcRefField;
24 import com.versant.core.jdbc.metadata.JdbcClass;
25 import com.versant.core.jdbc.sql.SqlDriver;
26 import com.versant.core.util.CharBuf;
27 import com.versant.core.common.Debug;
28
29 import java.sql.*;
30 import java.util.HashMap JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33 import java.util.List JavaDoc;
34
35 import com.versant.core.common.BindingSupportImpl;
36
37 /**
38  * This is a QueryImp compiled by a JdbcDataStore and ready to run.
39  * It contains the SQL and enough information to convert the ResultSet
40  * into State's. There is not much logic to avoid referencing server side
41  * classes as a client application may serialize a query containing one of
42  * these and re-associate it with a PM later.
43  */

44 public class JdbcCompiledQuery implements CompiledQuery {
45
46     public static final int PARAM_IN = 0;//default
47
public static final int PARAM_OUT = 1;
48     public static final int PARAM_OUT_CURSOR = 2;
49
50     private int id;
51     private final QueryDetails qp;
52
53     private Map JavaDoc parCollSqlStrucMap = new HashMap JavaDoc();
54
55     /**
56      * The class index of the candidate class of the query.
57      */

58     private int classIndex;
59     /**
60      * The cls index's of all the filter classes.
61      */

62     private ClassMetaData[] filterCmds;
63     /**
64      * Bitmapped array of the class indexes that will cause the results
65      * of this query to be evicted when their instances are modified. Each
66      * class index has one bit in this array.
67      */

68     private int[] evictionClassBits;
69     private int[] evictionClassIndexes;
70     /**
71      * If the results of the query is cacheble.
72      */

73     private boolean cacheble;
74     /**
75      * Must subclasses be included in the result?
76      */

77     private boolean includeSubclasses;
78     /**
79      * The root fetch group for the query. This will be from cmd. This
80      * will be the default fetch group unless the user specified a
81      * different group.
82      */

83     private int fetchGroupIndex;
84     /**
85      * Must this query return results suitable for random access?
86      */

87     private boolean randomAccess;
88     /**
89      * The max amount of rows to return for this query.
90      */

91     private int maxRows;
92     /**
93      * This is the amount of data that will be prefetched per each round trip
94      * to the server.
95      */

96     private int queryResultBatchSize;
97
98     private SqlStruct sqlStruct;
99
100     private boolean parColFetchEnabled;
101     /**
102      * This is the group by exp for the aggregate expression.
103      * This may only be non-null if result was specified and it contains aggregates.
104      */

105     private GroupingNode groupByNode;
106     protected int unique;
107     private int selectColumnCount;
108     private boolean copyResultsForCache;
109     public FgDs fgDs;
110     private boolean sqlQuery;
111     private boolean storeProc;
112     private boolean directSql;
113     private MappingInfo mappingInfo;
114     private ClassMetaData cmd;
115     private int[] sqlTypes;
116     /**
117      * If this is a 'in', 'out' or a 'inout' type
118      */

119     private int[] paramDirection;
120     private int outParamCount;
121
122     private boolean crossJoinAllowed;
123     private ProjectionQueryDecoder projectionDecoder;
124
125     public JdbcCompiledQuery(ClassMetaData cmd, QueryDetails queryParams) {
126         this.cmd = cmd;
127         if (cmd != null) {
128             this.classIndex = cmd.index;
129             this.includeSubclasses = queryParams.includeSubClasses() && cmd.isInHeirachy();
130         } else {
131             this.classIndex = -1;
132         }
133         if (queryParams.getLanguage() == QueryDetails.LANGUAGE_SQL) {
134             sqlQuery = true;
135             if (queryParams.getFilter() == null || queryParams.getFilter().trim().length() == 0) {
136                 throw BindingSupportImpl.getInstance().invalidOperation(
137                         "Must supply a valid filter for a 'SqlQeury'");
138             }
139             if (queryParams.getFilter().toUpperCase().startsWith("SELECT")) {
140                 storeProc = false;
141                 directSql = true;
142             } else {
143                 storeProc = true;
144                 directSql = false;
145             }
146         }
147
148         this.fetchGroupIndex = queryParams.getFetchGroupIndex();
149         this.randomAccess = queryParams.isRandomAccess();
150         this.maxRows = queryParams.getMaxResultCount();
151         this.queryResultBatchSize = queryParams.getResultBatchSize();
152         if (Debug.DEBUG) {
153             if (queryResultBatchSize <= 0) {
154                 throw BindingSupportImpl.getInstance().internal(
155                         "The queryDetails.resultBatchSize is not set");
156             }
157         }
158         this.qp = queryParams;
159
160         if (!sqlQuery) {
161             this.sqlStruct = new SqlStruct();
162             this.sqlStruct.jdoqlFilter = queryParams.getFilter();
163             if (sqlStruct.jdoqlFilter == null || sqlStruct.jdoqlFilter.length() == 0) {
164                 sqlStruct.jdoqlFilter = "NO FILTER";
165             }
166
167                 parColFetchEnabled = QueryDetails.enableParallelCollectionFetch(qp,
168                     cmd.fetchGroups[qp.getFetchGroupIndex()]);
169         } else {
170             unique = QueryDetails.FALSE;
171             //process the param types.
172
String JavaDoc[] types = queryParams.getParamTypes();
173             int count = queryParams.getParamCount();
174             sqlTypes = new int[count];
175             paramDirection = new int[count];
176             for (int i = 0; i < count; i++) {
177                 String JavaDoc type = types[i].toUpperCase();
178                 if (type.startsWith("OUT.")) {
179                     outParamCount++;
180                     if (type.equals("OUT.CURSOR")) {
181                         //the rs
182
paramDirection[i] = PARAM_OUT_CURSOR;
183                     } else {
184                         //change unique to true as we will create an Object[]
185
unique = QueryDetails.TRUE;
186                         //single value
187
paramDirection[i] = PARAM_OUT;
188                         sqlTypes[i] = getTypeInt(type.substring(type.indexOf(".") + 1));
189                     }
190                 } else {
191                     sqlTypes[i] = getTypeInt(types[i]);
192                 }
193             }
194         }
195     }
196
197     public ClassMetaData getCmd() {
198         return cmd;
199     }
200
201     public void setCmd(ClassMetaData cmd) {
202         this.cmd = cmd;
203     }
204
205     public int getOutParamCount() {
206         return outParamCount;
207     }
208
209     public int[] getSqlTypes() {
210         return sqlTypes;
211     }
212
213     public int[] getParamDirection() {
214         return paramDirection;
215     }
216
217     private int getTypeInt(String JavaDoc val) {
218         try {
219             return Types.class.getDeclaredField(val.toUpperCase()).getInt(null);
220         } catch (Exception JavaDoc e) {
221             throw BindingSupportImpl.getInstance().internal("Param type '" + val
222                     + "' is not a valid " + Types.class.getName() + " type.");
223         }
224     }
225
226     public boolean isSqlQuery() {
227         return sqlQuery;
228     }
229
230     public int getSelectColumnCount() {
231         return selectColumnCount;
232     }
233
234     public void setSelectColumnCount(int selectColumnCount) {
235         this.selectColumnCount = selectColumnCount;
236     }
237
238     /**
239      * This may only be called once the resultnode and the groupBy node has been processed and set.
240      */

241     public void process() {
242         if (qp.getUnique() == QueryDetails.TRUE) {
243             unique = QueryDetails.TRUE;
244         } else if (qp.getUnique() == QueryDetails.FALSE) {
245             unique = QueryDetails.FALSE;
246         } else {
247             if (projectionDecoder != null) {
248                 if (projectionDecoder.containsAggregate()) {
249                     if (groupByNode == null) {
250                         if (!projectionDecoder.aggregateOnly()) {
251                             unique = QueryDetails.FALSE;
252                         } else {
253                             unique = QueryDetails.TRUE;
254                         }
255                     } else {
256                         if (projectionDecoder.aggregateOnly()) {
257                             unique = QueryDetails.TRUE;
258                         } else {
259                             unique = QueryDetails.FALSE;
260                         }
261                     }
262                 } else {
263                     unique = QueryDetails.FALSE;
264                     if (groupByNode != null) {
265                         throw BindingSupportImpl.getInstance().invalidOperation("The query contains a 'Group By' " +
266                                 "expression but no aggregate's.");
267                     }
268                 }
269             } else {
270                 unique = QueryDetails.FALSE;
271             }
272         }
273
274         copyResultsForCache = (projectionDecoder != null
275                 && !projectionDecoder.isContainsThisOnly()
276                 && projectionDecoder.getRefIndexArray().length > 0);
277
278         sqlStruct.setAggregate(
279                 projectionDecoder != null && projectionDecoder.containsAggregate());
280
281         crossJoinAllowed = (projectionDecoder == null)
282                 && parColFetchEnabled
283                 && !sqlQuery
284                 && !qp.isRandomAccess()
285                 && (qp.getMaxResultCount() <= 0);
286     }
287
288     /**
289      * If this is a query with a single/unique result.
290      */

291     public boolean isUnique() {
292         if (unique == QueryDetails.NOT_SET) {
293             throw BindingSupportImpl.getInstance().internal(
294                     "The 'unique' value has not been processed.");
295         }
296         if (unique == QueryDetails.TRUE) return true;
297         return false;
298     }
299
300     public boolean isProjectionQuery() {
301         return (projectionDecoder != null);
302     }
303
304     public int getFirstThisIndex() {
305         if (projectionDecoder == null) return -1;
306         return projectionDecoder.getFirstThisIndex();
307     }
308
309     /**
310      * If this is a result/projection that only contains 'this' and no other
311      * fields in the projection.
312      */

313     public boolean isContainsThisOnly() {
314         return projectionDecoder.isContainsThisOnly();
315     }
316
317     /**
318      * If this is a result/projection that only contains 'this' and no other
319      * fields in the projection.
320      */

321     public boolean isContainsThis() {
322         if (projectionDecoder == null) return false;
323         return projectionDecoder.containsThis();
324     }
325
326     /**
327      * If the results of the query should be copied for caching.
328      * This should only happen for non-default type projection queries that
329      * contains references.
330      * <p/>
331      * If this is a projection that only specifies 'this' then this should
332      * also return false.
333      */

334     public boolean isCopyResultsForCache() {
335         return copyResultsForCache;
336     }
337
338     /**
339      * If this query returns default results.
340      */

341     public boolean isDefaultResult() {
342         if (sqlQuery) {
343             return cmd != null;
344         }
345         if (projectionDecoder == null) return true;
346         return projectionDecoder.isContainsThisOnly();
347     }
348
349     /**
350      * Array containing the index pos of ref fields of the projection.
351      * Return null if no ref fields in projection.
352      */

353     public int[] getRefIndexArray() {
354         if (projectionDecoder == null) {
355             throw BindingSupportImpl.getInstance().internal(
356                     "This may only be called on 'projection queries'");
357         }
358         return projectionDecoder.getRefIndexArray();
359     }
360
361     public int[] getResultTypeCodes() {
362         return projectionDecoder == null ? null : projectionDecoder.getTypeCodes();
363     }
364
365     public void setGroupingNode(GroupingNode groupingNode) {
366         groupByNode = groupingNode;
367     }
368
369     public boolean isParColFetchEnabled() {
370         return parColFetchEnabled;
371     }
372
373     public synchronized SqlStruct get(JdbcQueryResult.ColFHKey key) {
374         return (SqlStruct)parCollSqlStrucMap.get(key);
375     }
376
377     public synchronized void add(JdbcQueryResult.ColFHKey key, SqlStruct val) {
378         parCollSqlStrucMap.put(key, val);
379     }
380
381     public SqlStruct getSqlStruct() {
382         return sqlStruct;
383     }
384
385     public int getMaxRows() {
386         return maxRows;
387     }
388
389     public int getQueryResultBatchSize() {
390         return queryResultBatchSize;
391     }
392
393     public ClassMetaData[] getQueryClasses() {
394         return filterCmds;
395     }
396
397     public void setFilterClsIndexs(ClassMetaData[] filterClsIndexs) {
398         this.filterCmds = filterClsIndexs;
399     }
400
401     public int[] getEvictionClassBits() {
402         return evictionClassBits;
403     }
404
405     public int[] getClassIndexes() {
406         return evictionClassIndexes;
407     }
408
409     public QueryDetails getQueryDetails() {
410         return qp;
411     }
412
413     public void setEvictionClassBits(int[] evictionClassBits) {
414         this.evictionClassBits = evictionClassBits;
415     }
416
417     public void setEvictionClassIndexes(int[] evictionClassIndexes) {
418         this.evictionClassIndexes = evictionClassIndexes;
419     }
420
421     public boolean isCacheble() {
422         return cacheble;
423     }
424
425     public void setCacheable(boolean cacheble) {
426         this.cacheble = cacheble;
427     }
428
429     public String JavaDoc getFirstTableOrAlias() {
430         return sqlStruct.getFirstTableOrAlias();
431     }
432
433     public void setFirstTableOrAlias(String JavaDoc firstTableOrAlias) {
434         sqlStruct.setFirstTableOrAlias(firstTableOrAlias);
435     }
436
437     public boolean isDistinct() {
438         return sqlStruct.isDistinct();
439     }
440
441     /**
442      * Get the SQL query text.
443      */

444     public String JavaDoc getSql() {
445         return sqlStruct.getSql();
446     }
447
448     public int getClassIndex() {
449         return classIndex;
450     }
451
452     public boolean isIncludeSubclasses() {
453         return includeSubclasses;
454     }
455
456     public int getFetchGroupIndex() {
457         return fetchGroupIndex;
458     }
459
460     public FetchGroup getFetchGroup() {
461         return cmd.fetchGroups[fetchGroupIndex];
462     }
463
464     public boolean isRandomAccess() {
465         return randomAccess;
466     }
467
468     public CharBuf getSqlbuf() {
469         return sqlStruct.getSqlbuf();
470     }
471
472     public SqlStruct.Param getParamList() {
473         return sqlStruct.getParamList();
474     }
475
476     /**
477      * Update all our Param's for the null/not null state of their parameters
478      * and for 'select for update' or not. This may change the SQL query
479      * string.
480      */

481     public void updateSql(SqlDriver driver, Object JavaDoc[] params, boolean forUpdate,
482             boolean forCount) {
483         sqlStruct.updateSql(driver, params, forUpdate, forCount);
484     }
485
486     /**
487      * Set all the parameters for this query on ps. This is a NOP if params
488      * is null.
489      */

490     public void setParamsOnPS(ModelMetaData jmd, SqlDriver driver,
491             PreparedStatement ps, Object JavaDoc[] params, String JavaDoc sql)
492             throws SQLException {
493         sqlStruct.setParamsOnPS(jmd, driver, ps, params, sql);
494     }
495
496     public MappingInfo getMappingInfo(ResultSet rs) throws SQLException {
497         if (mappingInfo == null) {
498             mappingInfo = createMappingInfo(rs.getMetaData(), cmd);
499         }
500         return mappingInfo;
501     }
502
503     public boolean equals(Object JavaDoc obj) {
504         if (obj == this) return true;
505         if (obj instanceof JdbcCompiledQuery) {
506             return qp.equals(((JdbcCompiledQuery)obj).qp);
507         }
508         return false;
509     }
510
511     public int hashCode() {
512         return qp.hashCode();
513     }
514
515     public static MappingInfo createMappingInfo(ResultSetMetaData rsmd, ClassMetaData cmd) throws SQLException {
516         final int count = rsmd.getColumnCount();
517         MappingInfo mi = new MappingInfo();
518         mi.colCount = count;
519         if (cmd == null) return mi;
520         mi.cmd = cmd;
521
522         JdbcColumn[] pkCols = ((JdbcClass)cmd.storeClass).table.pk;
523         JdbcColumn discr = ((JdbcClass)cmd.storeClass).classIdCol;
524
525         /**
526          * Look for discriminator
527          */

528         if (discr != null) {
529             //get the discriminator col
530
for (int i = 1; i <= count; ) {
531                 if (discr.name.toUpperCase().equals(rsmd.getColumnName(i).toUpperCase())) {
532                     mi.discrIndex = i++;
533                     break;
534                 }
535                 i++;
536             }
537         }
538
539         final boolean appId = cmd.pkFields != null;
540         Set JavaDoc fieldList = new java.util.HashSet JavaDoc();
541         JdbcField[] jdbcFields = mi.fields = new JdbcField[count];
542         int[] pkindexes = null;
543         if (appId) {
544             pkindexes = new int[pkCols.length];
545         }
546
547         for (int i = 1; i <= count;) {
548             String JavaDoc colName = rsmd.getColumnName(i).toUpperCase();
549
550             //skip the already found discriminator col
551
if (i == mi.discrIndex) {
552                 i++;
553                 continue;
554             }
555
556 // if (mi.pkIndex == -1 && pkCols[0].name.toUpperCase().equals(colName)) {
557
// //assume the same ordering
558
// boolean ok = true;
559
// for (int j = 1; j < pkCols.length; j++) {
560
// if (!pkCols[j].name.toUpperCase().equals(rsmd.getColumnName(i + j).toUpperCase())) {
561
// ok = false;
562
// break;
563
// }
564
// }
565
//
566
// if (ok) {
567
// mi.pkIndex = i;
568
// i += pkCols.length;
569
// continue;
570
// }
571
// }
572

573
574             if (mi.dsPkIndex == -1 && !appId && pkCols[0].name.toUpperCase().equals(colName)) {
575                 //assume the same ordering
576
mi.dsPkIndex = i;
577                 i++;
578                 continue;
579             }
580
581             JdbcField field = getSubClassField(colName, cmd, mi.discrIndex != 0);
582 // if (field == null) {
583
// refFieldToJdbcField.clear();
584
// field = getRefField(colName, cmd, true, refFieldToJdbcField);
585
// System.out.println("refField = " + refFieldToJdbcField.fromField);
586
// if (field != null) {
587
// System.out.println("found ref field: " + field);
588
// }
589
// }
590

591             if (field != null) {
592                 if (fieldList.contains(field)) {
593                     //ignore
594
System.out.println("Ignoring column '"
595                                     + colName + "' at index '"
596                                     + i + "' because this column has already been mapped to '"
597                                     + field.fmd.classMetaData.qname + "." + field.fmd.name + "'");
598                     i++;
599                     continue;
600                 } else {
601                     if (field.mainTableCols.length == 1) {
602                         fieldList.add(field);
603                         jdbcFields[i - 1] = field;
604                         i++;
605                         continue;
606                     } else {
607                         /**
608                          * This field is mapped to more that one column in the db
609                          * so we must check to see that the next n cols will also resolve to this
610                          * field. If not the skip the current col
611                          */

612                         int endIndex = i + field.mainTableCols.length;
613                         boolean ok = false;
614                         for (int j = i + 1; j < endIndex; j++) {
615                             if (((JdbcClass)cmd.storeClass).getColNamesToJdbcField().get(colName) != field) {
616                                 //not the current field so skip this col and continue
617
break;
618                             }
619                         }
620
621                         if (ok) {
622                             /**
623                              * all the cols matched for the current field so accept it. Update the index
624                              * to the endindex.
625                              */

626                             fieldList.add(field);
627                             jdbcFields[i - 1] = field;
628                             i = endIndex;
629                         } else {
630                             /**
631                              * Skip the current col
632                              */

633                             i++;
634                         }
635                         continue;
636                     }
637                 }
638             } else {
639                 i++;
640                 //not in this class
641
}
642         }
643
644         if (cmd.pkFields != null) {
645             //flag to check that all pk fields are found in the jdbcfields array
646
boolean keyFound = false;
647             for (int i = 0; i < cmd.pkFields.length; i++) {
648                 FieldMetaData pkField = cmd.pkFields[i];
649                 keyFound = false;
650                 for (int j = 0; j < jdbcFields.length; j++) {
651                     JdbcField jdbcField = jdbcFields[j];
652                     if (pkField.storeField == jdbcField) {
653                         keyFound = true;
654                         pkindexes[i] = j;
655                         break;
656                     }
657                 }
658                 //if any of the keys is not found then break.
659
if (!keyFound) {
660                     break;
661                 }
662             }
663
664             if (Debug.DEBUG) {
665                 if (keyFound) {
666                     for (int i = 0; i < cmd.pkFields.length; i++) {
667                         FieldMetaData pkField = cmd.pkFields[i];
668                         if (pkField.storeField != jdbcFields[pkindexes[i]]) {
669                             throw BindingSupportImpl.getInstance().internal("pk field mismatch");
670                         }
671                     }
672                 }
673             }
674             if (keyFound) {
675                 mi.pkIndexInFieldsArray = pkindexes;
676             }
677         }
678 // if (mi.pkIndex == -1) {
679
// throw BindingSupportImpl.getInstance().invalidOperation("No columns in the result set " +
680
// "could be mapped to the pk fields");
681
// }
682
return mi;
683     }
684
685     /**
686      * Find a JdbcField by column name from reference fields.
687      */

688     private static JdbcField getRefField(String JavaDoc colName, ClassMetaData cmd, boolean includeSubs,
689                                          RefFieldMapping refFieldMapping) {
690         if (!includeSubs) {
691             return getRefFieldImp(cmd, colName, true);
692         } else {
693             List JavaDoc cmds = cmd.getHeirarchyList();
694             for (int i = 0; i < cmds.size(); i++) {
695                 JdbcField jdbcField = getRefFieldImp((ClassMetaData) cmds.get(i), colName, true);
696                 if (jdbcField != null) return jdbcField;
697             }
698         }
699         return null;
700     }
701
702     /**
703      * Find a JdbcField by column name from reference fields.
704      */

705     private static JdbcField getRefFieldImp(ClassMetaData cmd, String JavaDoc colName, boolean includeSubs) {
706         FieldMetaData[] fields = cmd.stateFields;
707         for (int i = 0; i < fields.length; i++) {
708             FieldMetaData fmd = fields[i];
709             if (fmd.category == MDStatics.CATEGORY_REF) {
710                 JdbcField jdbcField = getSubClassField(colName, fmd.typeMetaData, includeSubs);
711                 if (jdbcField != null) return jdbcField;
712             }
713         }
714         return null;
715     }
716
717     /**
718      * Do a breadth first recursive traversal of subclasses to find a JdbcField with a column name.
719      */

720     private static JdbcField getSubClassField(String JavaDoc colName, ClassMetaData cmd, boolean checkSubClasses) {
721         if (!checkSubClasses) {
722             return (JdbcField)((JdbcClass)cmd.storeClass).getColNamesToJdbcField().get(colName);
723         } else {
724             List JavaDoc subsList = cmd.getHeirarchyList();
725             for (int i = 0; i < subsList.size(); i++) {
726                 ClassMetaData icmd = (ClassMetaData) subsList.get(i);
727                 JdbcField field =
728                         (JdbcField)((JdbcClass)icmd.storeClass).getColNamesToJdbcField().get(colName);
729                 if (field != null) return field;
730             }
731         }
732         return null;
733     }
734
735     public boolean isStoredProc() {
736         return storeProc;
737     }
738
739     public boolean isDirectSql() {
740         return directSql;
741     }
742
743     public boolean isCrossJoinAllowed() {
744         return crossJoinAllowed;
745     }
746
747     public ProjectionQueryDecoder getProjectionDecoder() {
748         return projectionDecoder;
749     }
750
751     public void setProjectionDecoder(ProjectionQueryDecoder decoder) {
752         this.projectionDecoder = decoder;
753     }
754
755     /**
756      * Todo get rid of this horrible hack when we refactor all the query stuff
757      */

758     public boolean isEJBQLHack() {
759         return false;
760     }
761
762
763
764     /**
765      * Utils struct that is used when building mapping info for
766      * sql queries.
767      */

768     public static class RefFieldMapping {
769         public JdbcRefField fromField;
770         public JdbcField toField;
771
772         public void clear() {
773             fromField = null;
774             toField = null;
775         }
776     }
777
778     /**
779      * Utils struct to hold the info wrt to mapping jdbc fields to a
780      * 'sql' query.
781      */

782     public static class MappingInfo {
783         public ClassMetaData cmd;
784         /**
785          * The index pos of where the pkCols start
786          */

787         public int dsPkIndex = -1;
788         /**
789          * The index pos of where the discr Cols is
790          */

791         public int discrIndex = 0;
792         /**
793          * These are only fields for this hierarchy. The position in the array determine
794          * the index in rs shifted by 1.
795          */

796         public JdbcField[] fields;
797         public int colCount;
798         public boolean pkFieldsFound;
799         public boolean discriminatorColFound;
800         public int[] pkIndexInFieldsArray;
801
802         public void dump() {
803             System.out.println("MappingInfo.dump@" + System.identityHashCode(this));
804             for (int i = 0; i < fields.length; i++) {
805                 JdbcField jdbcField = fields[i];
806                 if (jdbcField != null) {
807                     System.out.println("jdbcField = " + jdbcField);
808                 }
809             }
810         }
811
812         /**
813          * If there is enough info to map(id , discriminator)
814          */

815         public boolean isPkValid() {
816             return dsPkIndex != -1 || pkIndexInFieldsArray != null;
817         }
818     }
819
820     public String JavaDoc toString() {
821         return sqlStruct == null ? "sqlStruct is null" : sqlStruct.getSql();
822     }
823
824     public int getId() {
825         return id;
826     }
827
828     public void setId(int id) {
829         this.id = id;
830     }
831
832 }
833
Popular Tags