View Javadoc
1   /*
2    * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package javax.sql.rowset;
27  
28  import java.sql.*;
29  import javax.sql.*;
30  import java.io.*;
31  
32  import java.lang.reflect.*;
33  
34  /**
35   * Provides implementations for the methods that set and get
36   * metadata information about a <code>RowSet</code> object's columns.
37   * A <code>RowSetMetaDataImpl</code> object keeps track of the
38   * number of columns in the rowset and maintains an internal array
39   * of column attributes for each column.
40   * <P>
41   * A <code>RowSet</code> object creates a <code>RowSetMetaDataImpl</code>
42   * object internally in order to set and retrieve information about
43   * its columns.
44   * <P>
45   * NOTE: All metadata in a <code>RowSetMetaDataImpl</code> object
46   * should be considered as unavailable until the <code>RowSet</code> object
47   * that it describes is populated.
48   * Therefore, any <code>RowSetMetaDataImpl</code> method that retrieves information
49   * is defined as having unspecified behavior when it is called
50   * before the <code>RowSet</code> object contains data.
51   */
52  public class RowSetMetaDataImpl implements RowSetMetaData,  Serializable {
53  
54      /**
55       * The number of columns in the <code>RowSet</code> object that created
56       * this <code>RowSetMetaDataImpl</code> object.
57       * @serial
58       */
59      private int colCount;
60  
61      /**
62       * An array of <code>ColInfo</code> objects used to store information
63       * about each column in the <code>RowSet</code> object for which
64       * this <code>RowSetMetaDataImpl</code> object was created. The first
65       * <code>ColInfo</code> object in this array contains information about
66       * the first column in the <code>RowSet</code> object, the second element
67       * contains information about the second column, and so on.
68       * @serial
69       */
70      private ColInfo[] colInfo;
71  
72      /**
73       * Checks to see that the designated column is a valid column number for
74       * the <code>RowSet</code> object for which this <code>RowSetMetaDataImpl</code>
75       * was created. To be valid, a column number must be greater than
76       * <code>0</code> and less than or equal to the number of columns in a row.
77       * @throws <code>SQLException</code> with the message "Invalid column index"
78       *        if the given column number is out of the range of valid column
79       *        numbers for the <code>RowSet</code> object
80       */
81      private void checkColRange(int col) throws SQLException {
82          if (col <= 0 || col > colCount) {
83              throw new SQLException("Invalid column index :"+col);
84          }
85      }
86  
87      /**
88       * Checks to see that the given SQL type is a valid column type and throws an
89       * <code>SQLException</code> object if it is not.
90       * To be valid, a SQL type must be one of the constant values
91       * in the <code><a href="../../sql/Types.html">java.sql.Types</a></code>
92       * class.
93       *
94       * @param SQLType an <code>int</code> defined in the class <code>java.sql.Types</code>
95       * @throws SQLException if the given <code>int</code> is not a constant defined in the
96       *         class <code>java.sql.Types</code>
97       */
98      private void checkColType(int SQLType) throws SQLException {
99          try {
100             Class<?> c = java.sql.Types.class;
101             Field[] publicFields = c.getFields();
102             int fieldValue = 0;
103             for (int i = 0; i < publicFields.length; i++) {
104                 fieldValue = publicFields[i].getInt(c);
105                 if (fieldValue == SQLType) {
106                     return;
107                  }
108             }
109         } catch (Exception e) {
110             throw new SQLException(e.getMessage());
111         }
112         throw new SQLException("Invalid SQL type for column");
113     }
114 
115     /**
116      * Sets to the given number the number of columns in the <code>RowSet</code>
117      * object for which this <code>RowSetMetaDataImpl</code> object was created.
118      *
119      * @param columnCount an <code>int</code> giving the number of columns in the
120      *        <code>RowSet</code> object
121      * @throws SQLException if the given number is equal to or less than zero
122      */
123     public void setColumnCount(int columnCount) throws SQLException {
124 
125         if (columnCount <= 0) {
126             throw new SQLException("Invalid column count. Cannot be less " +
127                 "or equal to zero");
128             }
129 
130        colCount = columnCount;
131 
132        // If the colCount is Integer.MAX_VALUE,
133        // we do not initialize the colInfo object.
134        // even if we try to initialize the colCount with
135        // colCount = Integer.MAx_VALUE-1, the colInfo
136        // initialization fails throwing an ERROR
137        // OutOfMemory Exception. So we do not initialize
138        // colInfo at Integer.MAX_VALUE. This is to pass TCK.
139 
140        if(!(colCount == Integer.MAX_VALUE)) {
141             colInfo = new ColInfo[colCount + 1];
142 
143            for (int i=1; i <= colCount; i++) {
144                  colInfo[i] = new ColInfo();
145            }
146        }
147 
148 
149     }
150 
151     /**
152      * Sets whether the designated column is automatically
153      * numbered, thus read-only, to the given <code>boolean</code>
154      * value.
155      *
156      * @param columnIndex the first column is 1, the second is 2, and so on;
157      *        must be between <code>1</code> and the number of columns
158      *        in the rowset, inclusive
159      * @param property <code>true</code> if the given column is
160      *                 automatically incremented; <code>false</code>
161      *                 otherwise
162      * @throws SQLException if a database access error occurs or
163      *         the given index is out of bounds
164      */
165     public void setAutoIncrement(int columnIndex, boolean property) throws SQLException {
166         checkColRange(columnIndex);
167         colInfo[columnIndex].autoIncrement = property;
168     }
169 
170     /**
171      * Sets whether the name of the designated column is case sensitive to
172      * the given <code>boolean</code>.
173      *
174      * @param columnIndex the first column is 1, the second is 2, and so on;
175      *        must be between <code>1</code> and the number of columns
176      *        in the rowset, inclusive
177      * @param property <code>true</code> to indicate that the column
178      *                 name is case sensitive; <code>false</code> otherwise
179      * @throws SQLException if a database access error occurs or
180      *         the given column number is out of bounds
181      */
182     public void setCaseSensitive(int columnIndex, boolean property) throws SQLException {
183         checkColRange(columnIndex);
184         colInfo[columnIndex].caseSensitive = property;
185     }
186 
187     /**
188      * Sets whether a value stored in the designated column can be used
189      * in a <code>WHERE</code> clause to the given <code>boolean</code> value.
190      *
191      * @param columnIndex the first column is 1, the second is 2, and so on;
192      *                    must be between <code>1</code> and the number
193      *                    of columns in the rowset, inclusive
194      * @param property <code>true</code> to indicate that a column
195      *                 value can be used in a <code>WHERE</code> clause;
196      *                 <code>false</code> otherwise
197      *
198      * @throws SQLException if a database access error occurs or
199      *         the given column number is out of bounds
200      */
201     public void setSearchable(int columnIndex, boolean property)
202         throws SQLException {
203         checkColRange(columnIndex);
204         colInfo[columnIndex].searchable = property;
205     }
206 
207     /**
208      * Sets whether a value stored in the designated column is a cash
209      * value to the given <code>boolean</code>.
210      *
211      * @param columnIndex the first column is 1, the second is 2, and so on;
212      * must be between <code>1</code> and the number of columns,
213      * inclusive between <code>1</code> and the number of columns, inclusive
214      * @param property true if the value is a cash value; false otherwise.
215      * @throws SQLException if a database access error occurs
216      *         or the given column number is out of bounds
217      */
218     public void setCurrency(int columnIndex, boolean property)
219         throws SQLException {
220         checkColRange(columnIndex);
221         colInfo[columnIndex].currency = property;
222     }
223 
224     /**
225      * Sets whether a value stored in the designated column can be set
226      * to <code>NULL</code> to the given constant from the interface
227      * <code>ResultSetMetaData</code>.
228      *
229      * @param columnIndex the first column is 1, the second is 2, and so on;
230      *        must be between <code>1</code> and the number of columns, inclusive
231      * @param property one of the following <code>ResultSetMetaData</code> constants:
232      *                 <code>columnNoNulls</code>,
233      *                 <code>columnNullable</code>, or
234      *                 <code>columnNullableUnknown</code>
235      *
236      * @throws SQLException if a database access error occurs,
237      *         the given column number is out of bounds, or the value supplied
238      *         for the <i>property</i> parameter is not one of the following
239      *         constants:
240      *           <code>ResultSetMetaData.columnNoNulls</code>,
241      *           <code>ResultSetMetaData.columnNullable</code>, or
242      *           <code>ResultSetMetaData.columnNullableUnknown</code>
243      */
244     public void setNullable(int columnIndex, int property) throws SQLException {
245         if ((property < ResultSetMetaData.columnNoNulls) ||
246             property > ResultSetMetaData.columnNullableUnknown) {
247                 throw new SQLException("Invalid nullable constant set. Must be " +
248                     "either columnNoNulls, columnNullable or columnNullableUnknown");
249         }
250         checkColRange(columnIndex);
251         colInfo[columnIndex].nullable = property;
252     }
253 
254     /**
255      * Sets whether a value stored in the designated column is a signed
256      * number to the given <code>boolean</code>.
257      *
258      * @param columnIndex the first column is 1, the second is 2, and so on;
259      *        must be between <code>1</code> and the number of columns, inclusive
260      * @param property <code>true</code> to indicate that a column
261      *                 value is a signed number;
262      *                 <code>false</code> to indicate that it is not
263      * @throws SQLException if a database access error occurs
264      *         or the given column number is out of bounds
265      */
266     public void setSigned(int columnIndex, boolean property) throws SQLException {
267         checkColRange(columnIndex);
268         colInfo[columnIndex].signed = property;
269     }
270 
271     /**
272      * Sets the normal maximum number of chars in the designated column
273      * to the given number.
274      *
275      * @param columnIndex the first column is 1, the second is 2, and so on;
276      *        must be between <code>1</code> and the number of columns, inclusive
277      * @param size the maximum size of the column in chars; must be
278      *        <code>0</code> or more
279      * @throws SQLException if a database access error occurs,
280      *        the given column number is out of bounds, or <i>size</i> is
281      *        less than <code>0</code>
282      */
283     public void setColumnDisplaySize(int columnIndex, int size) throws SQLException {
284         if (size < 0) {
285             throw new SQLException("Invalid column display size. Cannot be less " +
286                 "than zero");
287         }
288         checkColRange(columnIndex);
289         colInfo[columnIndex].columnDisplaySize = size;
290     }
291 
292     /**
293      * Sets the suggested column label for use in printouts and
294      * displays, if any, to <i>label</i>. If <i>label</i> is
295      * <code>null</code>, the column label is set to an empty string
296      * ("").
297      *
298      * @param columnIndex the first column is 1, the second is 2, and so on;
299      *        must be between <code>1</code> and the number of columns, inclusive
300      * @param label the column label to be used in printouts and displays; if the
301      *        column label is <code>null</code>, an empty <code>String</code> is
302      *        set
303      * @throws SQLException if a database access error occurs
304      *         or the given column index is out of bounds
305      */
306     public void setColumnLabel(int columnIndex, String label) throws SQLException {
307         checkColRange(columnIndex);
308         if (label != null) {
309             colInfo[columnIndex].columnLabel = label;
310         } else {
311             colInfo[columnIndex].columnLabel = "";
312         }
313     }
314 
315     /**
316      * Sets the column name of the designated column to the given name.
317      *
318      * @param columnIndex the first column is 1, the second is 2, and so on;
319      *      must be between <code>1</code> and the number of columns, inclusive
320      * @param columnName a <code>String</code> object indicating the column name;
321      *      if the given name is <code>null</code>, an empty <code>String</code>
322      *      is set
323      * @throws SQLException if a database access error occurs or the given column
324      *      index is out of bounds
325      */
326     public void setColumnName(int columnIndex, String columnName) throws SQLException {
327         checkColRange(columnIndex);
328         if (columnName != null) {
329             colInfo[columnIndex].columnName = columnName;
330         } else {
331             colInfo[columnIndex].columnName = "";
332         }
333     }
334 
335     /**
336      * Sets the designated column's table's schema name, if any, to
337      * <i>schemaName</i>. If <i>schemaName</i> is <code>null</code>,
338      * the schema name is set to an empty string ("").
339      *
340      * @param columnIndex the first column is 1, the second is 2, and so on;
341      *        must be between <code>1</code> and the number of columns, inclusive
342      * @param schemaName the schema name for the table from which a value in the
343      *        designated column was derived; may be an empty <code>String</code>
344      *        or <code>null</code>
345      * @throws SQLException if a database access error occurs
346      *        or the given column number is out of bounds
347      */
348     public void setSchemaName(int columnIndex, String schemaName) throws SQLException {
349         checkColRange(columnIndex);
350         if (schemaName != null ) {
351             colInfo[columnIndex].schemaName = schemaName;
352         } else {
353             colInfo[columnIndex].schemaName = "";
354         }
355     }
356 
357     /**
358      * Sets the total number of decimal digits in a value stored in the
359      * designated column to the given number.
360      *
361      * @param columnIndex the first column is 1, the second is 2, and so on;
362      *        must be between <code>1</code> and the number of columns, inclusive
363      * @param precision the total number of decimal digits; must be <code>0</code>
364      *        or more
365      * @throws SQLException if a database access error occurs,
366      *         <i>columnIndex</i> is out of bounds, or <i>precision</i>
367      *         is less than <code>0</code>
368      */
369     public void setPrecision(int columnIndex, int precision) throws SQLException {
370 
371         if (precision < 0) {
372             throw new SQLException("Invalid precision value. Cannot be less " +
373                 "than zero");
374         }
375         checkColRange(columnIndex);
376         colInfo[columnIndex].colPrecision = precision;
377     }
378 
379     /**
380      * Sets the number of digits to the right of the decimal point in a value
381      * stored in the designated column to the given number.
382      *
383      * @param columnIndex the first column is 1, the second is 2, and so on;
384      *        must be between <code>1</code> and the number of columns, inclusive
385      * @param scale the number of digits to the right of the decimal point; must be
386      *        zero or greater
387      * @throws SQLException if a database access error occurs,
388      *         <i>columnIndex</i> is out of bounds, or <i>scale</i>
389      *         is less than <code>0</code>
390      */
391     public void setScale(int columnIndex, int scale) throws SQLException {
392         if (scale < 0) {
393             throw new SQLException("Invalid scale size. Cannot be less " +
394                 "than zero");
395         }
396         checkColRange(columnIndex);
397         colInfo[columnIndex].colScale = scale;
398     }
399 
400     /**
401      * Sets the name of the table from which the designated column
402      * was derived to the given table name.
403      *
404      * @param columnIndex the first column is 1, the second is 2, and so on;
405      *        must be between <code>1</code> and the number of columns, inclusive
406      * @param tableName the column's table name; may be <code>null</code> or an
407      *        empty string
408      * @throws SQLException if a database access error occurs
409      *         or the given column number is out of bounds
410      */
411     public void setTableName(int columnIndex, String tableName) throws SQLException {
412         checkColRange(columnIndex);
413         if (tableName != null) {
414             colInfo[columnIndex].tableName = tableName;
415         } else {
416             colInfo[columnIndex].tableName = "";
417         }
418     }
419 
420     /**
421      * Sets the catalog name of the table from which the designated
422      * column was derived to <i>catalogName</i>. If <i>catalogName</i>
423      * is <code>null</code>, the catalog name is set to an empty string.
424      *
425      * @param columnIndex the first column is 1, the second is 2, and so on;
426      *        must be between <code>1</code> and the number of columns, inclusive
427      * @param catalogName the column's table's catalog name; if the catalogName
428      *        is <code>null</code>, an empty <code>String</code> is set
429      * @throws SQLException if a database access error occurs
430      *         or the given column number is out of bounds
431      */
432     public void setCatalogName(int columnIndex, String catalogName) throws SQLException {
433         checkColRange(columnIndex);
434         if (catalogName != null)
435             colInfo[columnIndex].catName = catalogName;
436         else
437             colInfo[columnIndex].catName = "";
438     }
439 
440     /**
441      * Sets the SQL type code for values stored in the designated column
442      * to the given type code from the class <code>java.sql.Types</code>.
443      *
444      * @param columnIndex the first column is 1, the second is 2, and so on;
445      *        must be between <code>1</code> and the number of columns, inclusive
446      * @param SQLType the designated column's SQL type, which must be one of the
447      *                constants in the class <code>java.sql.Types</code>
448      * @throws SQLException if a database access error occurs,
449      *         the given column number is out of bounds, or the column type
450      *         specified is not one of the constants in
451      *         <code>java.sql.Types</code>
452      * @see java.sql.Types
453      */
454     public void setColumnType(int columnIndex, int SQLType) throws SQLException {
455         // examine java.sql.Type reflectively, loop on the fields and check
456         // this. Separate out into a private method
457         checkColType(SQLType);
458         checkColRange(columnIndex);
459         colInfo[columnIndex].colType = SQLType;
460     }
461 
462     /**
463      * Sets the type name used by the data source for values stored in the
464      * designated column to the given type name.
465      *
466      * @param columnIndex the first column is 1, the second is 2, and so on;
467      * must be between <code>1</code> and the number of columns, inclusive
468      * @param typeName the data source-specific type name; if <i>typeName</i> is
469      *        <code>null</code>, an empty <code>String</code> is set
470      * @throws SQLException if a database access error occurs
471      *         or the given column number is out of bounds
472      */
473     public void setColumnTypeName(int columnIndex, String typeName)
474         throws SQLException {
475         checkColRange(columnIndex);
476         if (typeName != null) {
477             colInfo[columnIndex].colTypeName = typeName;
478         } else {
479             colInfo[columnIndex].colTypeName = "";
480         }
481     }
482 
483     /**
484      * Retrieves the number of columns in the <code>RowSet</code> object
485      * for which this <code>RowSetMetaDataImpl</code> object was created.
486      *
487      * @return the number of columns
488      * @throws SQLException if an error occurs determining the column count
489      */
490     public int getColumnCount() throws SQLException {
491         return colCount;
492     }
493 
494     /**
495      * Retrieves whether a value stored in the designated column is
496      * automatically numbered, and thus readonly.
497      *
498      * @param columnIndex the first column is 1, the second is 2, and so on;
499      *         must be between <code>1</code> and the number of columns, inclusive
500      * @return <code>true</code> if the column is automatically numbered;
501      *         <code>false</code> otherwise
502      * @throws SQLException if a database access error occurs
503      * or the given column number is out of bounds
504      */
505     public boolean isAutoIncrement(int columnIndex) throws SQLException {
506         checkColRange(columnIndex);
507         return colInfo[columnIndex].autoIncrement;
508     }
509 
510     /**
511      * Indicates whether the case of the designated column's name
512      * matters.
513      *
514      * @param columnIndex the first column is 1, the second is 2, and so on;
515      * must be between <code>1</code> and the number of columns, inclusive
516      * @return <code>true</code> if the column name is case sensitive;
517      *          <code>false</code> otherwise
518      * @throws SQLException if a database access error occurs
519      * or the given column number is out of bounds
520      */
521     public boolean isCaseSensitive(int columnIndex) throws SQLException {
522         checkColRange(columnIndex);
523         return colInfo[columnIndex].caseSensitive;
524     }
525 
526     /**
527      * Indicates whether a value stored in the designated column
528      * can be used in a <code>WHERE</code> clause.
529      *
530      * @param columnIndex the first column is 1, the second is 2, and so on;
531      *        must be between <code>1</code> and the number of columns, inclusive
532      * @return <code>true</code> if a value in the designated column can be used in a
533      *         <code>WHERE</code> clause; <code>false</code> otherwise
534      * @throws SQLException if a database access error occurs
535      *         or the given column number is out of bounds
536      */
537     public boolean isSearchable(int columnIndex) throws SQLException {
538         checkColRange(columnIndex);
539         return colInfo[columnIndex].searchable;
540     }
541 
542     /**
543      * Indicates whether a value stored in the designated column
544      * is a cash value.
545      *
546      * @param columnIndex the first column is 1, the second is 2, and so on;
547      *        must be between <code>1</code> and the number of columns, inclusive
548      * @return <code>true</code> if a value in the designated column is a cash value;
549      *         <code>false</code> otherwise
550      * @throws SQLException if a database access error occurs
551      *         or the given column number is out of bounds
552      */
553     public boolean isCurrency(int columnIndex) throws SQLException {
554         checkColRange(columnIndex);
555         return colInfo[columnIndex].currency;
556     }
557 
558     /**
559      * Retrieves a constant indicating whether it is possible
560      * to store a <code>NULL</code> value in the designated column.
561      *
562      * @param columnIndex the first column is 1, the second is 2, and so on;
563      *        must be between <code>1</code> and the number of columns, inclusive
564      * @return a constant from the <code>ResultSetMetaData</code> interface;
565      *         either <code>columnNoNulls</code>,
566      *         <code>columnNullable</code>, or
567      *         <code>columnNullableUnknown</code>
568      * @throws SQLException if a database access error occurs
569      *         or the given column number is out of bounds
570      */
571     public int isNullable(int columnIndex) throws SQLException {
572         checkColRange(columnIndex);
573         return colInfo[columnIndex].nullable;
574     }
575 
576     /**
577      * Indicates whether a value stored in the designated column is
578      * a signed number.
579      *
580      * @param columnIndex the first column is 1, the second is 2, and so on;
581      *        must be between <code>1</code> and the number of columns, inclusive
582      * @return <code>true</code> if if a value in the designated column is a signed
583      *         number; <code>false</code> otherwise
584      * @throws SQLException if a database access error occurs
585      *         or the given column number is out of bounds
586      */
587     public boolean isSigned(int columnIndex) throws SQLException {
588         checkColRange(columnIndex);
589         return colInfo[columnIndex].signed;
590     }
591 
592     /**
593      * Retrieves the normal maximum width in chars of the designated column.
594      *
595      * @param columnIndex the first column is 1, the second is 2, and so on;
596      *        must be between <code>1</code> and the number of columns, inclusive
597      * @return the maximum number of chars that can be displayed in the designated
598      *         column
599      * @throws SQLException if a database access error occurs
600      *         or the given column number is out of bounds
601      */
602     public int getColumnDisplaySize(int columnIndex) throws SQLException {
603         checkColRange(columnIndex);
604         return colInfo[columnIndex].columnDisplaySize;
605     }
606 
607     /**
608      * Retrieves the the suggested column title for the designated
609      * column for use in printouts and displays.
610      *
611      * @param columnIndex the first column is 1, the second is 2, and so on;
612      *        must be between <code>1</code> and the number of columns, inclusive
613      * @return the suggested column name to use in printouts and displays
614      * @throws SQLException if a database access error occurs
615      *         or the given column number is out of bounds
616      */
617     public String getColumnLabel(int columnIndex) throws SQLException {
618         checkColRange(columnIndex);
619         return colInfo[columnIndex].columnLabel;
620     }
621 
622     /**
623      * Retrieves the name of the designated column.
624      *
625      * @param columnIndex the first column is 1, the second is 2, and so on;
626      * must be between <code>1</code> and the number of columns, inclusive
627      * @return the column name of the designated column
628      * @throws SQLException if a database access error occurs
629      * or the given column number is out of bounds
630      */
631     public String getColumnName(int columnIndex) throws SQLException {
632         checkColRange(columnIndex);
633         return colInfo[columnIndex].columnName;
634     }
635 
636     /**
637      * Retrieves the schema name of the table from which the value
638      * in the designated column was derived.
639      *
640      * @param columnIndex the first column is 1, the second is 2, and so on;
641      *         must be between <code>1</code> and the number of columns,
642      *         inclusive
643      * @return the schema name or an empty <code>String</code> if no schema
644      *         name is available
645      * @throws SQLException if a database access error occurs
646      * or the given column number is out of bounds
647      */
648     public String getSchemaName(int columnIndex) throws SQLException {
649         checkColRange(columnIndex);
650         String str ="";
651         if(colInfo[columnIndex].schemaName == null){
652         } else {
653               str = colInfo[columnIndex].schemaName;
654         }
655         return str;
656     }
657 
658     /**
659      * Retrieves the total number of digits for values stored in
660      * the designated column.
661      *
662      * @param columnIndex the first column is 1, the second is 2, and so on;
663      * must be between <code>1</code> and the number of columns, inclusive
664      * @return the precision for values stored in the designated column
665      * @throws SQLException if a database access error occurs
666      * or the given column number is out of bounds
667      */
668     public int getPrecision(int columnIndex) throws SQLException {
669         checkColRange(columnIndex);
670         return colInfo[columnIndex].colPrecision;
671     }
672 
673     /**
674      * Retrieves the number of digits to the right of the decimal point
675      * for values stored in the designated column.
676      *
677      * @param columnIndex the first column is 1, the second is 2, and so on;
678      * must be between <code>1</code> and the number of columns, inclusive
679      * @return the scale for values stored in the designated column
680      * @throws SQLException if a database access error occurs
681      * or the given column number is out of bounds
682      */
683     public int getScale(int columnIndex) throws SQLException {
684         checkColRange(columnIndex);
685         return colInfo[columnIndex].colScale;
686     }
687 
688     /**
689      * Retrieves the name of the table from which the value
690      * in the designated column was derived.
691      *
692      * @param columnIndex the first column is 1, the second is 2, and so on;
693      * must be between <code>1</code> and the number of columns, inclusive
694      * @return the table name or an empty <code>String</code> if no table name
695      *         is available
696      * @throws SQLException if a database access error occurs
697      * or the given column number is out of bounds
698      */
699     public String getTableName(int columnIndex) throws SQLException {
700         checkColRange(columnIndex);
701         return colInfo[columnIndex].tableName;
702     }
703 
704     /**
705      * Retrieves the catalog name of the table from which the value
706      * in the designated column was derived.
707      *
708      * @param columnIndex the first column is 1, the second is 2, and so on;
709      * must be between <code>1</code> and the number of columns, inclusive
710      * @return the catalog name of the column's table or an empty
711      *         <code>String</code> if no catalog name is available
712      * @throws SQLException if a database access error occurs
713      * or the given column number is out of bounds
714      */
715     public String getCatalogName(int columnIndex) throws SQLException {
716         checkColRange(columnIndex);
717         String str ="";
718         if(colInfo[columnIndex].catName == null){
719         } else {
720            str = colInfo[columnIndex].catName;
721         }
722         return str;
723     }
724 
725     /**
726      * Retrieves the type code (one of the <code>java.sql.Types</code>
727      * constants) for the SQL type of the value stored in the
728      * designated column.
729      *
730      * @param columnIndex the first column is 1, the second is 2, and so on;
731      * must be between <code>1</code> and the number of columns, inclusive
732      * @return an <code>int</code> representing the SQL type of values
733      * stored in the designated column
734      * @throws SQLException if a database access error occurs
735      * or the given column number is out of bounds
736      * @see java.sql.Types
737      */
738     public int getColumnType(int columnIndex) throws SQLException {
739         checkColRange(columnIndex);
740         return colInfo[columnIndex].colType;
741     }
742 
743     /**
744      * Retrieves the DBMS-specific type name for values stored in the
745      * designated column.
746      *
747      * @param columnIndex the first column is 1, the second is 2, and so on;
748      * must be between <code>1</code> and the number of columns, inclusive
749      * @return the type name used by the data source
750      * @throws SQLException if a database access error occurs
751      * or the given column number is out of bounds
752      */
753     public String getColumnTypeName(int columnIndex) throws SQLException {
754         checkColRange(columnIndex);
755         return colInfo[columnIndex].colTypeName;
756     }
757 
758 
759     /**
760      * Indicates whether the designated column is definitely
761      * not writable, thus readonly.
762      *
763      * @param columnIndex the first column is 1, the second is 2, and so on;
764      * must be between <code>1</code> and the number of columns, inclusive
765      * @return <code>true</code> if this <code>RowSet</code> object is read-Only
766      * and thus not updatable; <code>false</code> otherwise
767      * @throws SQLException if a database access error occurs
768      * or the given column number is out of bounds
769      */
770     public boolean isReadOnly(int columnIndex) throws SQLException {
771         checkColRange(columnIndex);
772         return colInfo[columnIndex].readOnly;
773     }
774 
775     /**
776      * Indicates whether it is possible for a write operation on
777      * the designated column to succeed. A return value of
778      * <code>true</code> means that a write operation may or may
779      * not succeed.
780      *
781      * @param columnIndex the first column is 1, the second is 2, and so on;
782      *         must be between <code>1</code> and the number of columns, inclusive
783      * @return <code>true</code> if a write operation on the designated column may
784      *          will succeed; <code>false</code> otherwise
785      * @throws SQLException if a database access error occurs
786      *         or the given column number is out of bounds
787      */
788     public boolean isWritable(int columnIndex) throws SQLException {
789         checkColRange(columnIndex);
790         return colInfo[columnIndex].writable;
791     }
792 
793     /**
794      * Indicates whether a write operation on the designated column
795      * will definitely succeed.
796      *
797      * @param columnIndex the first column is 1, the second is 2, and so on;
798      * must be between <code>1</code> and the number of columns, inclusive
799      * @return <code>true</code> if a write operation on the designated column will
800      *         definitely succeed; <code>false</code> otherwise
801      * @throws SQLException if a database access error occurs
802      * or the given column number is out of bounds
803      */
804     public  boolean isDefinitelyWritable(int columnIndex)
805         throws SQLException { return true;}
806 
807     /**
808      * Retrieves the fully-qualified name of the class in the Java
809      * programming language to which a value in the designated column
810      * will be mapped.  For example, if the value is an <code>int</code>,
811      * the class name returned by this method will be
812      * <code>java.lang.Integer</code>.
813      * <P>
814      * If the value in the designated column has a custom mapping,
815      * this method returns the name of the class that implements
816      * <code>SQLData</code>. When the method <code>ResultSet.getObject</code>
817      * is called to retrieve a value from the designated column, it will
818      * create an instance of this class or one of its subclasses.
819      *
820      * @param columnIndex the first column is 1, the second is 2, and so on;
821      *        must be between <code>1</code> and the number of columns, inclusive
822      * @return the fully-qualified name of the class in the Java programming
823      *        language that would be used by the method <code>RowSet.getObject</code> to
824      *        retrieve the value in the specified column. This is the class
825      *        name used for custom mapping when there is a custom mapping.
826      * @throws SQLException if a database access error occurs
827      *         or the given column number is out of bounds
828      */
829     public String getColumnClassName(int columnIndex) throws SQLException {
830         String className = String.class.getName();
831 
832         int sqlType = getColumnType(columnIndex);
833 
834         switch (sqlType) {
835 
836         case Types.NUMERIC:
837         case Types.DECIMAL:
838             className = java.math.BigDecimal.class.getName();
839             break;
840 
841         case Types.BIT:
842             className = java.lang.Boolean.class.getName();
843             break;
844 
845         case Types.TINYINT:
846             className = java.lang.Byte.class.getName();
847             break;
848 
849         case Types.SMALLINT:
850             className = java.lang.Short.class.getName();
851             break;
852 
853         case Types.INTEGER:
854             className = java.lang.Integer.class.getName();
855             break;
856 
857         case Types.BIGINT:
858             className = java.lang.Long.class.getName();
859             break;
860 
861         case Types.REAL:
862             className = java.lang.Float.class.getName();
863             break;
864 
865         case Types.FLOAT:
866         case Types.DOUBLE:
867             className = java.lang.Double.class.getName();
868             break;
869 
870         case Types.BINARY:
871         case Types.VARBINARY:
872         case Types.LONGVARBINARY:
873             className = "byte[]";
874             break;
875 
876         case Types.DATE:
877             className = java.sql.Date.class.getName();
878             break;
879 
880         case Types.TIME:
881             className = java.sql.Time.class.getName();
882             break;
883 
884         case Types.TIMESTAMP:
885             className = java.sql.Timestamp.class.getName();
886             break;
887 
888         case Types.BLOB:
889             className = java.sql.Blob.class.getName();
890             break;
891 
892         case Types.CLOB:
893             className = java.sql.Clob.class.getName();
894             break;
895         }
896 
897         return className;
898     }
899 
900     /**
901      * Returns an object that implements the given interface to allow access to non-standard methods,
902      * or standard methods not exposed by the proxy.
903      * The result may be either the object found to implement the interface or a proxy for that object.
904      * If the receiver implements the interface then that is the object. If the receiver is a wrapper
905      * and the wrapped object implements the interface then that is the object. Otherwise the object is
906      *  the result of calling <code>unwrap</code> recursively on the wrapped object. If the receiver is not a
907      * wrapper and does not implement the interface, then an <code>SQLException</code> is thrown.
908      *
909      * @param iface A Class defining an interface that the result must implement.
910      * @return an object that implements the interface. May be a proxy for the actual implementing object.
911      * @throws java.sql.SQLException If no object found that implements the interface
912      * @since 1.6
913      */
914     public <T> T unwrap(java.lang.Class<T> iface) throws java.sql.SQLException {
915 
916         if(isWrapperFor(iface)) {
917             return iface.cast(this);
918         } else {
919             throw new SQLException("unwrap failed for:"+ iface);
920         }
921     }
922 
923     /**
924      * Returns true if this either implements the interface argument or is directly or indirectly a wrapper
925      * for an object that does. Returns false otherwise. If this implements the interface then return true,
926      * else if this is a wrapper then return the result of recursively calling <code>isWrapperFor</code> on the wrapped
927      * object. If this does not implement the interface and is not a wrapper, return false.
928      * This method should be implemented as a low-cost operation compared to <code>unwrap</code> so that
929      * callers can use this method to avoid expensive <code>unwrap</code> calls that may fail. If this method
930      * returns true then calling <code>unwrap</code> with the same argument should succeed.
931      *
932      * @param interfaces a Class defining an interface.
933      * @return true if this implements the interface or directly or indirectly wraps an object that does.
934      * @throws java.sql.SQLException  if an error occurs while determining whether this is a wrapper
935      * for an object with the given interface.
936      * @since 1.6
937      */
938     public boolean isWrapperFor(Class<?> interfaces) throws SQLException {
939         return interfaces.isInstance(this);
940     }
941 
942     static final long serialVersionUID = 6893806403181801867L;
943 
944     private class ColInfo implements Serializable {
945         /**
946          * The field that indicates whether the value in this column is a number
947          * that is incremented automatically, which makes the value read-only.
948          * <code>true</code> means that the value in this column
949          * is automatically numbered; <code>false</code> means that it is not.
950          *
951          * @serial
952          */
953         public boolean autoIncrement;
954 
955         /**
956          * The field that indicates whether the value in this column is case sensitive.
957          * <code>true</code> means that it is; <code>false</code> that it is not.
958          *
959          * @serial
960          */
961         public boolean caseSensitive;
962 
963         /**
964          * The field that indicates whether the value in this column is a cash value
965          * <code>true</code> means that it is; <code>false</code> that it is not.
966          *
967          * @serial
968          */
969         public boolean currency;
970 
971         /**
972          * The field that indicates whether the value in this column is nullable.
973          * The possible values are the <code>ResultSet</code> constants
974          * <code>columnNoNulls</code>, <code>columnNullable</code>, and
975          * <code>columnNullableUnknown</code>.
976          *
977          * @serial
978          */
979         public int nullable;
980 
981         /**
982          * The field that indicates whether the value in this column is a signed number.
983          * <code>true</code> means that it is; <code>false</code> that it is not.
984          *
985          * @serial
986          */
987         public boolean signed;
988 
989         /**
990          * The field that indicates whether the value in this column can be used in
991          * a <code>WHERE</code> clause.
992          * <code>true</code> means that it can; <code>false</code> that it cannot.
993          *
994          * @serial
995          */
996         public boolean searchable;
997 
998         /**
999          * The field that indicates the normal maximum width in characters for
1000          * this column.
1001          *
1002          * @serial
1003          */
1004         public int columnDisplaySize;
1005 
1006         /**
1007          * The field that holds the suggested column title for this column, to be
1008          * used in printing and displays.
1009          *
1010          * @serial
1011          */
1012         public String columnLabel;
1013 
1014         /**
1015          * The field that holds the name of this column.
1016          *
1017          * @serial
1018          */
1019         public  String columnName;
1020 
1021         /**
1022          * The field that holds the schema name for the table from which this column
1023          * was derived.
1024          *
1025          * @serial
1026          */
1027         public String schemaName;
1028 
1029         /**
1030          * The field that holds the precision of the value in this column.  For number
1031          * types, the precision is the total number of decimal digits; for character types,
1032          * it is the maximum number of characters; for binary types, it is the maximum
1033          * length in bytes.
1034          *
1035          * @serial
1036          */
1037         public int colPrecision;
1038 
1039         /**
1040          * The field that holds the scale (number of digits to the right of the decimal
1041          * point) of the value in this column.
1042          *
1043          * @serial
1044          */
1045         public int colScale;
1046 
1047         /**
1048          * The field that holds the name of the table from which this column
1049          * was derived.  This value may be the empty string if there is no
1050          * table name, such as when this column is produced by a join.
1051          *
1052          * @serial
1053          */
1054         public String tableName ="";
1055 
1056         /**
1057          * The field that holds the catalog name for the table from which this column
1058          * was derived.  If the DBMS does not support catalogs, the value may be the
1059          * empty string.
1060          *
1061          * @serial
1062          */
1063         public String catName;
1064 
1065         /**
1066          * The field that holds the type code from the class <code>java.sql.Types</code>
1067          * indicating the type of the value in this column.
1068          *
1069          * @serial
1070          */
1071         public int colType;
1072 
1073         /**
1074          * The field that holds the the type name used by this particular data source
1075          * for the value stored in this column.
1076          *
1077          * @serial
1078          */
1079         public String colTypeName;
1080 
1081         /**
1082          * The field that holds the updatablity boolean per column of a RowSet
1083          *
1084          * @serial
1085          */
1086         public boolean readOnly = false;
1087 
1088         /**
1089          * The field that hold the writable boolean per column of a RowSet
1090          *
1091          *@serial
1092          */
1093         public boolean writable = true;
1094 
1095         static final long serialVersionUID = 5490834817919311283L;
1096     }
1097 }