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 
  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  * @since 1.5
  53  */
  54 public 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 }