1 /*
   2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.rowset;
  27 
  28 import java.io.*;
  29 import java.util.*;
  30 import java.sql.*;
  31 import javax.sql.*;
  32 import java.math.*;
  33 
  34 import javax.sql.rowset.*;
  35 import javax.sql.rowset.spi.*;
  36 import javax.sql.rowset.serial.*;
  37 import com.sun.rowset.providers.*;
  38 import com.sun.rowset.internal.*;
  39 
  40 /**
  41  * The standard implementation of the <code>FilteredRowSet</code> interface. See the interface
  42  * definition for full behavior and implementation requirements.
  43  *
  44  * @see javax.sql.rowset.Predicate
  45  * @author Jonathan Bruce, Amit Handa
  46  */
  47 
  48 public class FilteredRowSetImpl extends WebRowSetImpl implements Serializable, Cloneable, FilteredRowSet {
  49 
  50     private Predicate p;
  51 
  52     private boolean onInsertRow = false;
  53 
  54 
  55     /**
  56      * Construct a <code>FilteredRowSet</code>
  57      */
  58     public FilteredRowSetImpl() throws SQLException {
  59         super();
  60     }
  61 
  62     /**
  63      * Construct a <code>FilteredRowSet</code> with a specified synchronization
  64      * provider.
  65      *
  66      * @param env a Hashtable containing a desired synchconizatation provider
  67      * name-value pair.
  68      */
  69     @SuppressWarnings("rawtypes")
  70     public FilteredRowSetImpl(Hashtable env) throws SQLException {
  71         super(env);
  72     }
  73 
  74     /**
  75      * Apply the predicate for this filter
  76      *
  77      * @param p an implementation of the predicate interface
  78      */
  79     public void setFilter(Predicate p) throws SQLException {
  80         this.p = p;
  81     }
  82 
  83     /**
  84      * Retrieve the filter active for this <code>FilteredRowSet</code>
  85      *
  86      * @return a <code>Predicate</code> object instance
  87      */
  88     public Predicate getFilter() {
  89         return this.p;
  90     }
  91 
  92     /**
  93      * Over-riding <code>internalNext()</code> implementation. This method
  94      * applies the filter on the <code>RowSet</code> each time the cursor is advanced or
  95      * manipulated. It moves the cursor to the next row according to the set
  96      * predicate and returns <code>true</code> if the cursor is still within the rowset or
  97      * <code>false</code> if the cursor position is over the last row
  98      *
  99      * @return true if over the valid row in the rowset; false if over the last
 100      * row
 101      */
 102     protected boolean internalNext() throws SQLException {
 103         // CachedRowSetImpl.next() internally calls
 104         // this(crs).internalNext() NOTE: this holds crs object
 105         // So when frs.next() is called,
 106         // internally this(frs).internalNext() will be called
 107         // which will be nothing but this method.
 108         // because this holds frs object
 109 
 110         // keep on doing super.internalNext()
 111         // rather than doing it once.
 112 
 113 
 114          // p.evaluate will help us in changing the cursor
 115          // and checking the next value by returning true or false.
 116          // to fit the filter
 117 
 118          // So while() loop will have a "random combination" of
 119          // true and false returned depending upon the records
 120          // are in or out of filter.
 121          // We need to traverse from present cursorPos till end,
 122          // whether true or false and check each row for "filter"
 123          // "till we get a "true"
 124 
 125 
 126          boolean bool = false;
 127 
 128          for(int rows=this.getRow(); rows<=this.size();rows++) {
 129              bool = super.internalNext();
 130 
 131              if( !bool || p == null) {
 132                return bool;
 133              }
 134              if(p.evaluate(this)){
 135                    break;
 136              }
 137 
 138          }
 139 
 140        return bool;
 141     }
 142 
 143 
 144     /**
 145      * Over-riding <code>internalPrevious()</code> implementation. This method
 146      * applies the filter on the <code>RowSet</code> each time the cursor is moved backward or
 147      * manipulated. It moves the cursor to the previous row according to the set
 148      * predicate and returns <code>true</code> if the cursor is still within the rowset or
 149      * <code>false</code> if the cursor position is over the last row
 150      *
 151      * @return true if over the valid row in the rowset; false if over the last
 152      * row
 153      */
 154     protected boolean internalPrevious() throws SQLException {
 155          boolean bool = false;
 156          // with previous move backwards,
 157          // i.e. from any record towards first record
 158 
 159          for(int rows=this.getRow(); rows>0;rows--) {
 160 
 161              bool = super.internalPrevious();
 162 
 163              if( p == null) {
 164                return bool;
 165              }
 166 
 167              if(p.evaluate(this)){
 168                    break;
 169              }
 170 
 171          }
 172 
 173        return bool;
 174     }
 175 
 176 
 177     /**
 178      * Over-riding <code>internalFirst()</code> implementation. This method
 179      * applies the filter on the <code>RowSet</code> each time the cursor is moved to first
 180      * row. It moves the cursor to the first row according to the set
 181      * predicate and returns <code>true</code> if the cursor is still within the rowset or
 182      * <code>false</code> if the cursor position is over the last row
 183      *
 184      * @return true if over the valid row in the rowset; false if over the last
 185      * row
 186      */
 187     protected boolean internalFirst() throws SQLException {
 188 
 189         // from first till present cursor position(go forward),
 190         // find the actual first which matches the filter.
 191 
 192          boolean bool = super.internalFirst();
 193 
 194          if( p == null) {
 195                return bool;
 196              }
 197 
 198          while(bool) {
 199 
 200              if(p.evaluate(this)){
 201                    break;
 202              }
 203         bool = super.internalNext();
 204         }
 205      return bool;
 206     }
 207 
 208 
 209     /**
 210      * Over-riding <code>internalLast()</code> implementation. This method
 211      * applies the filter on the <code>RowSet</code> each time the cursor is moved to
 212      * last row. It moves the cursor to the last row according to the set
 213      * predicate and returns <code>true</code> if the cursor is still within the rowset or
 214      * <code>false</code> if the cursor position is over the last row
 215      *
 216      * @return true if over the valid row in the rowset; false if over the last
 217      * row
 218      */
 219     protected boolean internalLast() throws SQLException {
 220         // from last to the present cursor position(go backward),
 221         // find the actual last which matches the filter.
 222 
 223          boolean bool = super.internalLast();
 224 
 225          if( p == null) {
 226                return bool;
 227              }
 228 
 229          while(bool) {
 230 
 231              if(p.evaluate(this)){
 232                    break;
 233              }
 234 
 235         bool = super.internalPrevious();
 236 
 237         }
 238      return bool;
 239 
 240    } // end internalLast()
 241    /**
 242      * Moves the cursor the specified number of rows from the current
 243      * position, with a positive number moving it forward and a
 244      * negative number moving it backward.
 245      * <P>
 246      * If the number is positive, the cursor moves the specified number of
 247      * rows toward the end of the rowset, starting at the current row.
 248      * For example, the following command, in which
 249      * <code>crs</code> is a <code>CachedRowSetImpl</code> object with 100 rows,
 250      * moves the cursor forward four rows from the current row.  If the
 251      * current row is 50, the cursor would move to row 54.
 252      * <PRE><code>
 253      *
 254      *    crs.relative(4);
 255      *
 256      * </code> </PRE>
 257      * <P>
 258      * If the number is negative, the cursor moves back toward the beginning
 259      * the specified number of rows, starting at the current row.
 260      * For example, calling the method
 261      * <code>absolute(-1)</code> positions the cursor on the last row,
 262      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
 263      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
 264      * the following command moves the cursor to the fourth-to-last row, which
 265      * in the case of a  rowset with five rows, is also the second row
 266      * from the beginning.
 267      * <PRE><code>
 268      *
 269      *    crs.absolute(-4);
 270      *
 271      * </code> </PRE>
 272      *
 273      * If the number specified is larger than the number of rows, the cursor
 274      * will move to the position after the last row. If the number specified
 275      * would move the cursor one or more rows before the first row, the cursor
 276      * moves to the position before the first row. In both cases, this method
 277      * throws an <code>SQLException</code>.
 278      * <P>
 279      * Note: Calling <code>absolute(1)</code> is the same as calling the
 280      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
 281      * same as calling <code>last()</code>.  Calling <code>relative(0)</code>
 282      * is valid, but it does not change the cursor position.
 283      *
 284      * @param rows an <code>int</code> indicating the number of rows to move
 285      *             the cursor, starting at the current row; a positive number
 286      *             moves the cursor forward; a negative number moves the cursor
 287      *             backward; must not move the cursor past the valid
 288      *             rows
 289      * @return <code>true</code> if the cursor is on a row in this
 290      *         <code>CachedRowSetImpl</code> object; <code>false</code>
 291      *         otherwise
 292      * @throws SQLException if the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>
 293      */
 294    public boolean relative(int rows) throws SQLException {
 295 
 296       boolean retval;
 297       boolean bool = false;
 298       boolean boolval = false;
 299 
 300       if(getType() == ResultSet.TYPE_FORWARD_ONLY) {
 301          throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.relative").toString());
 302       }
 303 
 304       if( rows > 0 ) {
 305 
 306          int i = 0;
 307          while( i < (rows)) {
 308 
 309             if( isAfterLast() ) {
 310                return false;
 311             }
 312             bool = internalNext();
 313             i++;
 314          }
 315 
 316          retval = bool;
 317       } else {
 318          int j = rows;
 319          while( (j) < 0 ) {
 320 
 321            if( isBeforeFirst() ) {
 322               return false;
 323            }
 324            boolval = internalPrevious();
 325            j++;
 326          }
 327          retval = boolval;
 328       }
 329       if(rows != 0)
 330           notifyCursorMoved();
 331       return retval;
 332    }
 333 
 334    /**
 335      * Moves this <code>CachedRowSetImpl</code> object's cursor to the row number
 336      * specified.
 337      *
 338      * <p>If the number is positive, the cursor moves to an absolute row with
 339      * respect to the beginning of the rowset.  The first row is row 1, the second
 340      * is row 2, and so on.  For example, the following command, in which
 341      * <code>crs</code> is a <code>CachedRowSetImpl</code> object, moves the cursor
 342      * to the fourth row, starting from the beginning of the rowset.
 343      * <PRE><code>
 344      *
 345      *    crs.absolute(4);
 346      *
 347      * </code> </PRE>
 348      * <P>
 349      * If the number is negative, the cursor moves to an absolute row position
 350      * with respect to the end of the rowset.  For example, calling
 351      * <code>absolute(-1)</code> positions the cursor on the last row,
 352      * <code>absolute(-2)</code> moves it on the next-to-last row, and so on.
 353      * If the <code>CachedRowSetImpl</code> object <code>crs</code> has five rows,
 354      * the following command moves the cursor to the fourth-to-last row, which
 355      * in the case of a  rowset with five rows, is also the second row, counting
 356      * from the beginning.
 357      * <PRE><code>
 358      *
 359      *    crs.absolute(-4);
 360      *
 361      * </code> </PRE>
 362      *
 363      * If the number specified is larger than the number of rows, the cursor
 364      * will move to the position after the last row. If the number specified
 365      * would move the cursor one or more rows before the first row, the cursor
 366      * moves to the position before the first row.
 367      * <P>
 368      * Note: Calling <code>absolute(1)</code> is the same as calling the
 369      * method <code>first()</code>.  Calling <code>absolute(-1)</code> is the
 370      * same as calling <code>last()</code>.
 371      *
 372      * @param rows a positive number to indicate the row, starting row numbering from
 373      *        the first row, which is <code>1</code>; a negative number to indicate
 374      *        the row, starting row numbering from the last row, which is
 375      *        <code>-1</code>; it must not be <code>0</code>
 376      * @return <code>true</code> if the cursor is on the rowset; <code>false</code>
 377      *         otherwise
 378      * @throws SQLException if the given cursor position is <code>0</code> or the
 379      *            type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>
 380      */
 381     public boolean absolute(int rows) throws SQLException {
 382 
 383       boolean retval;
 384       boolean bool = false;
 385 
 386       if(rows == 0 || getType() == ResultSet.TYPE_FORWARD_ONLY) {
 387          throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.absolute").toString());
 388       }
 389 
 390       if (rows > 0) {
 391          bool = internalFirst();
 392 
 393          int i = 0;
 394          while(i < (rows-1)) {
 395             if( isAfterLast() ) {
 396                return false;
 397             }
 398             bool = internalNext();
 399             i++;
 400          }
 401          retval = bool;
 402       } else {
 403          bool = internalLast();
 404 
 405          int j = rows;
 406          while((j+1) < 0 ) {
 407             if( isBeforeFirst() ) {
 408                return false;
 409             }
 410             bool = internalPrevious();
 411             j++;
 412          }
 413          retval = bool;
 414       }
 415       notifyCursorMoved();
 416       return retval;
 417    }
 418 
 419    /**
 420      * Moves the cursor for this <code>CachedRowSetImpl</code> object
 421      * to the insert row.  The current row in the rowset is remembered
 422      * while the cursor is on the insert row.
 423      * <P>
 424      * The insert row is a special row associated with an updatable
 425      * rowset.  It is essentially a buffer where a new row may
 426      * be constructed by calling the appropriate <code>updateXXX</code>
 427      * methods to assign a value to each column in the row.  A complete
 428      * row must be constructed; that is, every column that is not nullable
 429      * must be assigned a value.  In order for the new row to become part
 430      * of this rowset, the method <code>insertRow</code> must be called
 431      * before the cursor is moved back to the rowset.
 432      * <P>
 433      * Only certain methods may be invoked while the cursor is on the insert
 434      * row; many methods throw an exception if they are called while the
 435      * cursor is there.  In addition to the <code>updateXXX</code>
 436      * and <code>insertRow</code> methods, only the <code>getXXX</code> methods
 437      * may be called when the cursor is on the insert row.  A <code>getXXX</code>
 438      * method should be called on a column only after an <code>updateXXX</code>
 439      * method has been called on that column; otherwise, the value returned is
 440      * undetermined.
 441      *
 442      * @throws SQLException if this <code>CachedRowSetImpl</code> object is
 443      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 444      */
 445    public void moveToInsertRow() throws SQLException {
 446 
 447       onInsertRow = true;
 448       super.moveToInsertRow();
 449    }
 450 
 451    /**
 452      * This is explanation for the overriding of the updateXXX functions.
 453      * These functions have been overriden to ensure that only correct
 454      * values that pass the criteria for the filter are actaully inserted.
 455      * The evaluation of whether a particular value passes the criteria
 456      * of the filter is done using the evaluate function in the Predicate
 457      * interface.
 458      *
 459      * The checking can will done in the evaluate function which is implemented
 460      * in the class that implements the Predicate interface. So the checking
 461      * can vary from one implementation to another.
 462      *
 463      * Some additional points here on the following:
 464      * 1. updateBytes()     - since the evaluate function takes Object as parameter
 465      *                        a String is constructed from the byte array and would
 466      *                        passed to the evaluate function.
 467      * 2. updateXXXstream() - here it would suffice to pass the stream handle
 468      *                        to the evaluate function and the implementation
 469      *                        of the evaluate function can do the comparison
 470      *                        based on the stream and also type of data.
 471      */
 472 
 473 
 474    /**
 475      * Sets the designated column in either the current row or the insert
 476      * row of this <code>CachedRowSetImpl</code> object with the given
 477      * <code>int</code> value.
 478      * <P>
 479      * This method updates a column value in the current row or the insert
 480      * row of this rowset, but it does not update the database.
 481      * If the cursor is on a row in the rowset, the
 482      * method {@link #updateRow} must be called to update the database.
 483      * If the cursor is on the insert row, the method {@link #insertRow}
 484      * must be called, which will insert the new row into both this rowset
 485      * and the database. Both of these methods must be called before the
 486      * cursor moves to another row.
 487      *
 488      * @param columnIndex the first column is <code>1</code>, the second
 489      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 490      *        and equal to or less than the number of columns in this rowset
 491      * @param x the new column value
 492      * @throws SQLException if (1) the given column index is out of bounds,
 493      *            (2) the cursor is not on one of this rowset's rows or its
 494      *            insert row, or (3) this rowset is
 495      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 496      */
 497    public void updateInt(int columnIndex , int x) throws SQLException {
 498 
 499      boolean bool;
 500 
 501      if(onInsertRow) {
 502         if(p != null) {
 503            bool = p.evaluate(Integer.valueOf(x),columnIndex);
 504 
 505            if(!bool) {
 506               throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 507            }
 508         }
 509      }
 510 
 511      super.updateInt(columnIndex,x);
 512    }
 513 
 514    /**
 515      * Sets the designated column in either the current row or the insert
 516      * row of this <code>CachedRowSetImpl</code> object with the given
 517      * <code>int</code> value.
 518      * <P>
 519      * This method updates a column value in the current row or the insert
 520      * row of this rowset, but it does not update the database.
 521      * If the cursor is on a row in the rowset, the
 522      * method {@link #updateRow} must be called to update the database.
 523      * If the cursor is on the insert row, the method {@link #insertRow}
 524      * must be called, which will insert the new row into both this rowset
 525      * and the database. Both of these methods must be called before the
 526      * cursor moves to another row.
 527      *
 528      * @param columnName a <code>String</code> object that must match the
 529      *        SQL name of a column in this rowset, ignoring case
 530      * @param x the new column value
 531      * @throws SQLException if (1) the given column name does not match the
 532      *            name of a column in this rowset, (2) the cursor is not on
 533      *            one of this rowset's rows or its insert row, or (3) this
 534      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 535      */
 536    public void updateInt(String columnName , int x) throws SQLException {
 537 
 538        this.updateInt(findColumn(columnName), x);
 539    }
 540 
 541    /**
 542      * Sets the designated column in either the current row or the insert
 543      * row of this <code>CachedRowSetImpl</code> object with the given
 544      * <code>boolean</code> value.
 545      * <P>
 546      * This method updates a column value in the current row or the insert
 547      * row of this rowset, but it does not update the database.
 548      * If the cursor is on a row in the rowset, the
 549      * method {@link #updateRow} must be called to update the database.
 550      * If the cursor is on the insert row, the method {@link #insertRow}
 551      * must be called, which will insert the new row into both this rowset
 552      * and the database. Both of these methods must be called before the
 553      * cursor moves to another row.
 554      *
 555      * @param columnIndex the first column is <code>1</code>, the second
 556      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 557      *        and equal to or less than the number of columns in this rowset
 558      * @param x the new column value
 559      * @throws SQLException if (1) the given column index is out of bounds,
 560      *            (2) the cursor is not on one of this rowset's rows or its
 561      *            insert row, or (3) this rowset is
 562      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 563      */
 564    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
 565 
 566       boolean bool;
 567 
 568       if(onInsertRow) {
 569          if(p != null) {
 570             bool = p.evaluate(Boolean.valueOf(x) , columnIndex);
 571 
 572             if(!bool) {
 573                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 574             }
 575          }
 576       }
 577 
 578       super.updateBoolean(columnIndex,x);
 579    }
 580 
 581    /**
 582      * Sets the designated column in either the current row or the insert
 583      * row of this <code>CachedRowSetImpl</code> object with the given
 584      * <code>boolean</code> value.
 585      * <P>
 586      * This method updates a column value in the current row or the insert
 587      * row of this rowset, but it does not update the database.
 588      * If the cursor is on a row in the rowset, the
 589      * method {@link #updateRow} must be called to update the database.
 590      * If the cursor is on the insert row, the method {@link #insertRow}
 591      * must be called, which will insert the new row into both this rowset
 592      * and the database. Both of these methods must be called before the
 593      * cursor moves to another row.
 594      *
 595      * @param columnName a <code>String</code> object that must match the
 596      *        SQL name of a column in this rowset, ignoring case
 597      * @param x the new column value
 598      * @throws SQLException if (1) the given column name does not match the
 599      *            name of a column in this rowset, (2) the cursor is not on
 600      *            one of this rowset's rows or its insert row, or (3) this
 601      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 602      */
 603    public void updateBoolean(String columnName , boolean x) throws SQLException {
 604 
 605       this.updateBoolean(findColumn(columnName),x);
 606    }
 607 
 608 
 609 
 610     /**
 611      * Sets the designated column in either the current row or the insert
 612      * row of this <code>CachedRowSetImpl</code> object with the given
 613      * <code>byte</code> value.
 614      * <P>
 615      * This method updates a column value in the current row or the insert
 616      * row of this rowset, but it does not update the database.
 617      * If the cursor is on a row in the rowset, the
 618      * method {@link #updateRow} must be called to update the database.
 619      * If the cursor is on the insert row, the method {@link #insertRow}
 620      * must be called, which will insert the new row into both this rowset
 621      * and the database. Both of these methods must be called before the
 622      * cursor moves to another row.
 623      *
 624      * @param columnIndex the first column is <code>1</code>, the second
 625      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 626      *        and equal to or less than the number of columns in this rowset
 627      * @param x the new column value
 628      * @throws SQLException if (1) the given column index is out of bounds,
 629      *            (2) the cursor is not on one of this rowset's rows or its
 630      *            insert row, or (3) this rowset is
 631      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 632      */
 633    public void updateByte(int columnIndex , byte x) throws SQLException {
 634       boolean bool;
 635 
 636       if(onInsertRow) {
 637          if(p != null) {
 638             bool = p.evaluate(Byte.valueOf(x),columnIndex);
 639 
 640             if(!bool) {
 641                 throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 642             }
 643           }
 644       }
 645 
 646       super.updateByte(columnIndex,x);
 647    }
 648 
 649 
 650    /**
 651      * Sets the designated column in either the current row or the insert
 652      * row of this <code>CachedRowSetImpl</code> object with the given
 653      * <code>byte</code> value.
 654      * <P>
 655      * This method updates a column value in the current row or the insert
 656      * row of this rowset, but it does not update the database.
 657      * If the cursor is on a row in the rowset, the
 658      * method {@link #updateRow} must be called to update the database.
 659      * If the cursor is on the insert row, the method {@link #insertRow}
 660      * must be called, which will insert the new row into both this rowset
 661      * and the database. Both of these methods must be called before the
 662      * cursor moves to another row.
 663      *
 664      * @param columnName a <code>String</code> object that must match the
 665      *        SQL name of a column in this rowset, ignoring case
 666      * @param x the new column value
 667      * @throws SQLException if (1) the given column name does not match the
 668      *            name of a column in this rowset, (2) the cursor is not on
 669      *            one of this rowset's rows or its insert row, or (3) this
 670      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 671      */
 672    public void updateByte(String columnName , byte x) throws SQLException {
 673 
 674       this.updateByte(findColumn(columnName),x);
 675    }
 676 
 677 
 678    /**
 679      * Sets the designated column in either the current row or the insert
 680      * row of this <code>CachedRowSetImpl</code> object with the given
 681      * <code>short</code> value.
 682      * <P>
 683      * This method updates a column value in the current row or the insert
 684      * row of this rowset, but it does not update the database.
 685      * If the cursor is on a row in the rowset, the
 686      * method {@link #updateRow} must be called to update the database.
 687      * If the cursor is on the insert row, the method {@link #insertRow}
 688      * must be called, which will insert the new row into both this rowset
 689      * and the database. Both of these methods must be called before the
 690      * cursor moves to another row.
 691      *
 692      * @param columnIndex the first column is <code>1</code>, the second
 693      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 694      *        and equal to or less than the number of columns in this rowset
 695      * @param x the new column value
 696      * @throws SQLException if (1) the given column index is out of bounds,
 697      *            (2) the cursor is not on one of this rowset's rows or its
 698      *            insert row, or (3) this rowset is
 699      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 700      */
 701    public void updateShort( int columnIndex , short x) throws SQLException {
 702 
 703       boolean bool;
 704 
 705       if(onInsertRow) {
 706          if(p != null) {
 707             bool = p.evaluate(Short.valueOf(x), columnIndex);
 708 
 709             if(!bool) {
 710                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 711             }
 712           }
 713       }
 714 
 715       super.updateShort(columnIndex,x);
 716    }
 717 
 718    /**
 719      * Sets the designated column in either the current row or the insert
 720      * row of this <code>CachedRowSetImpl</code> object with the given
 721      * <code>short</code> value.
 722      * <P>
 723      * This method updates a column value in the current row or the insert
 724      * row of this rowset, but it does not update the database.
 725      * If the cursor is on a row in the rowset, the
 726      * method {@link #updateRow} must be called to update the database.
 727      * If the cursor is on the insert row, the method {@link #insertRow}
 728      * must be called, which will insert the new row into both this rowset
 729      * and the database. Both of these methods must be called before the
 730      * cursor moves to another row.
 731      *
 732      * @param columnName a <code>String</code> object that must match the
 733      *        SQL name of a column in this rowset, ignoring case
 734      * @param x the new column value
 735      * @throws SQLException if (1) the given column name does not match the
 736      *            name of a column in this rowset, (2) the cursor is not on
 737      *            one of this rowset's rows or its insert row, or (3) this
 738      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 739      */
 740    public void updateShort( String columnName , short x) throws SQLException {
 741 
 742       this.updateShort(findColumn(columnName),x);
 743    }
 744 
 745 
 746    /**
 747      * Sets the designated column in either the current row or the insert
 748      * row of this <code>CachedRowSetImpl</code> object with the given
 749      * <code>long</code> value.
 750      * <P>
 751      * This method updates a column value in the current row or the insert
 752      * row of this rowset, but it does not update the database.
 753      * If the cursor is on a row in the rowset, the
 754      * method {@link #updateRow} must be called to update the database.
 755      * If the cursor is on the insert row, the method {@link #insertRow}
 756      * must be called, which will insert the new row into both this rowset
 757      * and the database. Both of these methods must be called before the
 758      * cursor moves to another row.
 759      *
 760      * @param columnIndex the first column is <code>1</code>, the second
 761      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 762      *        and equal to or less than the number of columns in this rowset
 763      * @param x the new column value
 764      * @throws SQLException if (1) the given column index is out of bounds,
 765      *            (2) the cursor is not on one of this rowset's rows or its
 766      *            insert row, or (3) this rowset is
 767      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 768      */
 769    public void updateLong(int columnIndex , long x) throws SQLException {
 770 
 771       boolean bool;
 772 
 773       if(onInsertRow) {
 774          if(p != null) {
 775             bool = p.evaluate(Long.valueOf(x), columnIndex);
 776 
 777             if(!bool) {
 778                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 779             }
 780           }
 781       }
 782 
 783       super.updateLong(columnIndex,x);
 784    }
 785 
 786    /**
 787      * Sets the designated column in either the current row or the insert
 788      * row of this <code>CachedRowSetImpl</code> object with the given
 789      * <code>long</code> value.
 790      * <P>
 791      * This method updates a column value in the current row or the insert
 792      * row of this rowset, but it does not update the database.
 793      * If the cursor is on a row in the rowset, the
 794      * method {@link #updateRow} must be called to update the database.
 795      * If the cursor is on the insert row, the method {@link #insertRow}
 796      * must be called, which will insert the new row into both this rowset
 797      * and the database. Both of these methods must be called before the
 798      * cursor moves to another row.
 799      *
 800      * @param columnName a <code>String</code> object that must match the
 801      *        SQL name of a column in this rowset, ignoring case
 802      * @param x the new column value
 803      * @throws SQLException if (1) the given column name does not match the
 804      *            name of a column in this rowset, (2) the cursor is not on
 805      *            one of this rowset's rows or its insert row, or (3) this
 806      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 807      */
 808    public void updateLong( String columnName , long x) throws SQLException {
 809 
 810       this.updateLong(findColumn(columnName) , x);
 811    }
 812 
 813    /**
 814      * Sets the designated column in either the current row or the insert
 815      * row of this <code>CachedRowSetImpl</code> object with the given
 816      * <code>float</code> value.
 817      * <P>
 818      * This method updates a column value in the current row or the insert
 819      * row of this rowset, but it does not update the database.
 820      * If the cursor is on a row in the rowset, the
 821      * method {@link #updateRow} must be called to update the database.
 822      * If the cursor is on the insert row, the method {@link #insertRow}
 823      * must be called, which will insert the new row into both this rowset
 824      * and the database. Both of these methods must be called before the
 825      * cursor moves to another row.
 826      *
 827      * @param columnIndex the first column is <code>1</code>, the second
 828      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 829      *        and equal to or less than the number of columns in this rowset
 830      * @param x the new column value
 831      * @throws SQLException if (1) the given column index is out of bounds,
 832      *            (2) the cursor is not on one of this rowset's rows or its
 833      *            insert row, or (3) this rowset is
 834      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 835      */
 836    public void updateFloat(int columnIndex , float x) throws SQLException {
 837 
 838       boolean bool;
 839 
 840       if(onInsertRow) {
 841          if(p != null) {
 842             bool = p.evaluate(Float.valueOf(x), columnIndex);
 843 
 844             if(!bool) {
 845                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 846             }
 847           }
 848       }
 849 
 850       super.updateFloat(columnIndex,x);
 851    }
 852 
 853    /**
 854      * Sets the designated column in either the current row or the insert
 855      * row of this <code>CachedRowSetImpl</code> object with the given
 856      * <code>float</code> value.
 857      * <P>
 858      * This method updates a column value in the current row or the insert
 859      * row of this rowset, but it does not update the database.
 860      * If the cursor is on a row in the rowset, the
 861      * method {@link #updateRow} must be called to update the database.
 862      * If the cursor is on the insert row, the method {@link #insertRow}
 863      * must be called, which will insert the new row into both this rowset
 864      * and the database. Both of these methods must be called before the
 865      * cursor moves to another row.
 866      *
 867      * @param columnName a <code>String</code> object that must match the
 868      *        SQL name of a column in this rowset, ignoring case
 869      * @param x the new column value
 870      * @throws SQLException if (1) the given column name does not match the
 871      *            name of a column in this rowset, (2) the cursor is not on
 872      *            one of this rowset's rows or its insert row, or (3) this
 873      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 874      */
 875    public void updateFloat(String columnName , float x) throws SQLException {
 876 
 877       this.updateFloat(findColumn(columnName),x);
 878    }
 879 
 880     /**
 881      * Sets the designated column in either the current row or the insert
 882      * row of this <code>CachedRowSetImpl</code> object with the given
 883      * <code>double</code> value.
 884      *
 885      * This method updates a column value in either the current row or
 886      * the insert row of this rowset, but it does not update the
 887      * database.  If the cursor is on a row in the rowset, the
 888      * method {@link #updateRow} must be called to update the database.
 889      * If the cursor is on the insert row, the method {@link #insertRow}
 890      * must be called, which will insert the new row into both this rowset
 891      * and the database. Both of these methods must be called before the
 892      * cursor moves to another row.
 893      *
 894      * @param columnIndex the first column is <code>1</code>, the second
 895      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 896      *        and equal to or less than the number of columns in this rowset
 897      * @param x the new column value
 898      * @throws SQLException if (1) the given column index is out of bounds,
 899      *            (2) the cursor is not on one of this rowset's rows or its
 900      *            insert row, or (3) this rowset is
 901      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 902      */
 903    public void updateDouble(int columnIndex , double x) throws SQLException {
 904 
 905       boolean bool;
 906 
 907       if(onInsertRow) {
 908          if(p != null) {
 909             bool = p.evaluate(Double.valueOf(x) , columnIndex);
 910 
 911             if(!bool) {
 912                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 913             }
 914           }
 915       }
 916 
 917       super.updateDouble(columnIndex,x);
 918    }
 919 
 920    /**
 921      * Sets the designated column in either the current row or the insert
 922      * row of this <code>CachedRowSetImpl</code> object with the given
 923      * <code>double</code> value.
 924      *
 925      * This method updates a column value in either the current row or
 926      * the insert row of this rowset, but it does not update the
 927      * database.  If the cursor is on a row in the rowset, the
 928      * method {@link #updateRow} must be called to update the database.
 929      * If the cursor is on the insert row, the method {@link #insertRow}
 930      * must be called, which will insert the new row into both this rowset
 931      * and the database. Both of these methods must be called before the
 932      * cursor moves to another row.
 933      *
 934      * @param columnName a <code>String</code> object that must match the
 935      *        SQL name of a column in this rowset, ignoring case
 936      * @param x the new column value
 937      * @throws SQLException if (1) the given column name does not match the
 938      *            name of a column in this rowset, (2) the cursor is not on
 939      *            one of this rowset's rows or its insert row, or (3) this
 940      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
 941      */
 942    public void updateDouble(String columnName , double x) throws SQLException {
 943 
 944       this.updateDouble(findColumn(columnName),x);
 945    }
 946 
 947    /**
 948      * Sets the designated column in either the current row or the insert
 949      * row of this <code>CachedRowSetImpl</code> object with the given
 950      * <code>java.math.BigDecimal</code> object.
 951      * <P>
 952      * This method updates a column value in the current row or the insert
 953      * row of this rowset, but it does not update the database.
 954      * If the cursor is on a row in the rowset, the
 955      * method {@link #updateRow} must be called to update the database.
 956      * If the cursor is on the insert row, the method {@link #insertRow}
 957      * must be called, which will insert the new row into both this rowset
 958      * and the database. Both of these methods must be called before the
 959      * cursor moves to another row.
 960      *
 961      * @param columnIndex the first column is <code>1</code>, the second
 962      *        is <code>2</code>, and so on; must be <code>1</code> or larger
 963      *        and equal to or less than the number of columns in this rowset
 964      * @param x the new column value
 965      * @throws SQLException if (1) the given column index is out of bounds,
 966      *            (2) the cursor is not on one of this rowset's rows or its
 967      *            insert row, or (3) this rowset is
 968      *            <code>ResultSet.CONCUR_READ_ONLY</code>
 969      */
 970    public void updateBigDecimal(int columnIndex , BigDecimal x) throws SQLException {
 971 
 972       boolean bool;
 973 
 974       if(onInsertRow) {
 975          if(p != null) {
 976             bool = p.evaluate(x,columnIndex);
 977 
 978             if(!bool) {
 979                throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
 980             }
 981           }
 982       }
 983 
 984       super.updateBigDecimal(columnIndex,x);
 985    }
 986 
 987    /**
 988      * Sets the designated column in either the current row or the insert
 989      * row of this <code>CachedRowSetImpl</code> object with the given
 990      * <code>java.math.BigDecimal</code> object.
 991      * <P>
 992      * This method updates a column value in the current row or the insert
 993      * row of this rowset, but it does not update the database.
 994      * If the cursor is on a row in the rowset, the
 995      * method {@link #updateRow} must be called to update the database.
 996      * If the cursor is on the insert row, the method {@link #insertRow}
 997      * must be called, which will insert the new row into both this rowset
 998      * and the database. Both of these methods must be called before the
 999      * cursor moves to another row.
1000      *
1001      * @param columnName a <code>String</code> object that must match the
1002      *        SQL name of a column in this rowset, ignoring case
1003      * @param x the new column value
1004      * @throws SQLException if (1) the given column name does not match the
1005      *            name of a column in this rowset, (2) the cursor is not on
1006      *            one of this rowset's rows or its insert row, or (3) this
1007      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1008      */
1009    public void updateBigDecimal(String columnName , BigDecimal x) throws SQLException {
1010 
1011       this.updateBigDecimal(findColumn(columnName),x);
1012    }
1013 
1014    /**
1015      * Sets the designated column in either the current row or the insert
1016      * row of this <code>CachedRowSetImpl</code> object with the given
1017      * <code>String</code> object.
1018      * <P>
1019      * This method updates a column value in either the current row or
1020      * the insert row of this rowset, but it does not update the
1021      * database.  If the cursor is on a row in the rowset, the
1022      * method {@link #updateRow} must be called to mark the row as updated.
1023      * If the cursor is on the insert row, the method {@link #insertRow}
1024      * must be called to insert the new row into this rowset and mark it
1025      * as inserted. Both of these methods must be called before the
1026      * cursor moves to another row.
1027      * <P>
1028      * The method <code>acceptChanges</code> must be called if the
1029      * updated values are to be written back to the underlying database.
1030      *
1031      * @param columnIndex the first column is <code>1</code>, the second
1032      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1033      *        and equal to or less than the number of columns in this rowset
1034      * @param x the new column value
1035      * @throws SQLException if (1) the given column index is out of bounds,
1036      *            (2) the cursor is not on one of this rowset's rows or its
1037      *            insert row, or (3) this rowset is
1038      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1039      */
1040    public void updateString(int columnIndex , String x) throws SQLException {
1041 
1042       boolean bool;
1043 
1044       if(onInsertRow) {
1045          if(p != null) {
1046            bool = p.evaluate(x,columnIndex);
1047 
1048            if(!bool) {
1049               throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1050            }
1051          }
1052       }
1053 
1054       super.updateString(columnIndex,x);
1055    }
1056 
1057    /**
1058      * Sets the designated column in either the current row or the insert
1059      * row of this <code>CachedRowSetImpl</code> object with the given
1060      * <code>String</code> object.
1061      *
1062      * This method updates a column value in either the current row or
1063      * the insert row of this rowset, but it does not update the
1064      * database.  If the cursor is on a row in the rowset, the
1065      * method {@link #updateRow} must be called to update the database.
1066      * If the cursor is on the insert row, the method {@link #insertRow}
1067      * must be called, which will insert the new row into both this rowset
1068      * and the database. Both of these methods must be called before the
1069      * cursor moves to another row.
1070      *
1071      * @param columnName a <code>String</code> object that must match the
1072      *        SQL name of a column in this rowset, ignoring case
1073      * @param x the new column value
1074      * @throws SQLException if (1) the given column name does not match the
1075      *            name of a column in this rowset, (2) the cursor is not on
1076      *            one of this rowset's rows or its insert row, or (3) this
1077      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1078      */
1079    public void updateString(String columnName , String x) throws SQLException {
1080 
1081       this.updateString(findColumn(columnName),x);
1082    }
1083 
1084    /**
1085      * Sets the designated column in either the current row or the insert
1086      * row of this <code>CachedRowSetImpl</code> object with the given
1087      * <code>byte</code> array.
1088      *
1089      * This method updates a column value in either the current row or
1090      * the insert row of this rowset, but it does not update the
1091      * database.  If the cursor is on a row in the rowset, the
1092      * method {@link #updateRow} must be called to update the database.
1093      * If the cursor is on the insert row, the method {@link #insertRow}
1094      * must be called, which will insert the new row into both this rowset
1095      * and the database. Both of these methods must be called before the
1096      * cursor moves to another row.
1097      *
1098      * @param columnIndex the first column is <code>1</code>, the second
1099      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1100      *        and equal to or less than the number of columns in this rowset
1101      * @param x the new column value
1102      * @throws SQLException if (1) the given column index is out of bounds,
1103      *            (2) the cursor is not on one of this rowset's rows or its
1104      *            insert row, or (3) this rowset is
1105      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1106      */
1107    public void updateBytes(int columnIndex , byte []x) throws SQLException {
1108 
1109       boolean bool;
1110       String val = "";
1111 
1112       Byte [] obj_arr = new Byte[x.length];
1113 
1114       for(int i = 0; i < x.length; i++) {
1115          obj_arr[i] = Byte.valueOf(x[i]);
1116          val = val.concat(obj_arr[i].toString());
1117      }
1118 
1119 
1120       if(onInsertRow) {
1121          if(p != null) {
1122              bool = p.evaluate(val,columnIndex);
1123 
1124              if(!bool) {
1125                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1126              }
1127          }
1128       }
1129 
1130       super.updateBytes(columnIndex,x);
1131    }
1132 
1133    /**
1134      * Sets the designated column in either the current row or the insert
1135      * row of this <code>CachedRowSetImpl</code> object with the given
1136      * <code>byte</code> array.
1137      *
1138      * This method updates a column value in either the current row or
1139      * the insert row of this rowset, but it does not update the
1140      * database.  If the cursor is on a row in the rowset, the
1141      * method {@link #updateRow} must be called to update the database.
1142      * If the cursor is on the insert row, the method {@link #insertRow}
1143      * must be called, which will insert the new row into both this rowset
1144      * and the database. Both of these methods must be called before the
1145      * cursor moves to another row.
1146      *
1147      * @param columnName a <code>String</code> object that must match the
1148      *        SQL name of a column in this rowset, ignoring case
1149      * @param x the new column value
1150      * @throws SQLException if (1) the given column name does not match the
1151      *            name of a column in this rowset, (2) the cursor is not on
1152      *            one of this rowset's rows or its insert row, or (3) this
1153      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1154      */
1155    public void updateBytes(String columnName , byte []x) throws SQLException {
1156 
1157       this.updateBytes(findColumn(columnName),x);
1158    }
1159 
1160    /**
1161      * Sets the designated column in either the current row or the insert
1162      * row of this <code>CachedRowSetImpl</code> object with the given
1163      * <code>Date</code> object.
1164      *
1165      * This method updates a column value in either the current row or
1166      * the insert row of this rowset, but it does not update the
1167      * database.  If the cursor is on a row in the rowset, the
1168      * method {@link #updateRow} must be called to update the database.
1169      * If the cursor is on the insert row, the method {@link #insertRow}
1170      * must be called, which will insert the new row into both this rowset
1171      * and the database. Both of these methods must be called before the
1172      * cursor moves to another row.
1173      *
1174      * @param columnIndex the first column is <code>1</code>, the second
1175      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1176      *        and equal to or less than the number of columns in this rowset
1177      * @param x the new column value
1178      * @throws SQLException if (1) the given column index is out of bounds,
1179      *            (2) the cursor is not on one of this rowset's rows or its
1180      *            insert row, (3) the type of the designated column is not
1181      *            an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or
1182      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1183      */
1184    public void updateDate(int columnIndex , java.sql.Date x) throws SQLException {
1185 
1186       boolean bool;
1187 
1188       if(onInsertRow) {
1189          if(p != null) {
1190              bool = p.evaluate(x,columnIndex);
1191 
1192              if(!bool) {
1193                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1194              }
1195          }
1196       }
1197 
1198       super.updateDate(columnIndex,x);
1199    }
1200 
1201    /**
1202      * Sets the designated column in either the current row or the insert
1203      * row of this <code>CachedRowSetImpl</code> object with the given
1204      * <code>Date</code> object.
1205      *
1206      * This method updates a column value in either the current row or
1207      * the insert row of this rowset, but it does not update the
1208      * database.  If the cursor is on a row in the rowset, the
1209      * method {@link #updateRow} must be called to update the database.
1210      * If the cursor is on the insert row, the method {@link #insertRow}
1211      * must be called, which will insert the new row into both this rowset
1212      * and the database. Both of these methods must be called before the
1213      * cursor moves to another row.
1214      *
1215      * @param columnName a <code>String</code> object that must match the
1216      *        SQL name of a column in this rowset, ignoring case
1217      * @param x the new column value
1218      * @throws SQLException if (1) the given column name does not match the
1219      *            name of a column in this rowset, (2) the cursor is not on
1220      *            one of this rowset's rows or its insert row, (3) the type
1221      *            of the designated column is not an SQL <code>DATE</code> or
1222      *            <code>TIMESTAMP</code>, or (4) this rowset is
1223      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1224      */
1225    public void updateDate(String columnName , java.sql.Date x) throws SQLException {
1226 
1227       this.updateDate(findColumn(columnName),x);
1228    }
1229 
1230    /**
1231      * Sets the designated column in either the current row or the insert
1232      * row of this <code>CachedRowSetImpl</code> object with the given
1233      * <code>Time</code> object.
1234      *
1235      * This method updates a column value in either the current row or
1236      * the insert row of this rowset, but it does not update the
1237      * database.  If the cursor is on a row in the rowset, the
1238      * method {@link #updateRow} must be called to update the database.
1239      * If the cursor is on the insert row, the method {@link #insertRow}
1240      * must be called, which will insert the new row into both this rowset
1241      * and the database. Both of these methods must be called before the
1242      * cursor moves to another row.
1243      *
1244      * @param columnIndex the first column is <code>1</code>, the second
1245      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1246      *        and equal to or less than the number of columns in this rowset
1247      * @param x the new column value
1248      * @throws SQLException if (1) the given column index is out of bounds,
1249      *            (2) the cursor is not on one of this rowset's rows or its
1250      *            insert row, (3) the type of the designated column is not
1251      *            an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or
1252      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1253      */
1254    public void updateTime(int columnIndex , Time x) throws SQLException {
1255 
1256       boolean bool;
1257 
1258       if(onInsertRow) {
1259          if(p != null) {
1260              bool = p.evaluate(x, columnIndex);
1261 
1262              if(!bool) {
1263                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1264              }
1265          }
1266       }
1267 
1268       super.updateTime(columnIndex,x);
1269    }
1270 
1271    /**
1272      * Sets the designated column in either the current row or the insert
1273      * row of this <code>CachedRowSetImpl</code> object with the given
1274      * <code>Time</code> object.
1275      *
1276      * This method updates a column value in either the current row or
1277      * the insert row of this rowset, but it does not update the
1278      * database.  If the cursor is on a row in the rowset, the
1279      * method {@link #updateRow} must be called to update the database.
1280      * If the cursor is on the insert row, the method {@link #insertRow}
1281      * must be called, which will insert the new row into both this rowset
1282      * and the database. Both of these methods must be called before the
1283      * cursor moves to another row.
1284      *
1285      * @param columnName a <code>String</code> object that must match the
1286      *        SQL name of a column in this rowset, ignoring case
1287      * @param x the new column value
1288      * @throws SQLException if (1) the given column name does not match the
1289      *            name of a column in this rowset, (2) the cursor is not on
1290      *            one of this rowset's rows or its insert row, (3) the type
1291      *            of the designated column is not an SQL <code>TIME</code> or
1292      *            <code>TIMESTAMP</code>, or (4) this rowset is
1293      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1294      */
1295    public void updateTime(String columnName , Time x) throws SQLException {
1296 
1297       this.updateTime(findColumn(columnName),x);
1298    }
1299 
1300    /**
1301      * Sets the designated column in either the current row or the insert
1302      * row of this <code>CachedRowSetImpl</code> object with the given
1303      * <code>Timestamp</code> object.
1304      *
1305      * This method updates a column value in either the current row or
1306      * the insert row of this rowset, but it does not update the
1307      * database.  If the cursor is on a row in the rowset, the
1308      * method {@link #updateRow} must be called to update the database.
1309      * If the cursor is on the insert row, the method {@link #insertRow}
1310      * must be called, which will insert the new row into both this rowset
1311      * and the database. Both of these methods must be called before the
1312      * cursor moves to another row.
1313      *
1314      * @param columnIndex the first column is <code>1</code>, the second
1315      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1316      *        and equal to or less than the number of columns in this rowset
1317      * @param x the new column value
1318      * @throws SQLException if (1) the given column index is out of bounds,
1319      *            (2) the cursor is not on one of this rowset's rows or its
1320      *            insert row, (3) the type of the designated column is not
1321      *            an SQL <code>DATE</code>, <code>TIME</code>, or
1322      *            <code>TIMESTAMP</code>, or (4) this rowset is
1323      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1324      */
1325    public void updateTimestamp(int columnIndex , Timestamp x) throws SQLException {
1326 
1327       boolean bool;
1328 
1329       if(onInsertRow) {
1330          if(p != null) {
1331              bool = p.evaluate(x,columnIndex);
1332 
1333              if(!bool) {
1334                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1335              }
1336          }
1337       }
1338 
1339       super.updateTimestamp(columnIndex,x);
1340    }
1341 
1342     /**
1343      * Sets the designated column in either the current row or the insert
1344      * row of this <code>CachedRowSetImpl</code> object with the given
1345      * <code>Timestamp</code> object.
1346      *
1347      * This method updates a column value in either the current row or
1348      * the insert row of this rowset, but it does not update the
1349      * database.  If the cursor is on a row in the rowset, the
1350      * method {@link #updateRow} must be called to update the database.
1351      * If the cursor is on the insert row, the method {@link #insertRow}
1352      * must be called, which will insert the new row into both this rowset
1353      * and the database. Both of these methods must be called before the
1354      * cursor moves to another row.
1355      *
1356      * @param columnName a <code>String</code> object that must match the
1357      *        SQL name of a column in this rowset, ignoring case
1358      * @param x the new column value
1359      * @throws SQLException if the given column index is out of bounds or
1360      *            the cursor is not on one of this rowset's rows or its
1361      *            insert row
1362      * @throws SQLException if (1) the given column name does not match the
1363      *            name of a column in this rowset, (2) the cursor is not on
1364      *            one of this rowset's rows or its insert row, (3) the type
1365      *            of the designated column is not an SQL <code>DATE</code>,
1366      *            <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this
1367      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1368      */
1369    public void updateTimestamp(String columnName , Timestamp x) throws SQLException {
1370 
1371       this.updateTimestamp(findColumn(columnName),x);
1372    }
1373 
1374    /**
1375      * Sets the designated column in either the current row or the insert
1376      * row of this <code>CachedRowSetImpl</code> object with the given
1377      * ASCII stream value.
1378      * <P>
1379      * This method updates a column value in either the current row or
1380      * the insert row of this rowset, but it does not update the
1381      * database.  If the cursor is on a row in the rowset, the
1382      * method {@link #updateRow} must be called to update the database.
1383      * If the cursor is on the insert row, the method {@link #insertRow}
1384      * must be called, which will insert the new row into both this rowset
1385      * and the database. Both of these methods must be called before the
1386      * cursor moves to another row.
1387      *
1388      * @param columnIndex the first column is <code>1</code>, the second
1389      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1390      *        and equal to or less than the number of columns in this rowset
1391      * @param x the new column value
1392      * @param length the number of one-byte ASCII characters in the stream
1393      * @throws SQLException if this method is invoked
1394      */
1395    public void updateAsciiStream(int columnIndex , java.io.InputStream x ,int length) throws SQLException {
1396 
1397       boolean bool;
1398 
1399       if(onInsertRow) {
1400          if(p != null) {
1401              bool = p.evaluate(x,columnIndex);
1402 
1403              if(!bool) {
1404                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1405              }
1406          }
1407       }
1408 
1409       super.updateAsciiStream(columnIndex,x,length);
1410    }
1411 
1412    /**
1413      * Sets the designated column in either the current row or the insert
1414      * row of this <code>CachedRowSetImpl</code> object with the given
1415      * ASCII stream value.
1416      * <P>
1417      * This method updates a column value in either the current row or
1418      * the insert row of this rowset, but it does not update the
1419      * database.  If the cursor is on a row in the rowset, the
1420      * method {@link #updateRow} must be called to update the database.
1421      * If the cursor is on the insert row, the method {@link #insertRow}
1422      * must be called, which will insert the new row into both this rowset
1423      * and the database. Both of these methods must be called before the
1424      * cursor moves to another row.
1425      *
1426      * @param columnName a <code>String</code> object that must match the
1427      *        SQL name of a column in this rowset, ignoring case
1428      * @param x the new column value
1429      * @param length the number of one-byte ASCII characters in the stream
1430      */
1431    public void updateAsciiStream(String columnName , java.io.InputStream x , int length) throws SQLException {
1432 
1433       this.updateAsciiStream(findColumn(columnName),x,length);
1434    }
1435 
1436    /**
1437      * Sets the designated column in either the current row or the insert
1438      * row of this <code>CachedRowSetImpl</code> object with the given
1439      * <code>java.io.Reader</code> object.
1440      * <P>
1441      * This method updates a column value in either the current row or
1442      * the insert row of this rowset, but it does not update the
1443      * database.  If the cursor is on a row in the rowset, the
1444      * method {@link #updateRow} must be called to update the database.
1445      * If the cursor is on the insert row, the method {@link #insertRow}
1446      * must be called, which will insert the new row into both this rowset
1447      * and the database. Both of these methods must be called before the
1448      * cursor moves to another row.
1449      *
1450      * @param columnIndex the first column is <code>1</code>, the second
1451      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1452      *        and equal to or less than the number of columns in this rowset
1453      * @param x the new column value; must be a <code>java.io.Reader</code>
1454      *          containing <code>BINARY</code>, <code>VARBINARY</code>,
1455      *          <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,
1456      *          or <code>LONGVARCHAR</code> data
1457      * @param length the length of the stream in characters
1458      * @throws SQLException if (1) the given column index is out of bounds,
1459      *            (2) the cursor is not on one of this rowset's rows or its
1460      *            insert row, (3) the data in the stream is not a binary or
1461      *            character type, or (4) this rowset is
1462      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1463      */
1464    public void updateCharacterStream(int columnIndex , java.io.Reader x , int length) throws SQLException {
1465 
1466       boolean bool;
1467 
1468       if(onInsertRow) {
1469          if(p != null) {
1470              bool = p.evaluate(x,columnIndex);
1471 
1472              if(!bool) {
1473                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1474              }
1475          }
1476       }
1477 
1478       super.updateCharacterStream(columnIndex,x,length);
1479    }
1480 
1481    /**
1482      * Sets the designated column in either the current row or the insert
1483      * row of this <code>CachedRowSetImpl</code> object with the given
1484      * <code>java.io.Reader</code> object.
1485      * <P>
1486      * This method updates a column value in either the current row or
1487      * the insert row of this rowset, but it does not update the
1488      * database.  If the cursor is on a row in the rowset, the
1489      * method {@link #updateRow} must be called to update the database.
1490      * If the cursor is on the insert row, the method {@link #insertRow}
1491      * must be called, which will insert the new row into both this rowset
1492      * and the database. Both of these methods must be called before the
1493      * cursor moves to another row.
1494      *
1495      * @param columnName a <code>String</code> object that must match the
1496      *        SQL name of a column in this rowset, ignoring case
1497      * @param reader the new column value; must be a
1498      * <code>java.io.Reader</code> containing <code>BINARY</code>,
1499      * <code>VARBINARY</code>, <code>LONGVARBINARY</code>, <code>CHAR</code>,
1500      * <code>VARCHAR</code>, or <code>LONGVARCHAR</code> data
1501      * @param length the length of the stream in characters
1502      * @throws SQLException if (1) the given column name does not match the
1503      *            name of a column in this rowset, (2) the cursor is not on
1504      *            one of this rowset's rows or its insert row, (3) the data
1505      *            in the stream is not a binary or character type, or (4) this
1506      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1507      */
1508    public void updateCharacterStream(String columnName , java.io.Reader reader, int length) throws SQLException {
1509       this.updateCharacterStream(findColumn(columnName), reader, length);
1510    }
1511 
1512    /**
1513      * Sets the designated column in either the current row or the insert
1514      * row of this <code>CachedRowSetImpl</code> object with the given
1515      * <code>java.io.InputStream</code> object.
1516      * <P>
1517      * This method updates a column value in either the current row or
1518      * the insert row of this rowset, but it does not update the
1519      * database.  If the cursor is on a row in the rowset, the
1520      * method {@link #updateRow} must be called to update the database.
1521      * If the cursor is on the insert row, the method {@link #insertRow}
1522      * must be called, which will insert the new row into both this rowset
1523      * and the database. Both of these methods must be called before the
1524      * cursor moves to another row.
1525      *
1526      * @param columnIndex the first column is <code>1</code>, the second
1527      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1528      *        and equal to or less than the number of columns in this rowset
1529      * @param x the new column value; must be a <code>java.io.InputStream</code>
1530      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
1531      *          <code>LONGVARBINARY</code> data
1532      * @param length the length of the stream in bytes
1533      * @throws SQLException if (1) the given column index is out of bounds,
1534      *            (2) the cursor is not on one of this rowset's rows or its
1535      *            insert row, (3) the data in the stream is not binary, or
1536      *            (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1537      */
1538    public void updateBinaryStream(int columnIndex , java.io.InputStream x , int length) throws SQLException {
1539 
1540       boolean bool;
1541 
1542       if(onInsertRow) {
1543          if(p != null) {
1544              bool = p.evaluate(x,columnIndex);
1545 
1546              if(!bool) {
1547                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1548              }
1549          }
1550       }
1551 
1552       super.updateBinaryStream(columnIndex,x,length);
1553    }
1554 
1555    /**
1556      * Sets the designated column in either the current row or the insert
1557      * row of this <code>CachedRowSetImpl</code> object with the given
1558      * <code>java.io.InputStream</code> object.
1559      * <P>
1560      * This method updates a column value in either the current row or
1561      * the insert row of this rowset, but it does not update the
1562      * database.  If the cursor is on a row in the rowset, the
1563      * method {@link #updateRow} must be called to update the database.
1564      * If the cursor is on the insert row, the method {@link #insertRow}
1565      * must be called, which will insert the new row into both this rowset
1566      * and the database. Both of these methods must be called before the
1567      * cursor moves to another row.
1568      *
1569      * @param columnName a <code>String</code> object that must match the
1570      *        SQL name of a column in this rowset, ignoring case
1571      * @param x the new column value; must be a <code>java.io.InputStream</code>
1572      *          containing <code>BINARY</code>, <code>VARBINARY</code>, or
1573      *          <code>LONGVARBINARY</code> data
1574      * @param length the length of the stream in bytes
1575      * @throws SQLException if (1) the given column name does not match the
1576      *            name of a column in this rowset, (2) the cursor is not on
1577      *            one of this rowset's rows or its insert row, (3) the data
1578      *            in the stream is not binary, or (4) this rowset is
1579      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1580      */
1581    public void updateBinaryStream(String columnName , java.io.InputStream x, int length) throws SQLException {
1582 
1583       this.updateBinaryStream(findColumn(columnName),x,length);
1584    }
1585 
1586    /**
1587      * Sets the designated column in either the current row or the insert
1588      * row of this <code>CachedRowSetImpl</code> object with the given
1589      * <code>Object</code> value.
1590      * <P>
1591      * This method updates a column value in either the current row or
1592      * the insert row of this rowset, but it does not update the
1593      * database.  If the cursor is on a row in the rowset, the
1594      * method {@link #updateRow} must be called to update the database.
1595      * If the cursor is on the insert row, the method {@link #insertRow}
1596      * must be called, which will insert the new row into both this rowset
1597      * and the database. Both of these methods must be called before the
1598      * cursor moves to another row.
1599      *
1600      * @param columnIndex the first column is <code>1</code>, the second
1601      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1602      *        and equal to or less than the number of columns in this rowset
1603      * @param x the new column value
1604      * @throws SQLException if (1) the given column index is out of bounds,
1605      *            (2) the cursor is not on one of this rowset's rows or its
1606      *            insert row, or (3) this rowset is
1607      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1608      */
1609    public void updateObject(int columnIndex , Object x) throws SQLException {
1610 
1611       boolean bool;
1612 
1613       if(onInsertRow) {
1614          if(p != null) {
1615              bool = p.evaluate(x,columnIndex);
1616 
1617              if(!bool) {
1618                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1619              }
1620          }
1621       }
1622 
1623       super.updateObject(columnIndex,x);
1624    }
1625 
1626    /**
1627      * Sets the designated column in either the current row or the insert
1628      * row of this <code>CachedRowSetImpl</code> object with the given
1629      * <code>Object</code> value.
1630      * <P>
1631      * This method updates a column value in either the current row or
1632      * the insert row of this rowset, but it does not update the
1633      * database.  If the cursor is on a row in the rowset, the
1634      * method {@link #updateRow} must be called to update the database.
1635      * If the cursor is on the insert row, the method {@link #insertRow}
1636      * must be called, which will insert the new row into both this rowset
1637      * and the database. Both of these methods must be called before the
1638      * cursor moves to another row.
1639      *
1640      * @param columnName a <code>String</code> object that must match the
1641      *        SQL name of a column in this rowset, ignoring case
1642      * @param x the new column value
1643      * @throws SQLException if (1) the given column name does not match the
1644      *            name of a column in this rowset, (2) the cursor is not on
1645      *            one of this rowset's rows or its insert row, or (3) this
1646      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1647      */
1648    public void updateObject(String columnName , Object x) throws SQLException {
1649 
1650       this.updateObject(findColumn(columnName),x);
1651    }
1652 
1653    /**
1654      * Sets the designated column in either the current row or the insert
1655      * row of this <code>CachedRowSetImpl</code> object with the given
1656      * <code>Object</code> value.  The <code>scale</code> parameter indicates
1657      * the number of digits to the right of the decimal point and is ignored
1658      * if the new column value is not a type that will be mapped to an SQL
1659      * <code>DECIMAL</code> or <code>NUMERIC</code> value.
1660      * <P>
1661      * This method updates a column value in either the current row or
1662      * the insert row of this rowset, but it does not update the
1663      * database.  If the cursor is on a row in the rowset, the
1664      * method {@link #updateRow} must be called to update the database.
1665      * If the cursor is on the insert row, the method {@link #insertRow}
1666      * must be called, which will insert the new row into both this rowset
1667      * and the database. Both of these methods must be called before the
1668      * cursor moves to another row.
1669      *
1670      * @param columnIndex the first column is <code>1</code>, the second
1671      *        is <code>2</code>, and so on; must be <code>1</code> or larger
1672      *        and equal to or less than the number of columns in this rowset
1673      * @param x the new column value
1674      * @param scale the number of digits to the right of the decimal point (for
1675      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
1676      * @throws SQLException if (1) the given column index is out of bounds,
1677      *            (2) the cursor is not on one of this rowset's rows or its
1678      *            insert row, or (3) this rowset is
1679      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1680      */
1681    public void updateObject(int columnIndex , Object x , int scale) throws SQLException {
1682 
1683       boolean bool;
1684 
1685       if(onInsertRow) {
1686          if(p != null) {
1687              bool = p.evaluate(x,columnIndex);
1688 
1689              if(!bool) {
1690                  throw new SQLException(resBundle.handleGetObject("filteredrowsetimpl.notallowed").toString());
1691              }
1692          }
1693       }
1694 
1695       super.updateObject(columnIndex,x,scale);
1696    }
1697 
1698    /**
1699      * Sets the designated column in either the current row or the insert
1700      * row of this <code>CachedRowSetImpl</code> object with the given
1701      * <code>Object</code> value.  The <code>scale</code> parameter
1702      * indicates the number of digits to the right of the decimal point
1703      * and is ignored if the new column value is not a type that will be
1704      *  mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.
1705      * <P>
1706      * This method updates a column value in either the current row or
1707      * the insert row of this rowset, but it does not update the
1708      * database.  If the cursor is on a row in the rowset, the
1709      * method {@link #updateRow} must be called to update the database.
1710      * If the cursor is on the insert row, the method {@link #insertRow}
1711      * must be called, which will insert the new row into both this rowset
1712      * and the database. Both of these methods must be called before the
1713      * cursor moves to another row.
1714      *
1715      * @param columnName a <code>String</code> object that must match the
1716      *        SQL name of a column in this rowset, ignoring case
1717      * @param x the new column value
1718      * @param scale the number of digits to the right of the decimal point (for
1719      *              <code>DECIMAL</code> and <code>NUMERIC</code> types only)
1720      * @throws SQLException if (1) the given column name does not match the
1721      *            name of a column in this rowset, (2) the cursor is not on
1722      *            one of this rowset's rows or its insert row, or (3) this
1723      *            rowset is <code>ResultSet.CONCUR_READ_ONLY</code>
1724      */
1725    public void updateObject(String columnName , Object x, int scale) throws SQLException {
1726 
1727       this.updateObject(findColumn(columnName),x,scale);
1728    }
1729 
1730    /**
1731      * Inserts the contents of this <code>CachedRowSetImpl</code> object's insert
1732      * row into this rowset immediately following the current row.
1733      * If the current row is the
1734      * position after the last row or before the first row, the new row will
1735      * be inserted at the end of the rowset.  This method also notifies
1736      * listeners registered with this rowset that the row has changed.
1737      * <P>
1738      * The cursor must be on the insert row when this method is called.
1739      *
1740      * @throws SQLException if (1) the cursor is not on the insert row,
1741      *            (2) one or more of the non-nullable columns in the insert
1742      *            row has not been given a value, or (3) this rowset is
1743      *            <code>ResultSet.CONCUR_READ_ONLY</code>
1744      */
1745    public void insertRow() throws SQLException {
1746 
1747       onInsertRow = false;
1748       super.insertRow();
1749    }
1750 
1751    /**
1752     * This method re populates the resBundle
1753     * during the deserialization process
1754     *
1755     */
1756    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
1757        // Default state initialization happens here
1758        ois.defaultReadObject();
1759        // Initialization of transient Res Bundle happens here .
1760        try {
1761           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
1762        } catch(IOException ioe) {
1763            throw new RuntimeException(ioe);
1764        }
1765 
1766    }
1767 
1768    static final long serialVersionUID = 6178454588413509360L;
1769 } // end FilteredRowSetImpl class