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