Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/mysql/jdbc/ResultSetMetaData.java


1   /*
2    Copyright (C) 2002-2004 MySQL AB
3   
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of version 2 of the GNU General Public License as
6    published by the Free Software Foundation.
7    
8   
9    There are special exceptions to the terms and conditions of the GPL 
10   as it is applied to this software. View the full text of the 
11   exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
12   software distribution.
13  
14   This program 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.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23   */
24  package com.mysql.jdbc;
25  
26  import java.sql.SQLException;
27  import java.sql.Types;
28  
29  
30  /**
31   * A ResultSetMetaData object can be used to find out about the types and
32   * properties of the columns in a ResultSet
33   *
34   * @see java.sql.ResultSetMetaData
35   * @author Mark Matthews
36   * @version $Id: ResultSetMetaData.java,v 1.12.2.12 2004/09/13 18:03:37 mmatthew Exp $
37   */
38  public class ResultSetMetaData implements java.sql.ResultSetMetaData {
39      Field[] fields;
40  
41      /**
42              * Initialise for a result with a tuple set and
43       * a field descriptor set
44       *
45       * @param fields the array of field descriptors
46  
47       */
48      public ResultSetMetaData(Field[] fields) {
49          this.fields = fields;
50      }
51  
52      /**
53       * Is the column automatically numbered (and thus read-only)
54       *
55       * MySQL Auto-increment columns are not read only,
56       * so to conform to the spec, this method returns false.
57       *
58       * @param column the first column is 1, the second is 2...
59       * @return true if so
60       * @throws java.sql.SQLException if a database access error occurs
61       */
62      public boolean isAutoIncrement(int column) throws java.sql.SQLException {
63          Field f = getField(column);
64  
65          return f.isAutoIncrement();
66      }
67  
68      /**
69       * Does a column's case matter? ASSUMPTION: Any field that is
70       * not obviously case insensitive is assumed to be case sensitive
71       *
72       * @param column the first column is 1, the second is 2...
73       * @return true if so
74       * @throws java.sql.SQLException if a database access error occurs
75       */
76      public boolean isCaseSensitive(int column) throws java.sql.SQLException {
77        Field field = getField(column);
78        
79          int sqlType = field.getSQLType();
80  
81          switch (sqlType) {
82          case Types.BIT:
83          case Types.TINYINT:
84          case Types.SMALLINT:
85          case Types.INTEGER:
86          case Types.BIGINT:
87          case Types.FLOAT:
88          case Types.REAL:
89          case Types.DOUBLE:
90          case Types.DATE:
91          case Types.TIME:
92          case Types.TIMESTAMP:
93              return false;
94            
95          case Types.CHAR:
96          case Types.VARCHAR:
97            
98            return field.isBinary();
99                  
100         default:
101             return true;
102         }
103     }
104 
105     /**
106      * What's a column's table's catalog name?
107      *
108      * @param column the first column is 1, the second is 2...
109      * @return catalog name, or "" if not applicable
110      * @throws java.sql.SQLException if a database access error occurs
111      */
112     public String getCatalogName(int column) throws java.sql.SQLException {
113         Field f = getField(column);
114 
115         String database = f.getDatabaseName();
116 
117         return (database == null) ? "" : database;
118     }
119 
120     //--------------------------JDBC 2.0-----------------------------------
121 
122     /**
123      * JDBC 2.0
124      *
125      * <p>Return the fully qualified name of the Java class whose instances
126      * are manufactured if ResultSet.getObject() is called to retrieve a value
127      * from the column.  ResultSet.getObject() may return a subClass of the
128      * class returned by this method.
129      *
130      * @param column the column number to retrieve information for
131      * @return the fully qualified name of the Java class whose instances
132      * are manufactured if ResultSet.getObject() is called to retrieve a value
133      * from the column.
134      *
135      * @throws SQLException if an error occurs
136      */
137     public String getColumnClassName(int column) throws SQLException {
138         Field f = getField(column);
139 
140         // From JDBC-3.0 spec
141         //
142         //  JDBC Type Java Object Type
143         //
144         // CHAR       String
145         // VARCHAR       String
146         // LONGVARCHAR     String
147         // NUMERIC       java.math.BigDecimal
148         // DECIMAL       java.math.BigDecimal
149         // BIT         Boolean
150         // BOOLEAN       Boolean
151         // TINYINT       Integer
152         // SMALLINT     Integer
153         // INTEGER       Integer
154         // BIGINT       Long
155         // REAL       Float
156         // FLOAT       Double
157         // DOUBLE       Double
158         // BINARY       byte[]
159         // VARBINARY     byte[]
160         // LONGVARBINARY   byte[]
161         // DATE       java.sql.Date
162         // TIME       java.sql.Time
163         // TIMESTAMP     java.sql.Timestamp
164         // DISTINCT     Object type of underlying type
165         // CLOB       Clob
166         // BLOB       Blob
167         // ARRAY       Array
168         // STRUCT       Struct or SQLData
169         // REF         Ref
170         // DATALINK     java.net.URL
171         // JAVA_OBJECT     underlying Java class
172          
173         switch (f.getSQLType()) {
174         case Types.BIT:
175         case Types.BOOLEAN:
176             return "java.lang.Boolean";
177 
178         case Types.TINYINT:
179 
180             return "java.lang.Integer";
181            
182         case Types.SMALLINT:
183 
184             return "java.lang.Integer";
185 
186         case Types.INTEGER:
187 
188             if (f.isUnsigned()) {
189                 return "java.lang.Long";
190             } else {
191                 return "java.lang.Integer";
192             }
193 
194         case Types.BIGINT:
195           
196             return "java.lang.Long";
197 
198         case Types.DECIMAL:
199         case Types.NUMERIC:
200           
201             return "java.math.BigDecimal";
202 
203         case Types.REAL:
204         
205             return "java.lang.Float";
206         
207         case Types.FLOAT:
208         case Types.DOUBLE:
209           
210             return "java.lang.Double";
211 
212         case Types.CHAR:
213         case Types.VARCHAR:
214         case Types.LONGVARCHAR:
215           
216             return "java.lang.String";
217 
218         case Types.BINARY:
219         case Types.VARBINARY:
220         case Types.LONGVARBINARY:
221 
222             if (!f.isBlob()) {
223                 return "java.lang.String";
224             } else if (!f.isBinary()) {
225                 return "java.lang.String";
226             } else {
227                 return "[B";
228             }
229 
230         case Types.DATE:
231           
232             return "java.sql.Date";
233 
234         case Types.TIME:
235           
236             return "java.sql.Time";
237 
238         case Types.TIMESTAMP:
239           
240             return "java.sql.Timestamp";
241 
242         default:
243           
244             return "java.lang.Object";
245         }
246     }
247 
248     /**
249      * What's the MySQL character set name for the given column?
250      * 
251      * @param column the first column is 1, the second is 2, etc.
252      * 
253      * @return the MySQL character set name for the given column
254      * @throws SQLException if an invalid column index is given.
255      */
256     public String getColumnCharacterSet(int column) throws SQLException {
257       return getField(column).getCharacterSet();
258     }
259     
260     /**
261      * What's the Java character encoding name for the given column?
262      * 
263      * @param column the first column is 1, the second is 2, etc.
264      * 
265      * @return the Java character encoding name for the given column,
266      * or null if no Java character encoding maps to the MySQL character set
267      * for the given column.
268      * 
269      * @throws SQLException if an invalid column index is given.
270      */
271     public String getColumnCharacterEncoding(int column) throws SQLException {
272       String mysqlName = getColumnCharacterSet(column);
273       
274       String javaName = null;
275       
276       if (mysqlName != null) {
277         javaName = (String)CharsetMapping.MYSQL_TO_JAVA_CHARSET_MAP.get(mysqlName);
278       }
279       
280       return javaName;
281     }
282     
283     /**
284      * Whats the number of columns in the ResultSet?
285      *
286      * @return the number
287      * @throws java.sql.SQLException if a database access error occurs
288      */
289     public int getColumnCount() throws java.sql.SQLException {
290         return fields.length;
291     }
292 
293     /**
294      * What is the column's normal maximum width in characters?
295      *
296      * @param column the first column is 1, the second is 2, etc.
297      * @return the maximum width
298      * @throws java.sql.SQLException if a database access error occurs
299      */
300     public int getColumnDisplaySize(int column) throws java.sql.SQLException {
301         return (int)getField(column).getLength();
302     }
303 
304     /**
305      * What is the suggested column title for use in printouts and
306      * displays?
307      *
308      * @param column the first column is 1, the second is 2, etc.
309      * @return the column label
310      * @throws java.sql.SQLException if a database access error occurs
311      */
312     public String getColumnLabel(int column) throws java.sql.SQLException {
313         return getColumnName(column);
314     }
315 
316     /**
317      * What's a column's name?
318      *
319      * @param column the first column is 1, the second is 2, etc.
320      * @return the column name
321      * @throws java.sql.SQLException if a databvase access error occurs
322      */
323     public String getColumnName(int column) throws java.sql.SQLException {
324         return getField(column).getName();
325     }
326 
327     /**
328      * What is a column's SQL Type? (java.sql.Type int)
329      *
330      * @param column the first column is 1, the second is 2, etc.
331      * @return the java.sql.Type value
332      * @throws java.sql.SQLException if a database access error occurs
333      * @see java.sql.Types
334      */
335     public int getColumnType(int column) throws java.sql.SQLException {
336         return getField(column).getSQLType();
337     }
338 
339     /**
340      * Whats is the column's data source specific type name?
341      *
342      * @param column the first column is 1, the second is 2, etc.
343      * @return the type name
344      * @throws java.sql.SQLException if a database access error occurs
345      */
346     public String getColumnTypeName(int column) throws java.sql.SQLException {
347       Field field = getField(column);
348       
349         int mysqlType = field.getMysqlType();
350 
351         switch (mysqlType) {
352         case MysqlDefs.FIELD_TYPE_DECIMAL:
353             return field.isUnsigned() ? "DECIMAL UNSIGNED" : "DECIMAL";
354 
355         case MysqlDefs.FIELD_TYPE_TINY:
356             return field.isUnsigned() ? "TINYINT UNSIGNED" : "TINYINT";
357 
358         case MysqlDefs.FIELD_TYPE_SHORT:
359             return field.isUnsigned() ? "SMALLINT UNSIGNED" : "SMALLINT";
360 
361         case MysqlDefs.FIELD_TYPE_LONG:
362             return field.isUnsigned() ? "INTEGER UNSIGNED" : "INTEGER";
363 
364         case MysqlDefs.FIELD_TYPE_FLOAT:
365             return field.isUnsigned() ? "FLOAT UNSIGNED" : "FLOAT";
366 
367         case MysqlDefs.FIELD_TYPE_DOUBLE:
368             return field.isUnsigned() ? "DOUBLE UNSIGNED" : "DOUBLE";
369 
370         case MysqlDefs.FIELD_TYPE_NULL:
371             return "NULL";
372 
373         case MysqlDefs.FIELD_TYPE_TIMESTAMP:
374             return "TIMESTAMP";
375 
376         case MysqlDefs.FIELD_TYPE_LONGLONG:
377             return field.isUnsigned() ? "BIGINT UNSIGNED" : "BIGINT";
378 
379         case MysqlDefs.FIELD_TYPE_INT24:
380             return field.isUnsigned() ? "MEDIUMINT UNSIGNED" : "MEDIUMINT";
381 
382         case MysqlDefs.FIELD_TYPE_DATE:
383             return "DATE";
384 
385         case MysqlDefs.FIELD_TYPE_TIME:
386             return "TIME";
387 
388         case MysqlDefs.FIELD_TYPE_DATETIME:
389             return "DATETIME";
390 
391         case MysqlDefs.FIELD_TYPE_TINY_BLOB:
392             return "TINYBLOB";
393 
394         case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
395             return "MEDIUMBLOB";
396 
397         case MysqlDefs.FIELD_TYPE_LONG_BLOB:
398             return "LONGBLOB";
399 
400         case MysqlDefs.FIELD_TYPE_BLOB:
401 
402             if (getField(column).isBinary()) {
403                 return "BLOB";
404             } else {
405                 return "TEXT";
406             }
407 
408         case MysqlDefs.FIELD_TYPE_VAR_STRING:
409             return "VARCHAR";
410 
411         case MysqlDefs.FIELD_TYPE_STRING:
412             return "CHAR";
413 
414         case MysqlDefs.FIELD_TYPE_ENUM:
415             return "ENUM";
416 
417         case MysqlDefs.FIELD_TYPE_SET:
418             return "SET";
419            
420         case MysqlDefs.FIELD_TYPE_YEAR:
421           return "YEAR";
422 
423         default:
424             return "UNKNOWN";
425         }
426     }
427 
428     /**
429      * Is the column a cash value?
430      *
431      * @param column the first column is 1, the second is 2...
432      * @return true if its a cash column
433      * @throws java.sql.SQLException if a database access error occurs
434      */
435     public boolean isCurrency(int column) throws java.sql.SQLException {
436         return false;
437     }
438 
439     /**
440      * Will a write on this column definately succeed?
441      *
442      * @param column the first column is 1, the second is 2, etc..
443      * @return true if so
444      * @throws java.sql.SQLException if a database access error occurs
445      */
446     public boolean isDefinitelyWritable(int column)
447         throws java.sql.SQLException {
448         return isWritable(column);
449     }
450 
451     /**
452      * Can you put a NULL in this column?
453      *
454      * @param column the first column is 1, the second is 2...
455      * @return one of the columnNullable values
456      * @throws java.sql.SQLException if a database access error occurs
457      */
458     public int isNullable(int column) throws java.sql.SQLException {
459         if (!getField(column).isNotNull()) {
460             return java.sql.ResultSetMetaData.columnNullable;
461         } else {
462             return java.sql.ResultSetMetaData.columnNoNulls;
463         }
464     }
465 
466     /**
467      * What is a column's number of decimal digits.
468      *
469      * @param column the first column is 1, the second is 2...
470      * @return the precision
471      * @throws java.sql.SQLException if a database access error occurs
472      */
473     public int getPrecision(int column) throws java.sql.SQLException {
474         Field f = getField(column);
475 
476         if (isDecimalType(f.getSQLType())) {
477             if (f.getDecimals() > 0) {
478                 return (int)(f.getLength() - 1 + f.getPrecisionAdjustFactor());
479             }
480 
481             return (int)(f.getLength() + f.getPrecisionAdjustFactor());
482         }
483 
484         switch (f.getMysqlType()) {
485         case MysqlDefs.FIELD_TYPE_TINY_BLOB:
486         case MysqlDefs.FIELD_TYPE_BLOB:
487         case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
488         case MysqlDefs.FIELD_TYPE_LONG_BLOB:
489           return (int)f.getLength(); // this may change in the future
490                                   // for now, the server only
491                                   // returns FIELD_TYPE_BLOB for _all_
492                                   // BLOB types, but varying lengths
493                                   // indicating the _maximum_ size
494                                   // for each BLOB type.
495         default:
496           return (int)f.getLength();
497                 
498         }
499     }
500 
501     /**
502      * Is the column definitely not writable?
503      *
504      * @param column the first column is 1, the second is 2, etc.
505      * @return true if so
506      * @throws java.sql.SQLException if a database access error occurs
507      */
508     public boolean isReadOnly(int column) throws java.sql.SQLException {
509         return getField(column).isReadOnly();
510     }
511 
512     /**
513      * What is a column's number of digits to the right of the
514      * decimal point?
515      *
516      * @param column the first column is 1, the second is 2...
517      * @return the scale
518      * @throws java.sql.SQLException if a database access error occurs
519      */
520     public int getScale(int column) throws java.sql.SQLException {
521         Field f = getField(column);
522 
523         if (isDecimalType(f.getSQLType())) {
524             return f.getDecimals();
525         }
526 
527         return 0;
528     }
529 
530     /**
531      * What is a column's table's schema?  This relies on us knowing
532      * the table name.
533      *
534      * The JDBC specification allows us to return "" if this is not
535      * applicable.
536      *
537      * @param column the first column is 1, the second is 2...
538      * @return the Schema
539      * @throws java.sql.SQLException if a database access error occurs
540      */
541     public String getSchemaName(int column) throws java.sql.SQLException {
542         return "";
543     }
544 
545     /**
546      * Can the column be used in a WHERE clause?  Basically for
547      * this, I split the functions into two types: recognised
548      * types (which are always useable), and OTHER types (which
549      * may or may not be useable).  The OTHER types, for now, I
550      * will assume they are useable.  We should really query the
551      * catalog to see if they are useable.
552      *
553      * @param column the first column is 1, the second is 2...
554      * @return true if they can be used in a WHERE clause
555      * @throws java.sql.SQLException if a database access error occurs
556      */
557     public boolean isSearchable(int column) throws java.sql.SQLException {
558         return true;
559     }
560 
561     /**
562      * Is the column a signed number?
563      *
564      * @param column the first column is 1, the second is 2...
565      * @return true if so
566      * @throws java.sql.SQLException if a database access error occurs
567      */
568     public boolean isSigned(int column) throws java.sql.SQLException {
569         Field f = getField(column);
570         int sqlType = f.getSQLType();
571 
572         switch (sqlType) {
573         case Types.TINYINT:
574         case Types.SMALLINT:
575         case Types.INTEGER:
576         case Types.BIGINT:
577         case Types.FLOAT:
578         case Types.REAL:
579         case Types.DOUBLE:
580         case Types.NUMERIC:
581         case Types.DECIMAL:
582             return !f.isUnsigned();
583 
584         case Types.DATE:
585         case Types.TIME:
586         case Types.TIMESTAMP:
587             return false;
588 
589         default:
590             return false;
591         }
592     }
593 
594     /**
595      * Whats a column's table's name?
596      *
597      * @param column the first column is 1, the second is 2...
598      * @return column name, or "" if not applicable
599      * @throws java.sql.SQLException if a database access error occurs
600      */
601     public String getTableName(int column) throws java.sql.SQLException {
602         return getField(column).getTableName();
603     }
604 
605     /**
606      * Is it possible for a write on the column to succeed?
607      *
608      * @param column the first column is 1, the second is 2, etc.
609      * @return true if so
610      * @throws java.sql.SQLException if a database access error occurs
611      */
612     public boolean isWritable(int column) throws java.sql.SQLException {
613         return !isReadOnly(column);
614     }
615 
616     // *********************************************************************
617     //
618     //                END OF PUBLIC INTERFACE
619     //
620     // *********************************************************************
621 
622     /**
623      * Returns the field instance for the given column index
624      *
625      * @param columnIndex the column number to retrieve a field instance for
626      * @return the field instance for the given column index
627      *
628      * @throws java.sql.SQLException if an error occurs
629      */
630     protected Field getField(int columnIndex) throws java.sql.SQLException {
631         if ((columnIndex < 1) || (columnIndex > fields.length)) {
632             throw new java.sql.SQLException("Column index out of range.",
633                 SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
634         }
635 
636         return fields[columnIndex - 1];
637     }
638 
639     /**
640      * Checks if the SQL Type is a Decimal/Number Type
641      * @param type SQL Type
642      */
643     private static final boolean isDecimalType(int type) {
644         switch (type) {
645         case Types.BIT:
646         case Types.TINYINT:
647         case Types.SMALLINT:
648         case Types.INTEGER:
649         case Types.BIGINT:
650         case Types.FLOAT:
651         case Types.REAL:
652         case Types.DOUBLE:
653         case Types.NUMERIC:
654         case Types.DECIMAL:
655             return true;
656         }
657 
658         return false;
659     }
660 }