KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > jdbc > JdbcMetaData


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.jdbc;
31
32 import com.caucho.util.L10N;
33 import com.caucho.util.Log;
34
35 import javax.sql.DataSource JavaDoc;
36 import java.sql.Connection JavaDoc;
37 import java.sql.DatabaseMetaData JavaDoc;
38 import java.sql.ResultSet JavaDoc;
39 import java.sql.SQLException JavaDoc;
40 import java.sql.Types JavaDoc;
41 import java.util.logging.Level JavaDoc;
42 import java.util.logging.Logger JavaDoc;
43
44 /**
45  * Abstract way of grabbing data from the JDBC connection.
46  */

47 public class JdbcMetaData {
48   private static final L10N L = new L10N(JdbcMetaData.class);
49   private static final Logger JavaDoc log = Log.open(JdbcMetaData.class);
50
51   private DataSource JavaDoc _ds;
52
53   /**
54    * Create a new JDBC backing store.
55    */

56   protected JdbcMetaData(DataSource JavaDoc ds)
57   {
58     _ds = ds;
59   }
60
61   /**
62    * Create based on the connection.
63    */

64   public static JdbcMetaData create(DataSource JavaDoc ds)
65   {
66     Connection JavaDoc conn = null;
67
68     try {
69       conn = ds.getConnection();
70
71       DatabaseMetaData JavaDoc md = conn.getMetaData();
72
73       String JavaDoc name = md.getDatabaseProductName();
74
75       log.fine(L.l("Database '{0}' metadata.", name));
76
77       if ("oracle".equalsIgnoreCase(name))
78     return new OracleMetaData(ds);
79       else if ("resin".equalsIgnoreCase(name))
80     return new ResinMetaData(ds);
81       else if ("postgres".equalsIgnoreCase(name) ||
82            "PostgreSQL".equalsIgnoreCase(name))
83     return new PostgresMetaData(ds);
84       else if ("mysql".equalsIgnoreCase(name))
85     return new MysqlMetaData(ds);
86       else if ("Microsoft SQL Server".equalsIgnoreCase(name))
87     return new SqlServerMetaData(ds);
88       else {
89     log.fine(name + " is an unknown database type");
90     return new JdbcMetaData(ds);
91       }
92     } catch (SQLException JavaDoc e) {
93       log.log(Level.FINE, e.toString(), e);
94       return new JdbcMetaData(ds);
95     } finally {
96       try {
97     if (conn != null) conn.close();
98       } catch (SQLException JavaDoc e) {
99       }
100     }
101   }
102
103   /**
104    * Returns the database name.
105    */

106   public String JavaDoc getDatabaseName()
107   {
108     Connection JavaDoc conn = null;
109
110     try {
111       conn = getConnection();
112
113       DatabaseMetaData JavaDoc md = conn.getMetaData();
114
115       return md.getDatabaseProductName();
116     } catch (SQLException JavaDoc e) {
117       log.log(Level.WARNING, e.toString(), e);
118       return "unknown";
119     } finally {
120       try {
121     if (conn != null) conn.close();
122       } catch (SQLException JavaDoc e) {
123       }
124     }
125   }
126
127   /**
128    * Returns the blob type.
129    */

130   public String JavaDoc getBlobType()
131   {
132     Connection JavaDoc conn = null;
133
134     try {
135       conn = getConnection();
136
137       DatabaseMetaData JavaDoc md = conn.getMetaData();
138       ResultSet JavaDoc rs;
139
140       rs = md.getTypeInfo();
141       try {
142     while (rs.next()) {
143       if (rs.getShort("DATA_TYPE") == Types.BLOB) {
144         return rs.getString("TYPE_NAME");
145       }
146     }
147       } finally {
148     rs.close();
149       }
150
151       rs = md.getTypeInfo();
152       try {
153         while (rs.next()) {
154           int dataType = rs.getShort("DATA_TYPE");
155
156           if (rs.getShort("DATA_TYPE") == Types.LONGVARBINARY) {
157             return rs.getString("TYPE_NAME");
158           }
159         }
160       } finally {
161         rs.close();
162       }
163
164       rs = md.getTypeInfo();
165       try {
166         while (rs.next()) {
167           if (rs.getShort("DATA_TYPE") == Types.BINARY) {
168             return rs.getString("TYPE_NAME");
169           }
170         }
171       } finally {
172         rs.close();
173       }
174
175       rs = md.getTypeInfo();
176       try {
177     while (rs.next()) {
178       if (rs.getShort("DATA_TYPE") == Types.VARBINARY) {
179         return rs.getString("TYPE_NAME");
180       }
181     }
182       } finally {
183     rs.close();
184       }
185     } catch (SQLException JavaDoc e) {
186       log.log(Level.FINE, e.toString(), e);
187     } finally {
188       try {
189     if (conn != null)
190       conn.close();
191       } catch (Exception JavaDoc e) {
192       }
193     }
194
195     return null;
196   }
197
198   /**
199    * True if blobs must be truncated on delete.
200    */

201   public boolean isTruncateBlobBeforeDelete()
202   {
203     return false;
204   }
205
206   /**
207    * True if the generated ketys is supported
208    */

209   public boolean supportsGetGeneratedKeys()
210   {
211     try {
212       Connection JavaDoc conn = getConnection();
213
214       try {
215         DatabaseMetaData JavaDoc metaData = conn.getMetaData();
216
217     return metaData.supportsGetGeneratedKeys();
218       } finally {
219         conn.close();
220       }
221     } catch (SQLException JavaDoc e) {
222       throw new RuntimeException JavaDoc(e);
223     }
224   }
225
226   /**
227    * Returns the long type.
228    */

229   public String JavaDoc getLongType()
230   {
231     Connection JavaDoc conn = null;
232
233     try {
234       conn = getConnection();
235
236       DatabaseMetaData JavaDoc md = conn.getMetaData();
237       ResultSet JavaDoc rs;
238
239       rs = md.getTypeInfo();
240       try {
241     while (rs.next()) {
242       if (rs.getShort("DATA_TYPE") == Types.BIGINT) {
243         return rs.getString("TYPE_NAME");
244       }
245     }
246       } finally {
247     rs.close();
248       }
249     } catch (SQLException JavaDoc e) {
250       log.log(Level.FINE, e.toString(), e);
251     } finally {
252       try {
253     if (conn != null) conn.close();
254       } catch (SQLException JavaDoc e) {
255       }
256     }
257
258     return null;
259   }
260
261   /**
262    * Returns true if identity is supported.
263    */

264   public boolean supportsIdentity()
265   {
266     return false;
267   }
268
269   /**
270    * Returns the identity property
271    */

272   public String JavaDoc createIdentitySQL(String JavaDoc sqlType)
273   {
274     throw new UnsupportedOperationException JavaDoc(getClass().getName());
275   }
276
277   /**
278    * Returns true if sequences are supported.
279    */

280   public boolean supportsSequences()
281   {
282     return false;
283   }
284
285   /**
286    * Returns a sequence select expression.
287    */

288   public String JavaDoc createSequenceSQL(String JavaDoc name, int size)
289   {
290     throw new UnsupportedOperationException JavaDoc(getClass().getName());
291   }
292
293   /**
294    * Returns a sequence select expression.
295    */

296   public String JavaDoc selectSequenceSQL(String JavaDoc name)
297   {
298     throw new UnsupportedOperationException JavaDoc(getClass().getName());
299   }
300
301   /**
302    * Returns a sequence select expression.
303    */

304   public String JavaDoc testSequenceSQL(String JavaDoc name)
305   {
306     return selectSequenceSQL(name) + " WHERE 1=0";
307   }
308
309   /**
310    * Returns the code to test for a boolean value for a term.
311    */

312   public String JavaDoc generateBoolean(String JavaDoc term)
313   {
314     return term;
315   }
316
317   /**
318    * Returns a limit.
319    */

320   public String JavaDoc limit(String JavaDoc sql, int max)
321   {
322     return sql;
323   }
324   /**
325    * New version to Return SQL for the table with the given
326    * SQL type. Takes, length, precision and scale.
327    */

328   public String JavaDoc getCreateColumnSQL(int sqlType, int length, int precision, int scale)
329   {
330     String JavaDoc type = null;
331
332     switch (sqlType) {
333     case Types.BOOLEAN:
334       type = getCreateColumnSQLImpl(sqlType, length, precision, scale);
335       if (type == null)
336         type = getCreateColumnSQLImpl(Types.BIT, length, precision, scale);
337       break;
338
339     case Types.DATE:
340       type = getCreateColumnSQLImpl(sqlType, length, precision, scale);
341       if (type == null)
342     type = getCreateColumnSQLImpl(Types.TIMESTAMP, length, precision, scale);
343       break;
344
345     case Types.TIME:
346       type = getCreateColumnSQLImpl(sqlType, length, precision, scale);
347       if (type == null)
348     type = getCreateColumnSQLImpl(Types.TIMESTAMP, length, precision, scale);
349       break;
350
351     case Types.DOUBLE:
352       type = getCreateColumnSQLImpl(Types.DOUBLE, length, precision, scale);
353       break;
354
355     case Types.NUMERIC:
356         type = getCreateColumnSQLImpl(Types.NUMERIC, length, precision, scale);
357         break;
358
359     default:
360       type = getCreateColumnSQLImpl(sqlType, length, precision, scale);
361       break;
362     }
363
364     if (type == null)
365       type = getDefaultCreateTableSQL(sqlType, length, precision, scale);
366
367     return type;
368   }
369
370   /**
371    * Returns the SQL for the table with the given SQL type.
372    */

373   protected String JavaDoc getCreateColumnSQLImpl(int sqlType, int length, int precision, int scale)
374   {
375     Connection JavaDoc conn = null;
376
377     try {
378       conn = getConnection();
379
380       DatabaseMetaData JavaDoc md = conn.getMetaData();
381       ResultSet JavaDoc rs;
382
383       rs = md.getTypeInfo();
384
385       try {
386     while (rs.next()) {
387       if (rs.getShort("DATA_TYPE") == sqlType) {
388         String JavaDoc typeName = rs.getString("TYPE_NAME");
389         String JavaDoc params = rs.getString("CREATE_PARAMS");
390
391         if (params == null || params.equals(""))
392           return typeName;
393         else if (params.startsWith("(M)")) {
394           if (length > 0)
395         return typeName + "(" + length + ")";
396           else
397         return typeName;
398         }
399         else if (params.startsWith("(M,D)") || params.equals("precision,scale")) {
400               if (precision > 0) {
401                 typeName += "(" + precision;
402                 if (scale > 0) {
403                   typeName += "," + scale;
404                 }
405                 typeName += ")";
406               }
407           return typeName;
408         }
409         else if (params.startsWith("(")) {
410           int tail = params.indexOf(')');
411
412           if (tail > 0) {
413         String JavaDoc value = params.substring(1, tail);
414         boolean isConstant = true;
415
416         for (int i = 0; i < value.length(); i++) {
417           if (value.charAt(i) >= 'a' && value.charAt(i) <= 'z')
418             isConstant = false;
419           else if (value.charAt(i) >= 'A' && value.charAt(i) <= 'Z')
420             isConstant = false;
421         }
422
423         if (isConstant)
424           return typeName + "(" + value + ")";
425           }
426
427           return typeName;
428         }
429         else {
430           return typeName;
431         }
432       }
433     }
434       } finally {
435     rs.close();
436       }
437     } catch (Throwable JavaDoc e) {
438       log.log(Level.FINE, e.toString(), e);
439     } finally {
440       try {
441     if (conn != null)
442       conn.close();
443       } catch (Exception JavaDoc e) {
444       }
445     }
446
447     return null;
448   }
449
450   protected String JavaDoc getDefaultCreateTableSQL(int sqlType, int length, int precision, int scale)
451   {
452     switch (sqlType) {
453     case java.sql.Types.BOOLEAN:
454       return "CHAR";
455     case java.sql.Types.BIT:
456     case java.sql.Types.TINYINT:
457     case java.sql.Types.SMALLINT:
458     case java.sql.Types.INTEGER:
459     case java.sql.Types.BIGINT:
460       return "INTEGER";
461     case java.sql.Types.NUMERIC:
462     case java.sql.Types.DECIMAL:
463       String JavaDoc typeString = "NUMERIC";
464       if (precision > 0) {
465         typeString += "(" + precision;
466         if (scale > 0) {
467           typeString += "," + scale;
468         }
469         typeString += ")";
470       }
471       return typeString;
472     case java.sql.Types.DOUBLE:
473     case java.sql.Types.FLOAT:
474       return "DOUBLE";
475     case java.sql.Types.CHAR:
476       return "CHAR";
477     case java.sql.Types.DATE:
478     case java.sql.Types.TIME:
479     case java.sql.Types.TIMESTAMP:
480         return "TIMESTAMP";
481     default:
482       return "VARCHAR(" + length + ")";
483     }
484   }
485
486   /**
487    * Returns a connection.
488    */

489   protected Connection JavaDoc getConnection()
490     throws SQLException JavaDoc
491   {
492     return _ds.getConnection();
493   }
494 }
495
Popular Tags