KickJava   Java API By Example, From Geeks To Geeks.

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


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.metadata.MDStatics;
15 import com.versant.core.metadata.ClassMetaData;
16 import com.versant.core.metadata.ClassIdTranslator;
17 import com.versant.core.metadata.parser.JdoField;
18 import com.versant.core.common.OID;
19 import com.versant.core.jdbc.sql.JdbcNameGenerator;
20 import com.versant.core.jdbc.sql.SqlDriver;
21 import com.versant.core.jdbc.sql.exp.*;
22 import com.versant.core.jdbc.JdbcMetaDataBuilder;
23 import com.versant.core.jdbc.JdbcPolyRefMetaDataBuilder;
24 import com.versant.core.jdbc.JdbcOID;
25 import com.versant.core.util.CharBuf;
26 import com.versant.core.common.State;
27
28 import java.util.ArrayList JavaDoc;
29 import java.io.PrintStream JavaDoc;
30 import java.sql.PreparedStatement JavaDoc;
31 import java.sql.SQLException JavaDoc;
32 import java.sql.ResultSet JavaDoc;
33
34 /**
35  * A field that is a polymorphic reference to any other PC class (e.g. an
36  * Object or interface reference).
37  */

38 public class JdbcPolyRefField extends JdbcField {
39
40     /**
41      * The column used to hold the classId value identifying the class (and
42      * hence table) that is being referenced.
43      * @see #cols
44      */

45     public JdbcColumn classIdCol;
46     /**
47      * The columns used to store the classId and the primary key of the
48      * referenced (target) tables.
49      * @see #cols
50      */

51     public JdbcColumn[] refCols;
52     /**
53      * @keep
54      * The classIdCol at index 0 and pkCols.
55      */

56     public JdbcColumn[] cols;
57
58     private ClassIdTranslator classIdTranslator;
59     private int literalType;
60
61     public String JavaDoc toString() {
62         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
63         s.append(super.toString());
64         switch (useJoin) {
65             case USE_JOIN_INNER: s.append(" INNER");
66             case USE_JOIN_OUTER: s.append(" OUTER");
67         }
68         return s.toString();
69     }
70
71     /**
72      * Complete our meta data except for column names.
73      */

74     public void processMetaData(JdoField context, JdbcMetaDataBuilder mdb) {
75
76         JdbcPolyRefMetaDataBuilder rdb = new JdbcPolyRefMetaDataBuilder(mdb,
77                 context, fmd.name,
78                 fmd.jdoField == null ? null : fmd.jdoField.extensions, this);
79
80         classIdCol = rdb.getClassIdCol();
81         refCols = rdb.getPkCols();
82         cols = rdb.getCols();
83
84         int nc = cols.length;
85         for (int i = 0; i < nc; i++) cols[i].comment = fmd.getCommentName();
86
87         boolean nulls = fmd.nullValue != MDStatics.NULL_VALUE_EXCEPTION;
88         for (int i = 0; i < nc; i++) cols[i].nulls = nulls;
89
90         // include this in the where clause for changed locking only if all
91
// columns support equalityTest
92
includeForChangedLocking = true;
93         for (int i = 0; i < nc; i++) {
94             if (!cols[i].equalityTest) {
95                 includeForChangedLocking = false;
96                 break;
97             }
98         }
99
100         useJoin = JdbcRefField.USE_JOIN_NO;
101
102         literalType = JdbcTypes.getLiteralType(classIdCol.jdbcType);
103         classIdTranslator = rdb.getClassIdTranslator();
104     }
105
106     /**
107      * Set the table field on all our main table columns.
108      */

109     public void setMainTable(JdbcTable table) {
110         super.setMainTable(table);
111         for (int i = 0; i < cols.length; i++) cols[i].setTable(table);
112     }
113
114     /**
115      * Init the mainTableCols field to all our main table columns.
116      */

117     public void initMainTableCols() {
118         mainTableCols = cols;
119         super.initMainTableCols();
120     }
121
122     /**
123      * Flatten all of this fields main table columns to a.
124      */

125     public void addMainTableCols(ArrayList JavaDoc a) {
126         int n = cols.length;
127         for (int i = 0; i < n; i++) a.add(cols[i]);
128     }
129
130     /**
131      * Make sure all of this fields main table columns have names.
132      */

133     public void nameColumns(String JavaDoc tableName, JdbcNameGenerator nameGen) {
134         // extract the current names of the columns
135
String JavaDoc[] names = new String JavaDoc[cols.length];
136         for (int i = 0; i < cols.length; i++) names[i] = cols[i].name;
137
138         // generate the names for the unnamed columns
139
nameGen.generatePolyRefFieldColumnNames(tableName, fmd.name, names);
140
141         // set our column names
142
for (int i = 0; i < cols.length; i++) cols[i].name = names[i];
143     }
144
145     public void dump(PrintStream JavaDoc out, String JavaDoc indent) {
146         super.dump(out, indent);
147         String JavaDoc is = indent + " ";
148         if (cols != null) {
149             out.println(is + cols.length + " cols(s)");
150             for (int i = 0; i < cols.length; i++) {
151                 out.println(is + "[" + i + "] " + cols[i]);
152             }
153         }
154     }
155
156     /**
157      * Append part of an update statement for us to s (e.g col = ?).
158      */

159     public boolean appendUpdate(CharBuf s, State state) {
160         int nc = mainTableColsForUpdate.length;
161         s.append(mainTableColsForUpdate[0].name);
162         s.append("=?");
163         for (int i = 1; i < nc; i++) {
164             s.append(", ");
165             s.append(mainTableColsForUpdate[i].name);
166             s.append("=?");
167         }
168         return false;
169     }
170
171     /**
172      * Append part of a where clause for us to s (e.g cola = ? and colb = ?).
173      * This is used for generating the where clause for changed locking.
174      */

175     public void appendWhere(CharBuf s, SqlDriver sqlDriver) {
176         int nc = mainTableColsForUpdate.length;
177         JdbcColumn c = mainTableColsForUpdate[0];
178         s.append(c.name);
179         s.append('=');
180         sqlDriver.appendWhereParam(s, c);
181         for (int i = 1; i < nc; i++) {
182             c = mainTableColsForUpdate[i];
183             s.append(" and ");
184             s.append(c.name);
185             s.append('=');
186             sqlDriver.appendWhereParam(s, c);
187         }
188     }
189
190     /**
191      * Append part of a is null where clause for us to s (e.g cola is null
192      * and colb is null).
193      * This is used for generating the where clause for changed locking.
194      */

195     public void appendWhereIsNull(CharBuf s, SqlDriver sqlDriver) {
196         int nc = mainTableColsForUpdate.length;
197         JdbcColumn c = mainTableColsForUpdate[0];
198         s.append(c.name);
199         s.append(" is null");
200         for (int i = 1; i < nc; i++) {
201             c = mainTableColsForUpdate[i];
202             s.append(" and ");
203             s.append(c.name);
204             s.append(" is null");
205         }
206     }
207
208     /**
209      * Append part of the insert list for us to s (e.g. cola, colb)).
210      */

211     public void appendInsertColumnList(CharBuf s) {
212         int nc = mainTableColsForUpdate.length;
213         s.append(mainTableColsForUpdate[0].name);
214         for (int i = 1; i < nc; i++) {
215             s.append(", ");
216             s.append(mainTableColsForUpdate[i].name);
217         }
218     }
219
220     /**
221      * Append part of the insert value list for us to s (e.g. ?, ?)). This
222      * must return true if a replacable parameter was <b>not</b> added (e.g.
223      * columns using Oracle LOBs which put in empty_clob() or whatever).
224      */

225     public boolean appendInsertValueList(CharBuf s, State state) {
226         s.append('?');
227         int nc = mainTableColsForUpdate.length;
228         for (int i = 1; i < nc; i++) s.append(", ?");
229         return false;
230     }
231
232     /**
233      * Convert this field into a list of ColumnExp's or null if this is
234      * not possible.
235      */

236     public ColumnExp toColumnExp(SelectExp se, boolean joinToSuper) {
237         if (joinToSuper) se = SelectExp.createJoinToSuperTable(se, this);
238
239         ColumnExp ans = new ColumnExp(cols[0], se, this);
240         SqlExp e = ans;
241         int nc = cols.length;
242         for (int i = 1; i < nc; i++) {
243             e = e.next = new ColumnExp(cols[i], se, this);
244         }
245         return ans;
246     }
247
248     /**
249      * Convert this field into a list of ColumnExp's to be compared to
250      * a null literal. This should only include non-shared columns i.e.
251      * columns that are updated. If all columns are shared then all should
252      * be included.
253      */

254     public ColumnExp toColumnExpForNullLiteralCompare(SelectExp se) {
255         se = SelectExp.createJoinToSuperTable(se, this);
256         
257         if (mainTableColsForUpdate == null) return toColumnExp(se, true);
258         ColumnExp ans = new ColumnExp(mainTableColsForUpdate[0], se, this);
259         SqlExp e = ans;
260         int nc = mainTableColsForUpdate.length;
261         for (int i = 1; i < nc; i++) {
262             e = e.next = new ColumnExp(mainTableColsForUpdate[i], se, this);
263         }
264         return ans;
265     }
266
267     /**
268      * Set this field on a PreparedStatement. This is used to set parameters
269      * for queries.
270      * @return Index of the parameter after the last one we set in ps
271      */

272     public int setQueryParam(PreparedStatement JavaDoc ps, int firstParam, Object JavaDoc value)
273             throws SQLException JavaDoc {
274         OID oid = (OID)value;
275         if (oid != null) {
276             ClassMetaData target = oid.getClassMetaData();
277             if (classIdTranslator.isStringClassIds()) {
278                 String JavaDoc id = classIdTranslator.getStringClassIdForClass(target);
279                 classIdCol.set(ps, firstParam, id);
280             } else {
281                 int id = classIdTranslator.getIntClassIdForClass(target);
282                 classIdCol.set(ps, firstParam, id);
283             }
284             firstParam = ((JdbcOID)oid).setParams(ps, ++firstParam);
285         } else {
286             int nc = cols.length;
287             for (int i = 0; i < nc; i++) {
288                 ps.setNull(firstParam++, cols[i].jdbcType);
289             }
290         }
291         return firstParam;
292     }
293
294     /**
295      * Set this field on a PS for inserting or updating a row.
296      * @param firstParam Index of first parameter to set
297      * @return Index of next parameter to be set on ps
298      */

299     public int setData(PreparedStatement JavaDoc ps, int firstParam, OID oid)
300             throws SQLException JavaDoc {
301         if (oid != null) {
302             if (classIdCol.isForUpdate()) {
303                 ClassMetaData target = oid.getClassMetaData();
304                 if (classIdTranslator.isStringClassIds()) {
305                     String JavaDoc id = classIdTranslator.getStringClassIdForClass(target);
306                     classIdCol.set(ps, firstParam++, id);
307                 } else {
308                     int id = classIdTranslator.getIntClassIdForClass(target);
309                     classIdCol.set(ps, firstParam++, id);
310                 }
311             }
312             firstParam = ((JdbcOID)oid).setParams(ps, firstParam, refCols);
313         } else {
314             JdbcColumn[] cols = mainTableCols;
315             int nc = cols.length;
316             for (int i = 0; i < nc; i++) {
317                 JdbcColumn col = cols[i];
318                 if (col.isForUpdate()) {
319                     ps.setNull(firstParam++, col.jdbcType);
320                 }
321             }
322         }
323         return firstParam;
324     }
325
326     /**
327      * Get this field from a ResultSet starting at index firstCol.
328      */

329     public OID getData(ResultSet JavaDoc rs, int firstCol) throws SQLException JavaDoc {
330         ClassMetaData target;
331         if (classIdTranslator.isStringClassIds()) {
332             String JavaDoc id = (String JavaDoc)classIdCol.get(rs, firstCol);
333             if (id == null) return null;
334             target = classIdTranslator.getClassForStringClassId(id);
335         } else {
336             int id = classIdCol.getInt(rs, firstCol);
337             if (id == 0) return null;
338             target = classIdTranslator.getClassForIntClassId(id);
339         }
340         JdbcOID oid = (JdbcOID)target.createOID(target.pcSubclasses == null);
341         if (oid.copyKeyFields(rs, firstCol + 1)) return oid;
342         else return null;
343     }
344
345     /**
346      * Create an expression to compare our classIdCol to the correct class-id
347      * value for target.
348      */

349     public SqlExp createClassIdMatchExp(SelectExp root, ClassMetaData target) {
350         SqlExp left = classIdCol.toSqlExp(root);
351         String JavaDoc id = classIdTranslator.isStringClassIds()
352                 ? classIdTranslator.getStringClassIdForClass(target)
353                 : Integer.toString(classIdTranslator.getIntClassIdForClass(target));
354         LiteralExp right = new LiteralExp(literalType, id);
355         return new BinaryOpExp(left, BinaryOpExp.EQUAL, right);
356     }
357
358 }
359
360
361
Popular Tags