KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > versant > core > jdbc > metadata > JdbcColumn


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.metadata;
13
14 import com.versant.core.common.Debug;
15 import com.versant.core.common.NotImplementedException;
16 import com.versant.core.metadata.MDStaticUtils;
17 import com.versant.core.jdbc.JdbcConverter;
18 import com.versant.core.jdbc.JdbcConverterFactory;
19 import com.versant.core.jdbc.JdbcTypeRegistry;
20 import com.versant.core.jdbc.JdbcUtils;
21 import com.versant.core.jdbc.sql.JdbcNameGenerator;
22 import com.versant.core.jdbc.sql.SqlDriver;
23 import com.versant.core.jdbc.sql.exp.*;
24 import com.versant.core.util.CharBuf;
25
26 import java.io.Serializable JavaDoc;
27 import java.sql.PreparedStatement JavaDoc;
28 import java.sql.ResultSet JavaDoc;
29 import java.sql.SQLException JavaDoc;
30
31 import com.versant.core.common.BindingSupportImpl;
32
33 /**
34  * A column in a JDBC table.
35  */

36 public final class JdbcColumn implements Serializable JavaDoc {
37
38     /**
39      * The table this column belongs to.
40      */

41     public transient JdbcTable table;
42     /**
43      * The java type of this column. This is used to select converters
44      * etc and when the state of this column needs to be stored. For a column
45      * for a persistent field this will just be the type of the field.
46      */

47     public transient Class JavaDoc javaType;
48     /**
49      * The java type code of this column from MDStatics.
50      *
51      * @see com.versant.core.metadata.MDStatics
52      */

53     public int javaTypeCode;
54     /**
55      * Is this column part of the primary key for its table?
56      */

57     public boolean pk;
58     /**
59      * Is this column part of a foreign key reference to another table?
60      */

61     public boolean foreignKey;
62     /**
63      * Is this column part of an index?
64      */

65     public boolean partOfIndex;
66     /**
67      * Is this an autoincrement column?
68      */

69     public boolean autoinc;
70     /**
71      * The JDBC name of this column.
72      */

73     public String JavaDoc name;
74     /**
75      * The JDBC type of this column from java.sql.Types.
76      */

77     public int jdbcType;
78     /**
79      * The actual SQL type of this column for create scripts etc.
80      */

81     public String JavaDoc sqlType;
82     
83     
84     /**
85      * The length (or precision) of this column.
86      */

87     public int length;
88     /**
89      * The scale of this column (number of digits after the decimal point).
90      */

91     public int scale;
92     /**
93      * Does this column allow nulls?
94      */

95     public boolean nulls;
96     /**
97      * Can values from this column be compared for equality with Java values?
98      * Non-exact data types should have false here (e.g. float and double).
99      */

100     public boolean equalityTest;
101     /**
102      * Should this column not be created when generating the schema? This
103      * is used when columns are shared between one or more fields.
104      */

105     public boolean shared;
106     /**
107      * This is responsible for getting a suitable java value for this column
108      * from a ResultSet and setting the java value of this column on a
109      * PreparedStatement. It may be null in which case the ResultSet should
110      * be accessed directly using one of the getXXX or setXXX methods.
111      */

112     public transient JdbcConverter converter;
113     /**
114      * The name of the field this column references. This is used for columns
115      * that reference composite primary key classes to identify which
116      * primary key field the column is for.
117      */

118     public transient JdbcSimpleField refField;
119     /**
120      * Comment info for the SQL script (e.g. what field this column is for).
121      */

122     public String JavaDoc comment;
123
124     public JdbcColumn() {
125     }
126
127     public JdbcColumn(JdbcJavaTypeMapping m, JdbcTypeRegistry jdbcTypeRegistry) {
128         sqlType = m.getSqlType();
129         if (sqlType == null) {
130             throw BindingSupportImpl.getInstance().internal(
131                     "sqlType is null: " + m);
132         }
133         
134         setJavaType(m.getJavaType());
135         jdbcType = m.getJdbcType();
136         length = m.getLength();
137         scale = m.getScale();
138         nulls = m.getNulls() != JdbcJavaTypeMapping.FALSE;
139         equalityTest = m.getEqualityTest() != JdbcJavaTypeMapping.FALSE;
140         setShared(m.getShared() == JdbcJavaTypeMapping.TRUE);
141         JdbcConverterFactory cf = m.getConverterFactory();
142         if (cf != null) {
143             converter = cf.createJdbcConverter(this, null, jdbcTypeRegistry);
144             if (converter != null && converter.isOracleStyleLOB()) equalityTest = false;
145         }
146     }
147
148     /**
149      * Set our properties based on the info in the mapping. This is useful
150      * when a column is based on another column instead of being created
151      * by resolving the mapping (e.g. reference fields).
152      */

153     public void updateFrom(JdbcJavaTypeMapping m,
154             JdbcTypeRegistry jdbcTypeRegistry) {
155         if (m.getSqlType() != null) sqlType = m.getSqlType();
156         if (m.getJavaType() != null) setJavaType(m.getJavaType());
157         if (m.getJdbcType() != 0) jdbcType = m.getJdbcType();
158         if (m.getLength() != -1) length = m.getLength();
159         if (m.getScale() != -1) scale = m.getScale();
160         if (m.getNulls() != JdbcJavaTypeMapping.NOT_SET) {
161             nulls = m.getNulls() != JdbcJavaTypeMapping.FALSE;
162         }
163         if (m.getEqualityTest() != JdbcJavaTypeMapping.NOT_SET) {
164             equalityTest = m.getEqualityTest() != JdbcJavaTypeMapping.FALSE;
165         }
166         if (m.getShared() != JdbcJavaTypeMapping.NOT_SET) {
167             setShared(m.getShared() != JdbcJavaTypeMapping.FALSE);
168         }
169         JdbcConverterFactory cf = m.getConverterFactory();
170         if (cf != null) {
171             converter = cf.createJdbcConverter(this, null, jdbcTypeRegistry);
172             if (converter != null && converter.isOracleStyleLOB()) equalityTest = false;
173         }
174     }
175
176     /**
177      * Set the javaType and the javaTypeCode.
178      */

179     public void setJavaType(Class JavaDoc javaType) {
180         this.javaType = javaType;
181         javaTypeCode = MDStaticUtils.toTypeCode(javaType);
182     }
183
184     public Class JavaDoc getJavaType() {
185         return javaType;
186     }
187
188     /**
189      * If the column or its component columns have names then add them to
190      * nameGen.
191      *
192      * @throws IllegalArgumentException if any names are invalid
193      */

194     public void addColumnNames(String JavaDoc tableName, JdbcNameGenerator nameGen)
195             throws IllegalArgumentException JavaDoc {
196         if (name != null) nameGen.addColumnName(tableName, name);
197     }
198
199     /**
200      * Get the names of all our component columns.
201      */

202     public String JavaDoc[] getColumnNames() {
203         return new String JavaDoc[]{name};
204     }
205
206     /**
207      * Get the names of all our component columns into the array.
208      */

209     public void getColumnNames(String JavaDoc[] names) {
210         names[0] = name;
211     }
212
213     /**
214      * Set the names of all our component columns from the array.
215      */

216     public void setColumnNames(String JavaDoc[] names) {
217         name = names[0];
218     }
219
220     /**
221      * Set our table field and recursively all our columns.
222      */

223     public void setTable(JdbcTable t) {
224         table = t;
225     }
226
227     /**
228      * Duplicate this column but leave the name, table and refField fields of
229      * the duplicates null.
230      */

231     public JdbcColumn copy() {
232         JdbcColumn d = new JdbcColumn();
233         d.javaType = javaType;
234         d.pk = pk;
235         d.javaTypeCode = javaTypeCode;
236         d.jdbcType = jdbcType;
237         d.sqlType = sqlType;
238         d.length = length;
239         d.scale = scale;
240         d.nulls = nulls;
241         d.equalityTest = equalityTest;
242         d.setShared(shared);
243         d.converter = converter;
244         return d;
245     }
246
247     /**
248      * Combine two arrays of JdbcColumn's into one. If b is null then a is
249      * returned as is.
250      */

251     public static JdbcColumn[] concat(JdbcColumn[] a, JdbcColumn[] b) {
252         if (b == null) return a;
253         if (a == null) return b;
254         int na = a.length;
255         int nb = b.length;
256         JdbcColumn[] ans = new JdbcColumn[na + nb];
257         System.arraycopy(a, 0, ans, 0, na);
258         System.arraycopy(b, 0, ans, na, nb);
259         return ans;
260     }
261
262     /**
263      * Combine an arrays of JdbcColumn's and a single column into one. If
264      * the single column is null then the array is returned as is.
265      */

266     public static JdbcColumn[] concat(JdbcColumn[] a, JdbcColumn b) {
267         if (b == null) return a;
268         int na = a.length;
269         JdbcColumn[] ans = new JdbcColumn[na + 1];
270         System.arraycopy(a, 0, ans, 0, na);
271         ans[na] = b;
272         return ans;
273     }
274
275     /**
276      * Flatten cols into a list of expressions to select all the cols.
277      */

278     public static SqlExp toSqlExp(JdbcColumn[] cols, SelectExp se) {
279         SqlExp list = new ColumnExp(cols[0], se, null);
280         SqlExp e = list;
281         int nc = cols.length;
282         for (int i = 1; i < nc; i++) {
283             e = e.next = new ColumnExp(cols[i], se, null);
284         }
285         return list;
286     }
287
288     /**
289      * Flatten cols into a list of expressions to select all the cols. Add the sqlExp
290      * to the end of the created list.
291      */

292     public static SqlExp toSqlExp(JdbcColumn[] cols, SelectExp se,
293             SqlExp sList) {
294         SqlExp list = new ColumnExp(cols[0], se, null);
295         SqlExp e = list;
296         int nc = cols.length;
297         for (int i = 1; i < nc; i++) {
298             e = e.next = new ColumnExp(cols[i], se, null);
299         }
300         e.next = sList;
301         return list;
302     }
303
304     /**
305      * Get a list of expressions to select all our simple cols.
306      */

307     public SqlExp toSqlExp(SelectExp se) {
308         return new ColumnExp(this, SelectExp.createJoinToSuperTable(se, table),
309                 null);
310     }
311
312     /**
313      * If the column or its component columns have names then add them to
314      * nameGen.
315      *
316      * @throws IllegalArgumentException if any names are invalid
317      */

318     public static void addColumnNames(String JavaDoc tableName, JdbcColumn[] cols,
319             JdbcNameGenerator namegen) throws IllegalArgumentException JavaDoc {
320         for (int i = 0; i < cols.length; i++) {
321             cols[i].addColumnNames(tableName, namegen);
322         }
323     }
324
325     /**
326      * Get the names of all the simple columns in an array of columns.
327      */

328     public static String JavaDoc[] getColumnNames(JdbcColumn[] cols) {
329         if (cols == null) {
330             return new String JavaDoc[0];
331         }
332         int n = cols.length;
333         String JavaDoc[] ans = new String JavaDoc[n];
334         for (int i = 0; i < n; i++) {
335             ans[i] = cols[i].name;
336         }
337         return ans;
338     }
339
340     /**
341      * Set the names of all the simple columns in an array of columns.
342      */

343     public static void setColumnNames(JdbcColumn[] cols, String JavaDoc[] names) {
344         if (cols == null) {
345             return;
346         }
347         int n = cols.length;
348         for (int i = 0; i < n; i++) {
349             cols[i].name = names[i];
350         }
351     }
352
353     /**
354      * Format an array of columns as a comma separated String of the names.
355      */

356     public static String JavaDoc toNameString(JdbcColumn[] cols) {
357         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
358         int len = cols.length;
359         for (int i = 0; i < len; i++) {
360             if (i > 0) s.append(", ");
361             s.append(cols[i].name);
362         }
363         return s.toString();
364     }
365
366     /**
367      * Set the nulls value for all of our columns.
368      */

369     public void setNulls(boolean nulls) {
370         this.nulls = nulls;
371     }
372
373     /**
374      * Get a 'cola = ? [and colb = ?]' expression for an array of simple
375      * columns from se.
376      */

377     public static SqlExp createEqualsParamExp(JdbcColumn[] scols, SelectExp se) {
378         int nc = scols.length;
379         if (nc == 1) {
380             return scols[0].createEqualsParamExp(se);
381         } else {
382             SqlExp list = scols[0].createEqualsParamExp(se);
383             SqlExp pos = list;
384             for (int i = 1; i < nc; i++) {
385                 pos = pos.next = scols[i].createEqualsParamExp(se);
386             }
387             return new AndExp(list);
388         }
389     }
390
391     public static InExp createInParamExp(JdbcColumn[] scols, SelectExp se,
392             int size) {
393         if (scols.length > 1) {
394             throw BindingSupportImpl.getInstance().notImplemented(
395                     "'In' expressions is not support on multi-pk classes");
396         }
397
398         ColumnExp columnExp = new ColumnExp(scols[0], se, null);
399         ParamExp rootParam = new ParamExp(scols[0].jdbcType, null);
400         columnExp.next = rootParam;
401         for (int i = 0; i < (size - 1); i++) {
402             rootParam.next = new ParamExp(scols[0].jdbcType, null);
403             rootParam = (ParamExp)rootParam.next;
404         }
405         return new InExp(columnExp);
406     }
407
408     /**
409      * /**
410      * Append a 'cola = ? [and colb = ?' string for an array of simple cols
411      * to s.
412      */

413     public static void appendEqualsParam(CharBuf s, JdbcColumn[] cols,
414             SqlDriver driver) {
415         int nc = cols.length;
416         JdbcColumn sc = cols[0];
417         s.append(sc.name);
418         s.append(' ');
419         s.append('=');
420         s.append(' ');
421         driver.appendWhereParam(s, sc);
422         for (int i = 1; i < nc; i++) {
423             s.append(" AND ");
424             sc = cols[i];
425             s.append(sc.name);
426             s.append(' ');
427             s.append('=');
428             s.append(' ');
429             driver.appendWhereParam(s, sc);
430         }
431     }
432
433     /**
434      * Get the value of this column from a ResultSet.
435      */

436     public Object JavaDoc get(ResultSet JavaDoc rs, int index) throws SQLException JavaDoc {
437         if (converter == null) {
438             return JdbcUtils.get(rs, index, javaTypeCode, scale);
439         } else {
440             return converter.get(rs, index, this);
441         }
442     }
443
444
445
446     /**
447      * Set a value for this column on a PreparedStatement.
448      */

449     public void set(PreparedStatement JavaDoc ps, int index, Object JavaDoc value)
450             throws SQLException JavaDoc {
451         if (converter == null) {
452             JdbcUtils.set(ps, index, value, javaTypeCode, jdbcType);
453         } else {
454             converter.set(ps, index, this, value);
455         }
456     }
457
458     /**
459      * Set a value for this column on a PreparedStatement.
460      */

461     public void set(PreparedStatement JavaDoc ps, int index, int value)
462             throws SQLException JavaDoc {
463         if (converter == null) {
464             JdbcUtils.set(ps, index, value, javaTypeCode, jdbcType);
465         } else {
466             converter.set(ps, index, this, value);
467         }
468     }
469
470     /**
471      * Get the value of this column from the ResultSet as an int.
472      */

473     public int getInt(ResultSet JavaDoc rs, int index) throws SQLException JavaDoc {
474         if (converter == null) {
475             return rs.getInt(index);
476         } else {
477             return ((Integer JavaDoc)converter.get(rs, index, this)).intValue();
478         }
479     }
480
481     /**
482      * Append a comma list of our column name(s) to s.
483      */

484     public void appendNames(CharBuf s) {
485         s.append(name);
486     }
487
488     /**
489      * Append a comma param list to s (e.g. ?, ?).
490      */

491     public void appendParams(CharBuf s) {
492         s.append('?');
493     }
494
495     /**
496      * Create a col = ? expression.
497      */

498     public SqlExp createEqualsParamExp(SelectExp se) {
499         return new BinaryOpExp(new ColumnExp(this, se, null),
500                 BinaryOpExp.EQUAL,
501                 new ParamExp(jdbcType, null));
502     }
503
504     /**
505      * Must this column be included in update and insert statements?
506      */

507     public boolean isForUpdate() {
508         return !shared;
509     }
510
511     public String JavaDoc toString() {
512         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
513         s.append(javaType == null ? "(null javaType)" : javaType.getName());
514         s.append(' ');
515         s.append(name);
516         s.append(' ');
517         s.append(sqlType);
518         s.append('[');
519         s.append(JdbcTypes.toString(jdbcType));
520         s.append(']');
521         if (length != 0 || scale != 0) {
522             s.append('(');
523             s.append(length);
524             if (scale != 0) {
525                 s.append(',');
526                 s.append(scale);
527             }
528             s.append(')');
529         }
530         s.append(nulls ? " null" : " not null");
531         if (refField != null) {
532             s.append(" ref ");
533             s.append(refField);
534         }
535         s.append(shared ? " shared" : "");
536         s.append(autoinc ? " autoinc" : "");
537         if (Debug.DEBUG) {
538             s.append(" 0x");
539             s.append(Integer.toHexString(System.identityHashCode(this)));
540         }
541         return s.toString();
542     }
543
544     public void setShared(boolean shared) {
545         this.shared = shared;
546     }
547
548     public String JavaDoc getShortName() {
549         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc(name);
550         buffer.append(" ");
551         buffer.append(sqlType);
552         if (length > 0) {
553             buffer.append("(");
554             buffer.append(length);
555             buffer.append(")");
556         }
557         return buffer.toString();
558     }
559
560     public String JavaDoc getTypeString() {
561         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
562         buffer.append(sqlType);
563         if (length > 0) {
564             buffer.append("(");
565             buffer.append(length);
566             buffer.append(")");
567         }
568         return buffer.toString();
569     }
570
571     /**
572      * Create a Literal Exp for a classIdColumn
573      */

574     public LiteralExp createClassIdLiteralExp(Object JavaDoc val) {
575         return new LiteralExp(JdbcTypes.getLiteralType(javaTypeCode),
576                 val.toString());
577     }
578
579     public boolean equals(Object JavaDoc o) {
580         if (this == o) return true;
581         if (!(o instanceof JdbcColumn)) return false;
582
583         final JdbcColumn jdbcColumn = (JdbcColumn)o;
584
585         if (name != null ? !name.equals(jdbcColumn.name) : jdbcColumn.name != null) return false;
586         if (table != null ? !table.equals(jdbcColumn.table) : jdbcColumn.table != null) return false;
587
588         return true;
589     }
590
591     public int hashCode() {
592         int result;
593         result = (table != null ? table.hashCode() : 0);
594         result = 29 * result + (name != null ? name.hashCode() : 0);
595         return result;
596     }
597 }
598
Popular Tags