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