Path: blob/master/src/java.sql.rowset/share/classes/com/sun/rowset/JoinRowSetImpl.java
40948 views
/*1* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.rowset;2627import java.sql.*;28import javax.sql.*;29import javax.naming.*;30import java.io.*;31import java.math.*;32import java.util.*;3334import javax.sql.rowset.*;35import javax.sql.rowset.spi.SyncProvider;36import javax.sql.rowset.spi.SyncProviderException;3738/**39* The standard implementation of the <code>JoinRowSet</code>40* interface providing an SQL <code>JOIN</code> between <code>RowSet</code>41* objects.42* <P>43* The implementation provides an ANSI-style <code>JOIN</code> providing an44* inner join between two tables. Any unmatched rows in either table of the45* join are discarded.46* <p>47* Typically, a <code>JoinRowSet</code> implementation is leveraged by48* <code>RowSet</code> instances that are in a disconnected environment and49* thus do not have the luxury of an open connection to the data source to50* establish logical relationships between themselves. In other words, it is51* largely <code>CachedRowSet</code> objects and implementations derived from52* the <code>CachedRowSet</code> interface that will use the <code>JoinRowSetImpl</code>53* implementation.54*55* @author Amit Handa, Jonathan Bruce56*/57public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet {58/**59* A <code>Vector</code> object that contains the <code>RowSet</code> objects60* that have been added to this <code>JoinRowSet</code> object.61*/62private Vector<CachedRowSetImpl> vecRowSetsInJOIN;6364/**65* The <code>CachedRowSet</code> object that encapsulates this66* <code>JoinRowSet</code> object.67* When <code>RowSet</code> objects are added to this <code>JoinRowSet</code>68* object, they are also added to <i>crsInternal</i> to form the same kind of69* SQL <code>JOIN</code>. As a result, methods for making updates to this70* <code>JoinRowSet</code> object can use <i>crsInternal</i> methods in their71* implementations.72*/73private CachedRowSetImpl crsInternal;7475/**76* A <code>Vector</code> object containing the types of join that have been set77* for this <code>JoinRowSet</code> object.78* The last join type set forms the basis of succeeding joins.79*/80private Vector<Integer> vecJoinType;8182/**83* A <code>Vector</code> object containing the names of all the tables entering84* the join.85*/86private Vector<String> vecTableNames;8788/**89* An <code>int</code> that indicates the column index of the match column.90*/91private int iMatchKey;9293/**94* A <code>String</code> object that stores the name of the match column.95*/96private String strMatchKey ;9798/**99* An array of <code>boolean</code> values indicating the types of joins supported100* by this <code>JoinRowSet</code> implementation.101*/102boolean[] supportedJOINs;103104/**105* The <code>WebRowSet</code> object that encapsulates this <code>JoinRowSet</code>106* object. This <code>WebRowSet</code> object allows this <code>JoinRowSet</code>107* object to leverage the properties and methods of a <code>WebRowSet</code>108* object.109*/110private WebRowSet wrs;111112113/**114* Constructor for <code>JoinRowSetImpl</code> class. Configures various internal data115* structures to provide mechanisms required for <code>JoinRowSet</code> interface116* implementation.117*118* @throws SQLException if an error occurs in instantiating an instance of119* <code>JoinRowSetImpl</code>120*/121public JoinRowSetImpl() throws SQLException {122123vecRowSetsInJOIN = new Vector<CachedRowSetImpl>();124crsInternal = new CachedRowSetImpl();125vecJoinType = new Vector<Integer>();126vecTableNames = new Vector<String>();127iMatchKey = -1;128strMatchKey = null;129supportedJOINs =130new boolean[] {false, true, false, false, false};131try {132resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();133} catch(IOException ioe) {134throw new RuntimeException(ioe);135}136137}138139/**140* Adds the given <code>RowSet</code> object to this141* <code>JoinRowSet</code> object. If this142* rowset is the first to be added to the <code>JoinRowSet</code>143* object, it forms the basis for the <code>JOIN</code>144* relationships to be formed.145* <p>146* This method should be used when the given <code>RowSet</code> object147* already has a match column set.148*149* @param rowset the <code>RowSet</code> object that implements the150* <code>Joinable</code> interface and is to be added151* to this <code>JoinRowSet</code> object152* @throws SQLException if an empty <code>RowSet</code> is added to the to the153* <code>JoinRowSet</code>; if a match column is not set; or if an154* additional <code>RowSet</code> violates the active <code>JOIN</code>155* @see CachedRowSet#setMatchColumn156*/157public void addRowSet(Joinable rowset) throws SQLException {158boolean boolColId, boolColName;159160boolColId = false;161boolColName = false;162CachedRowSetImpl cRowset;163164if(!(rowset instanceof RowSet)) {165throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notinstance").toString());166}167168if(rowset instanceof JdbcRowSetImpl ) {169cRowset = new CachedRowSetImpl();170cRowset.populate((RowSet)rowset);171if(cRowset.size() == 0){172throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.emptyrowset").toString());173}174175176try {177int matchColumnCount = 0;178for(int i=0; i< rowset.getMatchColumnIndexes().length; i++) {179if(rowset.getMatchColumnIndexes()[i] != -1)180++ matchColumnCount;181else182break;183}184int[] pCol = new int[matchColumnCount];185for(int i=0; i<matchColumnCount; i++)186pCol[i] = rowset.getMatchColumnIndexes()[i];187cRowset.setMatchColumn(pCol);188} catch(SQLException sqle) {189190}191192} else {193cRowset = (CachedRowSetImpl)rowset;194if(cRowset.size() == 0){195throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.emptyrowset").toString());196}197}198199// Either column id or column name will be set200// If both not set throw exception.201202try {203iMatchKey = (cRowset.getMatchColumnIndexes())[0];204} catch(SQLException sqle) {205//if not set catch the exception but do nothing now.206boolColId = true;207}208209try {210strMatchKey = (cRowset.getMatchColumnNames())[0];211} catch(SQLException sqle) {212//if not set catch the exception but do nothing now.213boolColName = true;214}215216if(boolColId && boolColName) {217// neither setter methods have been used to set218throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.matchnotset").toString());219} else {220//if(boolColId || boolColName)221// either of the setter methods have been set.222if(boolColId){223//224ArrayList<Integer> indices = new ArrayList<>();225for(int i=0;i<cRowset.getMatchColumnNames().length;i++) {226if( (strMatchKey = (cRowset.getMatchColumnNames())[i]) != null) {227iMatchKey = cRowset.findColumn(strMatchKey);228indices.add(iMatchKey);229}230else231break;232}233int[] indexes = new int[indices.size()];234for(int i=0; i<indices.size();i++)235indexes[i] = indices.get(i);236cRowset.setMatchColumn(indexes);237// Set the match column here because join will be238// based on columnId,239// (nested for loop in initJOIN() checks for equality240// based on columnIndex)241} else {242//do nothing, iMatchKey is set.243}244// Now both iMatchKey and strMatchKey have been set pointing245// to the same column246}247248// Till first rowset setJoinType may not be set because249// default type is JoinRowSet.INNER_JOIN which should250// be set and for subsequent additions of rowset, if not set251// keep on adding join type as JoinRowSet.INNER_JOIN252// to vecJoinType.253254initJOIN(cRowset);255}256257/**258* Adds the given <code>RowSet</code> object to the <code>JOIN</code> relation259* and sets the designated column as the match column.260* If the given <code>RowSet</code>261* object is the first to be added to this <code>JoinRowSet</code>262* object, it forms the basis of the <code>JOIN</code> relationship to be formed263* when other <code>RowSet</code> objects are added .264* <P>265* This method should be used when the given <code>RowSet</code> object266* does not already have a match column set.267*268* @param rowset a <code>RowSet</code> object to be added to269* the <code>JOIN</code> relation; must implement the <code>Joinable</code>270* interface271* @param columnIdx an <code>int</code> giving the index of the column to be set as272* the match column273* @throws SQLException if (1) an empty <code>RowSet</code> object is added to this274* <code>JoinRowSet</code> object, (2) a match column has not been set,275* or (3) the <code>RowSet</code> object being added violates the active276* <code>JOIN</code>277* @see CachedRowSet#unsetMatchColumn278*/279public void addRowSet(RowSet rowset, int columnIdx) throws SQLException {280//passing the rowset as well as the columnIdx to form the joinrowset.281282((CachedRowSetImpl)rowset).setMatchColumn(columnIdx);283284addRowSet((Joinable)rowset);285}286287/**288* Adds the given <code>RowSet</code> object to the <code>JOIN</code> relationship289* and sets the designated column as the match column. If the given290* <code>RowSet</code>291* object is the first to be added to this <code>JoinRowSet</code>292* object, it forms the basis of the <code>JOIN</code> relationship to be formed293* when other <code>RowSet</code> objects are added .294* <P>295* This method should be used when the given <code>RowSet</code> object296* does not already have a match column set.297*298* @param rowset a <code>RowSet</code> object to be added to299* the <code>JOIN</code> relation300* @param columnName a <code>String</code> object giving the name of the column301* to be set as the match column; must implement the <code>Joinable</code>302* interface303* @throws SQLException if (1) an empty <code>RowSet</code> object is added to this304* <code>JoinRowSet</code> object, (2) a match column has not been set,305* or (3) the <code>RowSet</code> object being added violates the active306* <code>JOIN</code>307*/308public void addRowSet(RowSet rowset, String columnName) throws SQLException {309//passing the rowset as well as the columnIdx to form the joinrowset.310((CachedRowSetImpl)rowset).setMatchColumn(columnName);311addRowSet((Joinable)rowset);312}313314/**315* Adds the given <code>RowSet</code> objects to the <code>JOIN</code> relationship316* and sets the designated columns as the match columns. If the first317* <code>RowSet</code> object in the array of <code>RowSet</code> objects318* is the first to be added to this <code>JoinRowSet</code>319* object, it forms the basis of the <code>JOIN</code> relationship to be formed320* when other <code>RowSet</code> objects are added.321* <P>322* The first <code>int</code>323* in <i>columnIdx</i> is used to set the match column for the first324* <code>RowSet</code> object in <i>rowset</i>, the second <code>int</code>325* in <i>columnIdx</i> is used to set the match column for the second326* <code>RowSet</code> object in <i>rowset</i>, and so on.327* <P>328* This method should be used when the given <code>RowSet</code> objects329* do not already have match columns set.330*331* @param rowset an array of <code>RowSet</code> objects to be added to332* the <code>JOIN</code> relation; each <code>RowSet</code> object must333* implement the <code>Joinable</code> interface334* @param columnIdx an array of <code>int</code> values designating the columns335* to be set as the336* match columns for the <code>RowSet</code> objects in <i>rowset</i>337* @throws SQLException if the number of <code>RowSet</code> objects in338* <i>rowset</i> is not equal to the number of <code>int</code> values339* in <i>columnIdx</i>340*/341public void addRowSet(RowSet[] rowset,342int[] columnIdx) throws SQLException {343//validate if length of rowset array is same as length of int array.344if(rowset.length != columnIdx.length) {345throw new SQLException346(resBundle.handleGetObject("joinrowsetimpl.numnotequal").toString());347} else {348for(int i=0; i< rowset.length; i++) {349((CachedRowSetImpl)rowset[i]).setMatchColumn(columnIdx[i]);350addRowSet((Joinable)rowset[i]);351} //end for352} //end if353354}355356357/**358* Adds the given <code>RowSet</code> objects to the <code>JOIN</code> relationship359* and sets the designated columns as the match columns. If the first360* <code>RowSet</code> object in the array of <code>RowSet</code> objects361* is the first to be added to this <code>JoinRowSet</code>362* object, it forms the basis of the <code>JOIN</code> relationship to be formed363* when other <code>RowSet</code> objects are added.364* <P>365* The first <code>String</code> object366* in <i>columnName</i> is used to set the match column for the first367* <code>RowSet</code> object in <i>rowset</i>, the second <code>String</code>368* object in <i>columnName</i> is used to set the match column for the second369* <code>RowSet</code> object in <i>rowset</i>, and so on.370* <P>371* This method should be used when the given <code>RowSet</code> objects372* do not already have match columns set.373*374* @param rowset an array of <code>RowSet</code> objects to be added to375* the <code>JOIN</code> relation; each <code>RowSet</code> object must376* implement the <code>Joinable</code> interface377* @param columnName an array of <code>String</code> objects designating the columns378* to be set as the379* match columns for the <code>RowSet</code> objects in <i>rowset</i>380* @throws SQLException if the number of <code>RowSet</code> objects in381* <i>rowset</i> is not equal to the number of <code>String</code> objects382* in <i>columnName</i>, an empty <code>JdbcRowSet</code> is added to the383* <code>JoinRowSet</code>, if a match column is not set,384* or one or the <code>RowSet</code> objects in <i>rowset</i> violates the385* active <code>JOIN</code>386*/387public void addRowSet(RowSet[] rowset,388String[] columnName) throws SQLException {389//validate if length of rowset array is same as length of int array.390391if(rowset.length != columnName.length) {392throw new SQLException393(resBundle.handleGetObject("joinrowsetimpl.numnotequal").toString());394} else {395for(int i=0; i< rowset.length; i++) {396((CachedRowSetImpl)rowset[i]).setMatchColumn(columnName[i]);397addRowSet((Joinable)rowset[i]);398} //end for399} //end if400401}402403/**404* Returns a Collection of the <code>RowSet</code> object instances405* currently residing with the instance of the <code>JoinRowSet</code>406* object instance. This should return the 'n' number of RowSet contained407* within the JOIN and maintain any updates that have occoured while in408* this union.409*410* @return A <code>Collection</code> of the added <code>RowSet</code>411* object instances412* @throws SQLException if an error occours generating a collection413* of the originating RowSets contained within the JOIN.414*/415@SuppressWarnings("rawtypes")416public Collection getRowSets() throws SQLException {417return vecRowSetsInJOIN;418}419420/**421* Returns a string array of the RowSet names currently residing422* with the <code>JoinRowSet</code> object instance.423*424* @return a string array of the RowSet names425* @throws SQLException if an error occours retrieving the RowSet names426* @see CachedRowSet#setTableName427*/428public String[] getRowSetNames() throws SQLException {429Object [] arr = vecTableNames.toArray();430String []strArr = new String[arr.length];431432for( int i = 0;i < arr.length; i++) {433strArr[i] = arr[i].toString();434}435436return strArr;437}438439/**440* Creates a separate <code>CachedRowSet</code> object that contains the data441* in this <code>JoinRowSet</code> object.442* <P>443* If any updates or modifications have been applied to this <code>JoinRowSet</code>444* object, the <code>CachedRowSet</code> object returned by this method will445* not be able to persist446* the changes back to the originating rows and tables in the447* data source because the data may be from different tables. The448* <code>CachedRowSet</code> instance returned should not449* contain modification data, such as whether a row has been updated or what the450* original values are. Also, the <code>CachedRowSet</code> object should clear451* its properties pertaining to452* its originating SQL statement. An application should reset the453* SQL statement using the <code>RowSet.setCommand</code> method.454* <p>455* To persist changes back to the data source, the <code>JoinRowSet</code> object456* calls the method <code>acceptChanges</code>. Implementations457* can leverage the internal data and update tracking in their458* implementations to interact with the <code>SyncProvider</code> to persist any459* changes.460*461* @return a <code>CachedRowSet</code> object containing the contents of this462* <code>JoinRowSet</code> object463* @throws SQLException if an error occurs assembling the <code>CachedRowSet</code>464* object465* @see javax.sql.RowSet466* @see javax.sql.rowset.CachedRowSet467* @see javax.sql.rowset.spi.SyncProvider468*/469public CachedRowSet toCachedRowSet() throws SQLException {470return crsInternal;471}472473/**474* Returns <code>true</code> if this <code>JoinRowSet</code> object supports475* an SQL <code>CROSS_JOIN</code> and <code>false</code> if it does not.476*477* @return <code>true</code> if the CROSS_JOIN is supported; <code>false</code>478* otherwise479*/480public boolean supportsCrossJoin() {481return supportedJOINs[JoinRowSet.CROSS_JOIN];482}483484/**485* Returns <code>true</code> if this <code>JoinRowSet</code> object supports486* an SQL <code>INNER_JOIN</code> and <code>false</code> if it does not.487*488* @return true is the INNER_JOIN is supported; false otherwise489*/490public boolean supportsInnerJoin() {491return supportedJOINs[JoinRowSet.INNER_JOIN];492}493494/**495* Returns <code>true</code> if this <code>JoinRowSet</code> object supports496* an SQL <code>LEFT_OUTER_JOIN</code> and <code>false</code> if it does not.497*498* @return true is the LEFT_OUTER_JOIN is supported; false otherwise499*/500public boolean supportsLeftOuterJoin() {501return supportedJOINs[JoinRowSet.LEFT_OUTER_JOIN];502}503504/**505* Returns <code>true</code> if this <code>JoinRowSet</code> object supports506* an SQL <code>RIGHT_OUTER_JOIN</code> and <code>false</code> if it does not.507*508* @return true is the RIGHT_OUTER_JOIN is supported; false otherwise509*/510public boolean supportsRightOuterJoin() {511return supportedJOINs[JoinRowSet.RIGHT_OUTER_JOIN];512}513514/**515* Returns <code>true</code> if this <code>JoinRowSet</code> object supports516* an SQL <code>FULL_JOIN</code> and <code>false</code> if it does not.517*518* @return true is the FULL_JOIN is supported; false otherwise519*/520public boolean supportsFullJoin() {521return supportedJOINs[JoinRowSet.FULL_JOIN];522523}524525/**526* Sets the type of SQL <code>JOIN</code> that this <code>JoinRowSet</code>527* object will use. This method528* allows an application to adjust the type of <code>JOIN</code> imposed529* on tables contained within this <code>JoinRowSet</code> object and to do it530* on the fly. The last <code>JOIN</code> type set determines the type of531* <code>JOIN</code> to be performed.532* <P>533* Implementations should throw an <code>SQLException</code> if they do534* not support the given <code>JOIN</code> type.535*536* @param type one of the standard <code>JoinRowSet</code> constants537* indicating the type of <code>JOIN</code>. Must be one of the538* following:539* <code>JoinRowSet.CROSS_JOIN</code>540* <code>JoinRowSet.INNER_JOIN</code>541* <code>JoinRowSet.LEFT_OUTER_JOIN</code>542* <code>JoinRowSet.RIGHT_OUTER_JOIN</code>, or543* <code>JoinRowSet.FULL_JOIN</code>544* @throws SQLException if an unsupported <code>JOIN</code> type is set545*/546public void setJoinType(int type) throws SQLException {547// The join which governs the join of two rowsets is the last548// join set, using setJoinType549550if (type >= JoinRowSet.CROSS_JOIN && type <= JoinRowSet.FULL_JOIN) {551if (type != JoinRowSet.INNER_JOIN) {552// This 'if' will be removed after all joins are implemented.553throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notsupported").toString());554} else {555Integer Intgr = Integer.valueOf(JoinRowSet.INNER_JOIN);556vecJoinType.add(Intgr);557}558} else {559throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notdefined").toString());560} //end if561}562563564/**565* This checks for a match column for566* whether it exists or not.567*568* @param <code>CachedRowSet</code> object whose match column needs to be checked.569* @throws SQLException if MatchColumn is not set.570*/571private boolean checkforMatchColumn(Joinable rs) throws SQLException {572int[] i = rs.getMatchColumnIndexes();573if (i.length <= 0) {574return false;575}576return true;577}578579/**580* Internal initialization of <code>JoinRowSet</code>.581*/582private void initJOIN(CachedRowSet rowset) throws SQLException {583try {584585CachedRowSetImpl cRowset = (CachedRowSetImpl)rowset;586// Create a new CachedRowSet object local to this function.587CachedRowSetImpl crsTemp = new CachedRowSetImpl();588RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl();589590/* The following 'if block' seems to be always going true.591commenting this out for present592593if (!supportedJOINs[1]) {594throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.notsupported").toString());595}596597*/598599if (vecRowSetsInJOIN.isEmpty() ) {600601// implies first cRowset to be added to the Join602// simply add this as a CachedRowSet.603// Also add it to the class variable of type vector604// do not need to check "type" of Join but it should be set.605crsInternal = (CachedRowSetImpl)rowset.createCopy();606crsInternal.setMetaData((RowSetMetaDataImpl)cRowset.getMetaData());607// metadata will also set the MatchColumn.608609vecRowSetsInJOIN.add(cRowset);610611} else {612// At this point we are ready to add another rowset to 'this' object613// Check the size of vecJoinType and vecRowSetsInJoin614615// If nothing is being set, internally call setJoinType()616// to set to JoinRowSet.INNER_JOIN.617618// For two rowsets one (valid) entry should be there in vecJoinType619// For three rowsets two (valid) entries should be there in vecJoinType620621// Maintain vecRowSetsInJoin = vecJoinType + 1622623624if( (vecRowSetsInJOIN.size() - vecJoinType.size() ) == 2 ) {625// we are going to add next rowset and setJoinType has not been set626// recently, so set it to setJoinType() to JoinRowSet.INNER_JOIN.627// the default join type628629setJoinType(JoinRowSet.INNER_JOIN);630} else if( (vecRowSetsInJOIN.size() - vecJoinType.size() ) == 1 ) {631// do nothing setjoinType() has been set by programmer632}633634// Add the table names to the class variable of type vector.635vecTableNames.add(crsInternal.getTableName());636vecTableNames.add(cRowset.getTableName());637// Now we have two rowsets crsInternal and cRowset which need638// to be INNER JOIN'ED to form a new rowset639// Compare table1.MatchColumn1.value1 == { table2.MatchColumn2.value1640// ... upto table2.MatchColumn2.valueN }641// ...642// Compare table1.MatchColumn1.valueM == { table2.MatchColumn2.value1643// ... upto table2.MatchColumn2.valueN }644//645// Assuming first rowset has M rows and second N rows.646647int rowCount2 = cRowset.size();648int rowCount1 = crsInternal.size();649650// total columns in the new CachedRowSet will be sum of both -1651// (common column)652int matchColumnCount = 0;653for(int i=0; i< crsInternal.getMatchColumnIndexes().length; i++) {654if(crsInternal.getMatchColumnIndexes()[i] != -1)655++ matchColumnCount;656else657break;658}659660rsmd.setColumnCount661(crsInternal.getMetaData().getColumnCount() +662cRowset.getMetaData().getColumnCount() - matchColumnCount);663664crsTemp.setMetaData(rsmd);665crsInternal.beforeFirst();666cRowset.beforeFirst();667for (int i = 1 ; i <= rowCount1 ; i++) {668if(crsInternal.isAfterLast() ) {669break;670}671if(crsInternal.next()) {672cRowset.beforeFirst();673for(int j = 1 ; j <= rowCount2 ; j++) {674if( cRowset.isAfterLast()) {675break;676}677if(cRowset.next()) {678boolean match = true;679for(int k=0; k<matchColumnCount; k++) {680if (!crsInternal.getObject( crsInternal.getMatchColumnIndexes()[k]).equals681(cRowset.getObject(cRowset.getMatchColumnIndexes()[k]))) {682match = false;683break;684}685}686if (match) {687688int p;689int colc = 0; // reset this variable everytime you loop690// re create a JoinRowSet in crsTemp object691crsTemp.moveToInsertRow();692693// create a new rowset crsTemp with data from first rowset694for( p=1;695p<=crsInternal.getMetaData().getColumnCount();p++) {696697match = false;698for(int k=0; k<matchColumnCount; k++) {699if (p == crsInternal.getMatchColumnIndexes()[k] ) {700match = true;701break;702}703}704if ( !match ) {705706crsTemp.updateObject(++colc, crsInternal.getObject(p));707// column type also needs to be passed.708709rsmd.setColumnName710(colc, crsInternal.getMetaData().getColumnName(p));711rsmd.setTableName(colc, crsInternal.getTableName());712713rsmd.setColumnType(p, crsInternal.getMetaData().getColumnType(p));714rsmd.setAutoIncrement(p, crsInternal.getMetaData().isAutoIncrement(p));715rsmd.setCaseSensitive(p, crsInternal.getMetaData().isCaseSensitive(p));716rsmd.setCatalogName(p, crsInternal.getMetaData().getCatalogName(p));717rsmd.setColumnDisplaySize(p, crsInternal.getMetaData().getColumnDisplaySize(p));718rsmd.setColumnLabel(p, crsInternal.getMetaData().getColumnLabel(p));719rsmd.setColumnType(p, crsInternal.getMetaData().getColumnType(p));720rsmd.setColumnTypeName(p, crsInternal.getMetaData().getColumnTypeName(p));721rsmd.setCurrency(p,crsInternal.getMetaData().isCurrency(p) );722rsmd.setNullable(p, crsInternal.getMetaData().isNullable(p));723rsmd.setPrecision(p, crsInternal.getMetaData().getPrecision(p));724rsmd.setScale(p, crsInternal.getMetaData().getScale(p));725rsmd.setSchemaName(p, crsInternal.getMetaData().getSchemaName(p));726rsmd.setSearchable(p, crsInternal.getMetaData().isSearchable(p));727rsmd.setSigned(p, crsInternal.getMetaData().isSigned(p));728729} else {730// will happen only once, for that merged column pass731// the types as OBJECT, if types not equal732733crsTemp.updateObject(++colc, crsInternal.getObject(p));734735rsmd.setColumnName(colc, crsInternal.getMetaData().getColumnName(p));736rsmd.setTableName737(colc, crsInternal.getTableName()+738"#"+739cRowset.getTableName());740741742rsmd.setColumnType(p, crsInternal.getMetaData().getColumnType(p));743rsmd.setAutoIncrement(p, crsInternal.getMetaData().isAutoIncrement(p));744rsmd.setCaseSensitive(p, crsInternal.getMetaData().isCaseSensitive(p));745rsmd.setCatalogName(p, crsInternal.getMetaData().getCatalogName(p));746rsmd.setColumnDisplaySize(p, crsInternal.getMetaData().getColumnDisplaySize(p));747rsmd.setColumnLabel(p, crsInternal.getMetaData().getColumnLabel(p));748rsmd.setColumnType(p, crsInternal.getMetaData().getColumnType(p));749rsmd.setColumnTypeName(p, crsInternal.getMetaData().getColumnTypeName(p));750rsmd.setCurrency(p,crsInternal.getMetaData().isCurrency(p) );751rsmd.setNullable(p, crsInternal.getMetaData().isNullable(p));752rsmd.setPrecision(p, crsInternal.getMetaData().getPrecision(p));753rsmd.setScale(p, crsInternal.getMetaData().getScale(p));754rsmd.setSchemaName(p, crsInternal.getMetaData().getSchemaName(p));755rsmd.setSearchable(p, crsInternal.getMetaData().isSearchable(p));756rsmd.setSigned(p, crsInternal.getMetaData().isSigned(p));757758//don't do ++colc in the above statement759} //end if760} //end for761762763// append the rowset crsTemp, with data from second rowset764for(int q=1;765q<= cRowset.getMetaData().getColumnCount();q++) {766767match = false;768for(int k=0; k<matchColumnCount; k++) {769if (q == cRowset.getMatchColumnIndexes()[k] ) {770match = true;771break;772}773}774if ( !match ) {775776crsTemp.updateObject(++colc, cRowset.getObject(q));777778rsmd.setColumnName779(colc, cRowset.getMetaData().getColumnName(q));780rsmd.setTableName(colc, cRowset.getTableName());781782/**783* This will happen for a special case scenario. The value of 'p'784* will always be one more than the number of columns in the first785* rowset in the join. So, for a value of 'q' which is the number of786* columns in the second rowset that participates in the join.787* So decrement value of 'p' by 1 else `p+q-1` will be out of range.788**/789790//if((p+q-1) > ((crsInternal.getMetaData().getColumnCount()) +791// (cRowset.getMetaData().getColumnCount()) - 1)) {792// --p;793//}794rsmd.setColumnType(p+q-1, cRowset.getMetaData().getColumnType(q));795rsmd.setAutoIncrement(p+q-1, cRowset.getMetaData().isAutoIncrement(q));796rsmd.setCaseSensitive(p+q-1, cRowset.getMetaData().isCaseSensitive(q));797rsmd.setCatalogName(p+q-1, cRowset.getMetaData().getCatalogName(q));798rsmd.setColumnDisplaySize(p+q-1, cRowset.getMetaData().getColumnDisplaySize(q));799rsmd.setColumnLabel(p+q-1, cRowset.getMetaData().getColumnLabel(q));800rsmd.setColumnType(p+q-1, cRowset.getMetaData().getColumnType(q));801rsmd.setColumnTypeName(p+q-1, cRowset.getMetaData().getColumnTypeName(q));802rsmd.setCurrency(p+q-1,cRowset.getMetaData().isCurrency(q) );803rsmd.setNullable(p+q-1, cRowset.getMetaData().isNullable(q));804rsmd.setPrecision(p+q-1, cRowset.getMetaData().getPrecision(q));805rsmd.setScale(p+q-1, cRowset.getMetaData().getScale(q));806rsmd.setSchemaName(p+q-1, cRowset.getMetaData().getSchemaName(q));807rsmd.setSearchable(p+q-1, cRowset.getMetaData().isSearchable(q));808rsmd.setSigned(p+q-1, cRowset.getMetaData().isSigned(q));809}810else {811--p;812}813}814crsTemp.insertRow();815crsTemp.moveToCurrentRow();816817} else {818// since not equa12819// so do nothing820} //end if821// bool1 = cRowset.next();822}823824} // end inner for825//bool2 = crsInternal.next();826}827828} //end outer for829crsTemp.setMetaData(rsmd);830crsTemp.setOriginal();831832// Now the join is done.833// Make crsInternal = crsTemp, to be ready for next merge, if at all.834835int[] pCol = new int[matchColumnCount];836for(int i=0; i<matchColumnCount; i++)837pCol[i] = crsInternal.getMatchColumnIndexes()[i];838839crsInternal = (CachedRowSetImpl)crsTemp.createCopy();840841// Because we add the first rowset as crsInternal to the842// merged rowset, so pCol will point to the Match column.843// until reset, am not sure we should set this or not(?)844// if this is not set next inner join won't happen845// if we explicitly do not set a set MatchColumn of846// the new crsInternal.847848crsInternal.setMatchColumn(pCol);849// Add the merged rowset to the class variable of type vector.850crsInternal.setMetaData(rsmd);851vecRowSetsInJOIN.add(cRowset);852} //end if853} catch(SQLException sqle) {854// %%% Exception should not dump here:855sqle.printStackTrace();856throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.initerror").toString() + sqle);857} catch (Exception e) {858e.printStackTrace();859throw new SQLException(resBundle.handleGetObject("joinrowsetimpl.genericerr").toString() + e);860}861}862863/**864* Return a SQL-like description of the <code>WHERE</code> clause being used865* in a <code>JoinRowSet</code> object instance. An implementation can describe866* the <code>WHERE</code> clause of the SQL <code>JOIN</code> by supplying a <code>SQL</code>867* strings description of <code>JOIN</code> or provide a textual description to assist868* applications using a <code>JoinRowSet</code>.869*870* @return whereClause a textual or SQL descripition of the logical871* <code>WHERE</code> cluase used in the <code>JoinRowSet</code> instance872* @throws SQLException if an error occurs in generating a representation873* of the <code>WHERE</code> clause.874*/875public String getWhereClause() throws SQLException {876877String strWhereClause = "Select ";878String whereClause;879String tabName= "";880String strTabName = "";881int sz,cols;882int j;883CachedRowSetImpl crs;884885// get all the column(s) names from each rowset.886// append them with their tablenames i.e. tableName.columnName887// Select tableName1.columnName1,..., tableNameX.columnNameY888// from tableName1,...tableNameX where889// tableName1.(rowset1.getMatchColumnName()) ==890// tableName2.(rowset2.getMatchColumnName()) + "and" +891// tableNameX.(rowsetX.getMatchColumnName()) ==892// tableNameZ.(rowsetZ.getMatchColumnName()));893894sz = vecRowSetsInJOIN.size();895for(int i=0;i<sz; i++) {896crs = vecRowSetsInJOIN.get(i);897cols = crs.getMetaData().getColumnCount();898tabName = tabName.concat(crs.getTableName());899strTabName = strTabName.concat(tabName+", ");900j = 1;901while(j<cols) {902903strWhereClause = strWhereClause.concat904(tabName+"."+crs.getMetaData().getColumnName(j++));905strWhereClause = strWhereClause.concat(", ");906} //end while907} //end for908909910// now remove the last ","911strWhereClause = strWhereClause.substring912(0, strWhereClause.lastIndexOf(','));913914// Add from clause915strWhereClause = strWhereClause.concat(" from ");916917// Add the table names.918strWhereClause = strWhereClause.concat(strTabName);919920//Remove the last ","921strWhereClause = strWhereClause.substring922(0, strWhereClause.lastIndexOf(','));923924// Add the where clause925strWhereClause = strWhereClause.concat(" where ");926927// Get the match columns928// rowset1.getMatchColumnName() == rowset2.getMatchColumnName()929for(int i=0;i<sz; i++) {930strWhereClause = strWhereClause.concat(931vecRowSetsInJOIN.get(i).getMatchColumnNames()[0]);932if(i%2!=0) {933strWhereClause = strWhereClause.concat("=");934} else {935strWhereClause = strWhereClause.concat(" and");936}937strWhereClause = strWhereClause.concat(" ");938}939940return strWhereClause;941}942943944/**945* Moves the cursor down one row from its current position and946* returns <code>true</code> if the new cursor position is a947* valid row.948* The cursor for a new <code>ResultSet</code> object is initially949* positioned before the first row. The first call to the method950* <code>next</code> moves the cursor to the first row, making it951* the current row; the second call makes the second row the952* current row, and so on.953*954* <P>If an input stream from the previous row is open, it is955* implicitly closed. The <code>ResultSet</code> object's warning956* chain is cleared when a new row is read.957*958* @return <code>true</code> if the new current row is valid;959* <code>false</code> if there are no more rows960* @throws SQLException if an error occurs or961* the cursor is not positioned in the rowset, before962* the first row, or after the last row963*/964public boolean next() throws SQLException {965return crsInternal.next();966}967968969/**970* Releases the current contents of this rowset, discarding outstanding971* updates. The rowset contains no rows after the method972* <code>release</code> is called. This method sends a973* <code>RowSetChangedEvent</code> object to all registered listeners prior974* to returning.975*976* @throws SQLException if an error occurs977*/978public void close() throws SQLException {979crsInternal.close();980}981982983/**984* Reports whether the last column read was SQL <code>NULL</code>.985* Note that you must first call the method <code>getXXX</code>986* on a column to try to read its value and then call the method987* <code>wasNull</code> to determine whether the value was988* SQL <code>NULL</code>.989*990* @return <code>true</code> if the value in the last column read991* was SQL <code>NULL</code>; <code>false</code> otherwise992* @throws SQLException if an error occurs993*/994public boolean wasNull() throws SQLException {995return crsInternal.wasNull();996}997998/**999* Retrieves the value of the designated column in the current row1000* of this <code>JoinRowSetImpl</code> object as a1001* <code>String</code> object.1002*1003* @param columnIndex the first column is <code>1</code>, the second1004* is <code>2</code>, and so on; must be <code>1</code> or larger1005* and equal to or less than the number of columns in the rowset1006* @return the column value; if the value is SQL <code>NULL</code>, the1007* result is <code>null</code>1008* @throws SQLException if the given column index is out of bounds or1009* the cursor is not on a valid row1010*/1011public String getString(int columnIndex) throws SQLException {1012return crsInternal.getString(columnIndex);1013}10141015/**1016* Retrieves the value of the designated column in the current row1017* of this <code>JoinRowSetImpl</code> object as a1018* <code>boolean</code> value.1019*1020* @param columnIndex the first column is <code>1</code>, the second1021* is <code>2</code>, and so on; must be <code>1</code> or larger1022* and equal to or less than the number of columns in the rowset1023* @return the column value; if the value is SQL <code>NULL</code>, the1024* result is <code>false</code>1025* @throws SQLException if the given column index is out of bounds,1026* the cursor is not on a valid row, or this method fails1027*/1028public boolean getBoolean(int columnIndex) throws SQLException {1029return crsInternal.getBoolean(columnIndex);1030}10311032/**1033* Retrieves the value of the designated column in the current row1034* of this <code>JoinRowSetImpl</code> object as a1035* <code>byte</code> value.1036*1037* @param columnIndex the first column is <code>1</code>, the second1038* is <code>2</code>, and so on; must be <code>1</code> or larger1039* and equal to or less than the number of columns in the rowset1040* @return the column value; if the value is SQL <code>NULL</code>, the1041* result is <code>0</code>1042* @throws SQLException if the given column index is out of bounds,1043* the cursor is not on a valid row, or this method fails1044*/1045public byte getByte(int columnIndex) throws SQLException {1046return crsInternal.getByte(columnIndex);1047}10481049/**1050* Retrieves the value of the designated column in the current row1051* of this <code>JoinRowSetImpl</code> object as a1052* <code>short</code> value.1053*1054* @param columnIndex the first column is <code>1</code>, the second1055* is <code>2</code>, and so on; must be <code>1</code> or larger1056* and equal to or less than the number of columns in the rowset1057* @return the column value; if the value is SQL <code>NULL</code>, the1058* result is <code>0</code>1059* @throws SQLException if the given column index is out of bounds,1060* the cursor is not on a valid row, or this method fails1061*/1062public short getShort(int columnIndex) throws SQLException {1063return crsInternal.getShort(columnIndex);1064}10651066/**1067* Retrieves the value of the designated column in the current row1068* of this <code>JoinRowSetImpl</code> object as a1069* <code>short</code> value.1070*1071* @param columnIndex the first column is <code>1</code>, the second1072* is <code>2</code>, and so on; must be <code>1</code> or larger1073* and equal to or less than the number of columns in the rowset1074* @return the column value; if the value is SQL <code>NULL</code>, the1075* result is <code>0</code>1076* @throws SQLException if the given column index is out of bounds,1077* the cursor is not on a valid row, or this method fails1078*/1079public int getInt(int columnIndex) throws SQLException {1080return crsInternal.getInt(columnIndex);1081}10821083/**1084* Retrieves the value of the designated column in the current row1085* of this <code>JoinRowSetImpl</code> object as a1086* <code>long</code> value.1087*1088* @param columnIndex the first column is <code>1</code>, the second1089* is <code>2</code>, and so on; must be <code>1</code> or larger1090* and equal to or less than the number of columns in the rowset1091* @return the column value; if the value is SQL <code>NULL</code>, the1092* result is <code>0</code>1093* @throws SQLException if the given column index is out of bounds,1094* the cursor is not on a valid row, or this method fails1095*/1096public long getLong(int columnIndex) throws SQLException {1097return crsInternal.getLong(columnIndex);1098}10991100/**1101* Retrieves the value of the designated column in the current row1102* of this <code>JoinRowSetImpl</code> object as a1103* <code>float</code> value.1104*1105* @param columnIndex the first column is <code>1</code>, the second1106* is <code>2</code>, and so on; must be <code>1</code> or larger1107* and equal to or less than the number of columns in the rowset1108* @return the column value; if the value is SQL <code>NULL</code>, the1109* result is <code>0</code>1110* @throws SQLException if the given column index is out of bounds,1111* the cursor is not on a valid row, or this method fails1112*/1113public float getFloat(int columnIndex) throws SQLException {1114return crsInternal.getFloat(columnIndex);1115}11161117/**1118* Retrieves the value of the designated column in the current row1119* of this <code>JoinRowSetImpl</code> object as a1120* <code>double</code> value.1121*1122* @param columnIndex the first column is <code>1</code>, the second1123* is <code>2</code>, and so on; must be <code>1</code> or larger1124* and equal to or less than the number of columns in the rowset1125* @return the column value; if the value is SQL <code>NULL</code>, the1126* result is <code>0</code>1127* @throws SQLException if the given column index is out of bounds,1128* the cursor is not on a valid row, or this method fails1129*/1130public double getDouble(int columnIndex) throws SQLException {1131return crsInternal.getDouble(columnIndex);1132}11331134/**1135* Retrieves the value of the designated column in the current row1136* of this <code>JoinRowSetImpl</code> object as a1137* <code>java.math.BigDecimal</code> object.1138* <P>1139* This method is deprecated; use the version of <code>getBigDecimal</code>1140* that does not take a scale parameter and returns a value with full1141* precision.1142*1143* @param columnIndex the first column is <code>1</code>, the second1144* is <code>2</code>, and so on; must be <code>1</code> or larger1145* and equal to or less than the number of columns in the rowset1146* @param scale the number of digits to the right of the decimal point in the1147* value returned1148* @return the column value with the specified number of digits to the right1149* of the decimal point; if the value is SQL <code>NULL</code>, the1150* result is <code>null</code>1151* @throws SQLException if the given column index is out of bounds,1152* the cursor is not on a valid row, or this method fails1153* @deprecated1154*/1155@Deprecated1156public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {1157return crsInternal.getBigDecimal(columnIndex);1158}11591160/**1161* Retrieves the value of the designated column in the current row1162* of this <code>JoinRowSetImpl</code> object as a1163* <code>byte array</code> value.1164*1165* @param columnIndex the first column is <code>1</code>, the second1166* is <code>2</code>, and so on; must be <code>1</code> or larger1167* and equal to or less than the number of columns in the rowset1168* @return the column value; if the value is SQL <code>NULL</code>, the1169* result is <code>null</code>1170* @throws SQLException if the given column index is out of bounds,1171* the cursor is not on a valid row, or the value to be1172* retrieved is not binary1173*/1174public byte[] getBytes(int columnIndex) throws SQLException {1175return crsInternal.getBytes(columnIndex);1176}11771178/**1179* Retrieves the value of the designated column in the current row1180* of this <code>JoinRowSetImpl</code> object as a1181* <code>java.sql.Date</code> object.1182*1183* @param columnIndex the first column is <code>1</code>, the second1184* is <code>2</code>, and so on; must be <code>1</code> or larger1185* and equal to or less than the number of columns in the rowset1186* @return the column value; if the value is SQL <code>NULL</code>, the1187* result is <code>null</code>1188* @throws SQLException if the given column index is out of bounds,1189* the cursor is not on a valid row, or this method fails1190*/1191public java.sql.Date getDate(int columnIndex) throws SQLException {1192return crsInternal.getDate(columnIndex);1193}11941195/**1196* Retrieves the value of the designated column in the current row1197* of this <code>JoinRowSetImpl</code> object as a1198* <code>java.sql.Time</code> object.1199*1200* @param columnIndex the first column is <code>1</code>, the second1201* is <code>2</code>, and so on; must be <code>1</code> or larger1202* and equal to or less than the number of columns in the rowset1203* @return the column value; if the value is SQL <code>NULL</code>, the1204* result is <code>null</code>1205* @throws SQLException if the given column index is out of bounds,1206* the cursor is not on a valid row, or this method fails1207*/1208public java.sql.Time getTime(int columnIndex) throws SQLException {1209return crsInternal.getTime(columnIndex);1210}12111212/**1213* Retrieves the value of the designated column in the current row1214* of this <code>JoinRowSetImpl</code> object as a1215* <code>java.sql.Timestamp</code> object.1216*1217* @param columnIndex the first column is <code>1</code>, the second1218* is <code>2</code>, and so on; must be <code>1</code> or larger1219* and equal to or less than the number of columns in the rowset1220* @return the column value; if the value is SQL <code>NULL</code>, the1221* result is <code>null</code>1222* @throws SQLException if the given column index is out of bounds,1223* the cursor is not on a valid row, or this method fails1224*/1225public java.sql.Timestamp getTimestamp(int columnIndex) throws SQLException {1226return crsInternal.getTimestamp(columnIndex);1227}12281229/**1230* Retrieves the value of the designated column in the current row1231* of this <code>JoinRowSetImpl</code> object as a1232* <code>java.sql.Timestamp</code> object.1233*1234* @param columnIndex the first column is <code>1</code>, the second1235* is <code>2</code>, and so on; must be <code>1</code> or larger1236* and equal to or less than the number of columns in the rowset1237* @return the column value; if the value is SQL <code>NULL</code>, the1238* result is <code>null</code>1239* @throws SQLException if the given column index is out of bounds,1240* the cursor is not on a valid row, or this method fails1241*/1242public java.io.InputStream getAsciiStream(int columnIndex) throws SQLException {1243return crsInternal.getAsciiStream(columnIndex);1244}12451246/**1247* A column value can be retrieved as a stream of Unicode characters1248* and then read in chunks from the stream. This method is particularly1249* suitable for retrieving large LONGVARCHAR values. The JDBC driver will1250* do any necessary conversion from the database format into Unicode.1251*1252* <P><B>Note:</B> All the data in the returned stream must be1253* read prior to getting the value of any other column. The next1254* call to a get method implicitly closes the stream. . Also, a1255* stream may return 0 for available() whether there is data1256* available or not.1257*1258* @param columnIndex the first column is <code>1</code>, the second1259* is <code>2</code>, and so on; must be <code>1</code> or larger1260* and equal to or less than the number of columns in this rowset1261* @return a Java input stream that delivers the database column value1262* as a stream of two byte Unicode characters. If the value is SQL NULL1263* then the result is null.1264* @throws SQLException if an error occurs1265* @deprecated1266*/1267@Deprecated1268public java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException {1269return crsInternal.getUnicodeStream(columnIndex);1270}12711272/**1273* A column value can be retrieved as a stream of uninterpreted bytes1274* and then read in chunks from the stream. This method is particularly1275* suitable for retrieving large LONGVARBINARY values.1276*1277* <P><B>Note:</B> All the data in the returned stream must be1278* read prior to getting the value of any other column. The next1279* call to a get method implicitly closes the stream. Also, a1280* stream may return 0 for available() whether there is data1281* available or not.1282*1283* @param columnIndex the first column is <code>1</code>, the second1284* is <code>2</code>, and so on; must be <code>1</code> or larger1285* and equal to or less than the number of columns in the rowset1286* @return a Java input stream that delivers the database column value1287* as a stream of uninterpreted bytes. If the value is SQL NULL1288* then the result is null.1289* @throws SQLException if an error occurs1290*/1291public java.io.InputStream getBinaryStream(int columnIndex) throws SQLException {1292return crsInternal.getBinaryStream(columnIndex);1293}12941295// ColumnName methods12961297/**1298* Retrieves the value stored in the designated column1299* of the current row as a <code>String</code> object.1300*1301* @param columnName a <code>String</code> object giving the SQL name of1302* a column in this <code>JoinRowSetImpl</code> object1303* @return the column value; if the value is SQL <code>NULL</code>,1304* the result is <code>null</code>1305* @throws SQLException if the given column name does not match one of1306* this rowset's column names or the cursor is not on one of1307* this rowset's rows or its insert row1308*/1309public String getString(String columnName) throws SQLException {1310return crsInternal.getString(columnName);1311}13121313/**1314* Retrieves the value stored in the designated column1315* of the current row as a <code>boolean</code> value.1316*1317* @param columnName a <code>String</code> object giving the SQL name of1318* a column in this <code>JoinRowSetImpl</code> object1319* @return the column value; if the value is SQL <code>NULL</code>,1320* the result is <code>false</code>1321* @throws SQLException if the given column name does not match one of1322* this rowset's column names or the cursor is not on one of1323* this rowset's rows or its insert row1324*/1325public boolean getBoolean(String columnName) throws SQLException {1326return crsInternal.getBoolean(columnName);1327}13281329/**1330* Retrieves the value stored in the designated column1331* of the current row as a <code>byte</code> value.1332*1333* @param columnName a <code>String</code> object giving the SQL name of1334* a column in this <code>JoinRowSetImpl</code> object1335* @return the column value; if the value is SQL <code>NULL</code>,1336* the result is <code>0</code>1337* @throws SQLException if the given column name does not match one of1338* this rowset's column names or the cursor is not on one of1339* this rowset's rows or its insert row1340*/1341public byte getByte(String columnName) throws SQLException {1342return crsInternal.getByte(columnName);1343}13441345/**1346* Retrieves the value stored in the designated column1347* of the current row as a <code>short</code> value.1348*1349* @param columnName a <code>String</code> object giving the SQL name of1350* a column in this <code>JoinRowSetImpl</code> object1351* @return the column value; if the value is SQL <code>NULL</code>,1352* the result is <code>0</code>1353* @throws SQLException if the given column name does not match one of1354* this rowset's column names or the cursor is not on one of1355* this rowset's rows or its insert row1356*/1357public short getShort(String columnName) throws SQLException {1358return crsInternal.getShort(columnName);1359}13601361/**1362* Retrieves the value stored in the designated column1363* of the current row as an <code>int</code> value.1364*1365* @param columnName a <code>String</code> object giving the SQL name of1366* a column in this <code>JoinRowSetImpl</code> object1367* @return the column value; if the value is SQL <code>NULL</code>,1368* the result is <code>0</code>1369* @throws SQLException if the given column name does not match one of1370* this rowset's column names or the cursor is not on one of1371* this rowset's rows or its insert row1372*/1373public int getInt(String columnName) throws SQLException {1374return crsInternal.getInt(columnName);1375}13761377/**1378* Retrieves the value stored in the designated column1379* of the current row as a <code>long</code> value.1380*1381* @param columnName a <code>String</code> object giving the SQL name of1382* a column in this <code>JoinRowSetImpl</code> object1383* @return the column value; if the value is SQL <code>NULL</code>,1384* the result is <code>0</code>1385* @throws SQLException if the given column name does not match one of1386* this rowset's column names or the cursor is not on one of1387* this rowset's rows or its insert row1388*/1389public long getLong(String columnName) throws SQLException {1390return crsInternal.getLong(columnName);1391}13921393/**1394* Retrieves the value stored in the designated column1395* of the current row as a <code>float</code> value.1396*1397* @param columnName a <code>String</code> object giving the SQL name of1398* a column in this <code>JoinRowSetImpl</code> object1399* @return the column value; if the value is SQL <code>NULL</code>,1400* the result is <code>0</code>1401* @throws SQLException if the given column name does not match one of1402* this rowset's column names or the cursor is not on one of1403* this rowset's rows or its insert row1404*/1405public float getFloat(String columnName) throws SQLException {1406return crsInternal.getFloat(columnName);1407}14081409/**1410* Retrieves the value stored in the designated column1411* of the current row as a <code>double</code> value.1412*1413* @param columnName a <code>String</code> object giving the SQL name of1414* a column in this <code>JoinRowSetImpl</code> object1415* @return the column value; if the value is SQL <code>NULL</code>,1416* the result is <code>0</code>1417* @throws SQLException if the given column name does not match one of1418* this rowset's column names or the cursor is not on one of1419* this rowset's rows or its insert row1420*/1421public double getDouble(String columnName) throws SQLException {1422return crsInternal.getDouble(columnName);1423}14241425/**1426* Retrieves the value stored in the designated column1427* of the current row as a <code>java.math.BigDecimal</code> object.1428*1429* @param columnName a <code>String</code> object giving the SQL name of1430* a column in this <code>JoinRowSetImpl</code> object1431* @param scale the number of digits to the right of the decimal point1432* @return the column value; if the value is SQL <code>NULL</code>,1433* the result is <code>null</code>1434* @throws SQLException if the given column name does not match one of1435* this rowset's column names or the cursor is not on one of1436* this rowset's rows or its insert row1437* @deprecated use the method <code>getBigDecimal(String columnName)</code>1438* instead1439*/1440@Deprecated1441public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {1442return crsInternal.getBigDecimal(columnName);1443}14441445/**1446* Retrieves the value stored in the designated column1447* of the current row as a byte array.1448* The bytes represent the raw values returned by the driver.1449*1450* @param columnName a <code>String</code> object giving the SQL name of1451* a column in this <code>JoinRowSetImpl</code> object1452* @return the column value; if the value is SQL <code>NULL</code>,1453* the result is <code>null</code>1454* @throws SQLException if the given column name does not match one of1455* this rowset's column names or the cursor is not on one of1456* this rowset's rows or its insert row1457*/1458public byte[] getBytes(String columnName) throws SQLException {1459return crsInternal.getBytes(columnName);1460}14611462/**1463* Retrieves the value stored in the designated column1464* of the current row as a <code>java.sql.Date</code> object.1465*1466* @param columnName a <code>String</code> object giving the SQL name of1467* a column in this <code>JoinRowSetImpl</code> object1468* @return the column value; if the value is SQL <code>NULL</code>,1469* the result is <code>null</code>1470* @throws SQLException if the given column name does not match one of1471* this rowset's column names or the cursor is not on one of1472* this rowset's rows or its insert row1473*/1474public java.sql.Date getDate(String columnName) throws SQLException {1475return crsInternal.getDate(columnName);1476}14771478/**1479* Retrieves the value stored in the designated column1480* of the current row as a <code>java.sql.Time</code> object.1481*1482* @param columnName a <code>String</code> object giving the SQL name of1483* a column in this <code>JoinRowSetImpl</code> object1484* @return the column value; if the value is SQL <code>NULL</code>,1485* the result is <code>null</code>1486* @throws SQLException if the given column name does not match one of1487* this rowset's column names or the cursor is not on one of1488* this rowset's rows or its insert row1489*/1490public java.sql.Time getTime(String columnName) throws SQLException {1491return crsInternal.getTime(columnName);1492}14931494/**1495* Retrieves the value stored in the designated column1496* of the current row as a <code>java.sql.Timestamp</code> object.1497*1498* @param columnName a <code>String</code> object giving the SQL name of1499* a column in this <code>JoinRowSetImpl</code> object1500* @return the column value; if the value is SQL <code>NULL</code>,1501* the result is <code>null</code>1502* @throws SQLException if the given column name does not match one of1503* this rowset's column names or the cursor is not on one of1504* this rowset's rows or its insert row1505*/1506public java.sql.Timestamp getTimestamp(String columnName) throws SQLException {1507return crsInternal.getTimestamp(columnName);1508}15091510/**1511* This method is not supported, and it will throw an1512* <code>UnsupportedOperationException</code> if it is called.1513* <P>1514* A column value can be retrieved as a stream of ASCII characters1515* and then read in chunks from the stream. This method is particularly1516* suitable for retrieving large LONGVARCHAR values. The JDBC driver will1517* do any necessary conversion from the database format into ASCII format.1518*1519* <P><B>Note:</B> All the data in the returned stream must1520* be read prior to getting the value of any other column. The1521* next call to a <code>getXXX</code> method implicitly closes the stream.1522*1523* @param columnName a <code>String</code> object giving the SQL name of1524* a column in this <code>JoinRowSetImpl</code> object1525* @return a Java input stream that delivers the database column value1526* as a stream of one-byte ASCII characters. If the value is SQL1527* <code>NULL</code>, the result is <code>null</code>.1528* @throws UnsupportedOperationException if this method is called1529*/1530public java.io.InputStream getAsciiStream(String columnName) throws SQLException {1531return crsInternal.getAsciiStream(columnName);1532}15331534/**1535* Retrieves the value stored in the designated column1536* of the current row as a <code>java.io.InputStream</code> object.1537* A column value can be retrieved as a stream of Unicode characters1538* and then read in chunks from the stream. This method is particularly1539* suitable for retrieving large <code>LONGVARCHAR</code> values.1540* The JDBC driver will do any necessary conversion from the database1541* format into Unicode.1542*1543* <P><B>Note:</B> All the data in the returned stream must1544* be read prior to getting the value of any other column. The1545* next call to a <code>getXXX</code> method implicitly closes the stream.1546*1547* @param columnName a <code>String</code> object giving the SQL name of1548* a column in this <code>JoinRowSetImpl</code> object1549* @return a Java input stream that delivers the database column value1550* as a stream of two-byte Unicode characters. If the value is1551* SQL <code>NULL</code>, the result is <code>null</code>.1552* @throws SQLException if the given column name does not match one of1553* this rowset's column names or the cursor is not on one of1554* this rowset's rows or its insert row1555* @deprecated use the method <code>getCharacterStream</code> instead1556*/1557@Deprecated1558public java.io.InputStream getUnicodeStream(String columnName) throws SQLException {1559return crsInternal.getUnicodeStream(columnName);1560}15611562/**1563* Retrieves the value stored in the designated column1564* of the current row as a <code>java.io.InputStream</code> object.1565* A column value can be retrieved as a stream of uninterpreted bytes1566* and then read in chunks from the stream. This method is particularly1567* suitable for retrieving large <code>LONGVARBINARY</code> values.1568*1569* <P><B>Note:</B> All the data in the returned stream must1570* be read prior to getting the value of any other column. The1571* next call to a get method implicitly closes the stream.1572*1573* @param columnName a <code>String</code> object giving the SQL name of1574* a column in this <code>JoinRowSetImpl</code> object1575* @return a Java input stream that delivers the database column value1576* as a stream of uninterpreted bytes. If the value is SQL1577* <code>NULL</code>, the result is <code>null</code>.1578* @throws SQLException if the given column name does not match one of1579* this rowset's column names or the cursor is not on one of1580* this rowset's rows or its insert row1581*/1582public java.io.InputStream getBinaryStream(String columnName) throws SQLException {1583return crsInternal.getBinaryStream(columnName);1584}15851586/* The first warning reported by calls on this <code>JoinRowSetImpl</code>1587* object is returned. Subsequent <code>JoinRowSetImpl</code> warnings will1588* be chained to this <code>SQLWarning</code>.1589*1590* <P>The warning chain is automatically cleared each time a new1591* row is read.1592*1593* <P><B>Note:</B> This warning chain only covers warnings caused1594* by <code>ResultSet</code> methods. Any warning caused by statement1595* methods (such as reading OUT parameters) will be chained on the1596* <code>Statement</code> object.1597*1598* @return the first SQLWarning or null1599* @throws UnsupportedOperationException if this method is called1600*/1601public SQLWarning getWarnings() {1602return crsInternal.getWarnings();1603}16041605/**1606* Throws an <code>UnsupportedOperationException</code> if called.1607* <P>1608* After a call to this method, the <code>getWarnings</code> method1609* returns <code>null</code> until a new warning is reported for this1610* <code>JoinRowSetImpl</code> object.1611*1612* @throws UnsupportedOperationException if this method is called1613*/1614public void clearWarnings() {1615crsInternal.clearWarnings();1616}16171618/**1619* Retrieves the name of the SQL cursor used by this1620* <code>JoinRowSetImpl</code> object.1621*1622* <P>In SQL, a result table is retrieved through a cursor that is1623* named. The current row of a result can be updated or deleted1624* using a positioned update/delete statement that references the1625* cursor name. To insure that the cursor has the proper isolation1626* level to support an update operation, the cursor's <code>SELECT</code>1627* statement should be of the form 'select for update'. If the 'for update'1628* clause is omitted, positioned updates may fail.1629*1630* <P>JDBC supports this SQL feature by providing the name of the1631* SQL cursor used by a <code>ResultSet</code> object. The current row1632* of a result set is also the current row of this SQL cursor.1633*1634* <P><B>Note:</B> If positioned updates are not supported, an1635* <code>SQLException</code> is thrown.1636*1637* @return the SQL cursor name for this <code>JoinRowSetImpl</code> object's1638* cursor1639* @throws SQLException if an error occurs1640*/1641public String getCursorName() throws SQLException {1642return crsInternal.getCursorName();1643}16441645/**1646* Retrieves the <code>ResultSetMetaData</code> object that contains1647* information about this <code>CachedRowsSet</code> object. The1648* information includes the number of columns, the data type for each1649* column, and other properties for each column.1650*1651* @return the <code>ResultSetMetaData</code> object that describes this1652* <code>JoinRowSetImpl</code> object's columns1653* @throws SQLException if an error occurs1654*/1655public ResultSetMetaData getMetaData() throws SQLException {1656return crsInternal.getMetaData();1657}16581659/**1660* Retrieves the value of the designated column in the current row1661* of this <code>JoinRowSetImpl</code> object as an1662* <code>Object</code> value.1663* <P>1664* The type of the <code>Object</code> will be the default1665* Java object type corresponding to the column's SQL type,1666* following the mapping for built-in types specified in the JDBC1667* specification.1668* <P>1669* This method may also be used to read datatabase-specific1670* abstract data types.1671* <P>1672* This implementation of the method <code>getObject</code> extends its1673* behavior so that it gets the attributes of an SQL structured type as1674* as an array of <code>Object</code> values. This method also custom1675* maps SQL user-defined types to classes in the Java programming language.1676* When the specified column contains1677* a structured or distinct value, the behavior of this method is as1678* if it were a call to the method <code>getObject(columnIndex,1679* this.getStatement().getConnection().getTypeMap())</code>.1680*1681* @param columnIndex the first column is <code>1</code>, the second1682* is <code>2</code>, and so on; must be <code>1</code> or larger1683* and equal to or less than the number of columns in the rowset1684* @return a <code>java.lang.Object</code> holding the column value;1685* if the value is SQL <code>NULL</code>, the result is <code>null</code>1686* @throws SQLException if the given column index is out of bounds,1687* the cursor is not on a valid row, or there is a problem getting1688* the <code>Class</code> object for a custom mapping1689* @since 1.21690*/1691public Object getObject(int columnIndex) throws SQLException {1692return crsInternal.getObject(columnIndex);1693}16941695/**1696* Retrieves the value of the designated column in the current row1697* of this <code>JoinRowSetImpl</code> object as an1698* <code>Object</code> value.1699* <P>1700* The type of the <code>Object</code> will be the default1701* Java object type corresponding to the column's SQL type,1702* following the mapping for built-in types specified in the JDBC1703* specification.1704* <P>1705* This method may also be used to read datatabase-specific1706* abstract data types.1707* <P>1708* This implementation of the method <code>getObject</code> extends its1709* behavior so that it gets the attributes of an SQL structured type as1710* as an array of <code>Object</code> values. This method also custom1711* maps SQL user-defined types to classes1712* in the Java programming language. When the specified column contains1713* a structured or distinct value, the behavior of this method is as1714* if it were a call to the method <code>getObject(columnIndex,1715* this.getStatement().getConnection().getTypeMap())</code>.1716*1717* @param columnIndex the first column is <code>1</code>, the second1718* is <code>2</code>, and so on; must be <code>1</code> or larger1719* and equal to or less than the number of columns in the rowset1720* @param map a <code>java.util.Map</code> object showing the mapping1721* from SQL type names to classes in the Java programming1722* language1723* @return a <code>java.lang.Object</code> holding the column value;1724* if the value is SQL <code>NULL</code>, the result is1725* <code>null</code>1726* @throws SQLException if (1) the given column name does not match1727* one of this rowset's column names, (2) the cursor is not1728* on a valid row, or (3) there is a problem getting1729* the <code>Class</code> object for a custom mapping1730*/1731public Object getObject(int columnIndex,1732java.util.Map<String,Class<?>> map)1733throws SQLException {1734return crsInternal.getObject(columnIndex, map);1735}17361737/**1738* Retrieves the value of the designated column in the current row1739* of this <code>JoinRowSetImpl</code> object as an1740* <code>Object</code> value.1741* <P>1742* The type of the <code>Object</code> will be the default1743* Java object type corresponding to the column's SQL type,1744* following the mapping for built-in types specified in the JDBC1745* specification.1746* <P>1747* This method may also be used to read datatabase-specific1748* abstract data types.1749* <P>1750* This implementation of the method <code>getObject</code> extends its1751* behavior so that it gets the attributes of an SQL structured type as1752* as an array of <code>Object</code> values. This method also custom1753* maps SQL user-defined types to classes1754* in the Java programming language. When the specified column contains1755* a structured or distinct value, the behavior of this method is as1756* if it were a call to the method <code>getObject(columnIndex,1757* this.getStatement().getConnection().getTypeMap())</code>.1758*1759* @param columnName a <code>String</code> object that must match the1760* SQL name of a column in this rowset, ignoring case1761* @return a <code>java.lang.Object</code> holding the column value;1762* if the value is SQL <code>NULL</code>, the result is1763* <code>null</code>1764* @throws SQLException if (1) the given column name does not match1765* one of this rowset's column names, (2) the cursor is not1766* on a valid row, or (3) there is a problem getting1767* the <code>Class</code> object for a custom mapping1768*/1769public Object getObject(String columnName) throws SQLException {1770return crsInternal.getObject(columnName);1771}17721773/**1774* Retrieves the value of the designated column in this1775* <code>JoinRowSetImpl</code> object as an <code>Object</code> in1776* the Java programming lanugage, using the given1777* <code>java.util.Map</code> object to custom map the value if1778* appropriate.1779*1780* @param columnName a <code>String</code> object that must match the1781* SQL name of a column in this rowset, ignoring case1782* @param map a <code>java.util.Map</code> object showing the mapping1783* from SQL type names to classes in the Java programming1784* language1785* @return an <code>Object</code> representing the SQL value1786* @throws SQLException if the given column index is out of bounds or1787* the cursor is not on one of this rowset's rows or its1788* insert row1789*/1790public Object getObject(String columnName,1791java.util.Map<String,Class<?>> map)1792throws SQLException {1793return crsInternal.getObject(columnName, map);1794}17951796/**1797* Retrieves the value stored in the designated column1798* of the current row as a <code>java.io.Reader</code> object.1799*1800* <P><B>Note:</B> All the data in the returned stream must1801* be read prior to getting the value of any other column. The1802* next call to a <code>getXXX</code> method implicitly closes the stream.1803*1804* @param columnIndex the first column is <code>1</code>, the second1805* is <code>2</code>, and so on; must be <code>1</code> or larger1806* and equal to or less than the number of columns in the rowset1807* @return a Java character stream that delivers the database column value1808* as a <code>java.io.Reader</code> object. If the value is1809* SQL <code>NULL</code>, the result is <code>null</code>.1810* @throws SQLException if the given column index is out of bounds,1811* the cursor is not on a valid row, or there is a type mismatch1812*/1813public java.io.Reader getCharacterStream(int columnIndex) throws SQLException {1814return crsInternal.getCharacterStream(columnIndex);1815}18161817/**1818* Retrieves the value stored in the designated column1819* of the current row as a <code>java.io.Reader</code> object.1820*1821* <P><B>Note:</B> All the data in the returned stream must1822* be read prior to getting the value of any other column. The1823* next call to a <code>getXXX</code> method implicitly closes the stream.1824*1825* @param columnName a <code>String</code> object giving the SQL name of1826* a column in this <code>JoinRowSetImpl</code> object1827* @return a Java input stream that delivers the database column value1828* as a stream of two-byte Unicode characters. If the value is1829* SQL <code>NULL</code>, the result is <code>null</code>.1830* @throws SQLException if the given column index is out of bounds,1831* the cursor is not on a valid row, or there is a type mismatch1832*/1833public java.io.Reader getCharacterStream(String columnName) throws SQLException {1834return crsInternal.getCharacterStream(columnName);1835}18361837/**1838* Retrieves the value of the designated column in the current row1839* of this <code>JoinRowSetImpl</code> object as a1840* <code>java.math.BigDecimal</code> object.1841*1842* @param columnIndex the first column is <code>1</code>, the second1843* is <code>2</code>, and so on; must be <code>1</code> or larger1844* and equal to or less than the number of columns in the rowset1845* @return a <code>java.math.BigDecimal</code> value with full precision;1846* if the value is SQL <code>NULL</code>, the result is <code>null</code>1847* @throws SQLException if the given column index is out of bounds,1848* the cursor is not on a valid row, or this method fails1849*/1850public BigDecimal getBigDecimal(int columnIndex) throws SQLException {1851return crsInternal.getBigDecimal(columnIndex);1852}18531854/**1855* Retrieves the value of the designated column in the current row1856* of this <code>JoinRowSetImpl</code> object as a1857* <code>java.math.BigDecimal</code> object.1858*1859* @param columnName a <code>String</code> object that must match the1860* SQL name of a column in this rowset, ignoring case1861* @return a <code>java.math.BigDecimal</code> value with full precision;1862* if the value is SQL <code>NULL</code>, the result is <code>null</code>1863* @throws SQLException if the given column index is out of bounds,1864* the cursor is not on a valid row, or this method fails1865*/1866public BigDecimal getBigDecimal(String columnName) throws SQLException {1867return crsInternal.getBigDecimal(columnName);1868}18691870/**1871* Returns the number of rows in this <code>JoinRowSetImpl</code> object.1872*1873* @return number of rows in the rowset1874*/1875public int size() {1876return crsInternal.size();1877}18781879/**1880* Indicates whether the cursor is before the first row in this1881* <code>JoinRowSetImpl</code> object.1882*1883* @return <code>true</code> if the cursor is before the first row;1884* <code>false</code> otherwise or if the rowset contains no rows1885* @throws SQLException if an error occurs1886*/1887public boolean isBeforeFirst() throws SQLException {1888return crsInternal.isBeforeFirst();1889}18901891/**1892* Indicates whether the cursor is after the last row in this1893* <code>JoinRowSetImpl</code> object.1894*1895* @return <code>true</code> if the cursor is after the last row;1896* <code>false</code> otherwise or if the rowset contains no rows1897* @throws SQLException if an error occurs1898*/1899public boolean isAfterLast() throws SQLException {1900return crsInternal.isAfterLast();1901}19021903/**1904* Indicates whether the cursor is on the first row in this1905* <code>JoinRowSetImpl</code> object.1906*1907* @return <code>true</code> if the cursor is on the first row;1908* <code>false</code> otherwise or if the rowset contains no rows1909* @throws SQLException if an error occurs1910*/1911public boolean isFirst() throws SQLException {1912return crsInternal.isFirst();1913}19141915/**1916* Indicates whether the cursor is on the last row in this1917* <code>JoinRowSetImpl</code> object.1918* <P>1919* Note: Calling the method <code>isLast</code> may be expensive1920* because the JDBC driver might need to fetch ahead one row in order1921* to determine whether the current row is the last row in this rowset.1922*1923* @return <code>true</code> if the cursor is on the last row;1924* <code>false</code> otherwise or if this rowset contains no rows1925* @throws SQLException if an error occurs1926*/1927public boolean isLast() throws SQLException {1928return crsInternal.isLast();1929}19301931/**1932* Moves this <code>JoinRowSetImpl</code> object's cursor to the front of1933* the rowset, just before the first row. This method has no effect if1934* this rowset contains no rows.1935*1936* @throws SQLException if an error occurs or the type of this rowset1937* is <code>ResultSet.TYPE_FORWARD_ONLY</code>1938*/1939public void beforeFirst() throws SQLException {1940crsInternal.beforeFirst();1941}19421943/**1944* Moves this <code>JoinRowSetImpl</code> object's cursor to the end of1945* the rowset, just after the last row. This method has no effect if1946* this rowset contains no rows.1947*1948* @throws SQLException if an error occurs1949*/1950public void afterLast() throws SQLException {1951crsInternal.afterLast();1952}19531954/**1955* Moves this <code>JoinRowSetImpl</code> object's cursor to the first row1956* and returns <code>true</code> if the operation was successful. This1957* method also notifies registered listeners that the cursor has moved.1958*1959* @return <code>true</code> if the cursor is on a valid row;1960* <code>false</code> otherwise or if there are no rows in this1961* <code>JoinRowSetImpl</code> object1962* @throws SQLException if the type of this rowset1963* is <code>ResultSet.TYPE_FORWARD_ONLY</code>1964*/1965public boolean first() throws SQLException {1966return crsInternal.first();1967}196819691970/**1971* Moves this <code>JoinRowSetImpl</code> object's cursor to the last row1972* and returns <code>true</code> if the operation was successful. This1973* method also notifies registered listeners that the cursor has moved.1974*1975* @return <code>true</code> if the cursor is on a valid row;1976* <code>false</code> otherwise or if there are no rows in this1977* <code>JoinRowSetImpl</code> object1978* @throws SQLException if the type of this rowset1979* is <code>ResultSet.TYPE_FORWARD_ONLY</code>1980*/1981public boolean last() throws SQLException {1982return crsInternal.last();1983}19841985/**1986* Returns the number of the current row in this <code>JoinRowSetImpl</code>1987* object. The first row is number 1, the second number 2, and so on.1988*1989* @return the number of the current row; <code>0</code> if there is no1990* current row1991* @throws SQLException if an error occurs1992*/1993public int getRow() throws SQLException {1994return crsInternal.getRow();1995}19961997/**1998* Moves this <code>JoinRowSetImpl</code> object's cursor to the row number1999* specified.2000*2001* <p>If the number is positive, the cursor moves to an absolute row with2002* respect to the beginning of the rowset. The first row is row 1, the second2003* is row 2, and so on. For example, the following command, in which2004* <code>crs</code> is a <code>JoinRowSetImpl</code> object, moves the cursor2005* to the fourth row, starting from the beginning of the rowset.2006* <PRE><code>2007*2008* crs.absolute(4);2009*2010* </code> </PRE>2011* <P>2012* If the number is negative, the cursor moves to an absolute row position2013* with respect to the end of the rowset. For example, calling2014* <code>absolute(-1)</code> positions the cursor on the last row,2015* <code>absolute(-2)</code> moves it on the next-to-last row, and so on.2016* If the <code>JoinRowSetImpl</code> object <code>crs</code> has five rows,2017* the following command moves the cursor to the fourth-to-last row, which2018* in the case of a rowset with five rows, is also the second row, counting2019* from the beginning.2020* <PRE><code>2021*2022* crs.absolute(-4);2023*2024* </code> </PRE>2025*2026* If the number specified is larger than the number of rows, the cursor2027* will move to the position after the last row. If the number specified2028* would move the cursor one or more rows before the first row, the cursor2029* moves to the position before the first row.2030* <P>2031* Note: Calling <code>absolute(1)</code> is the same as calling the2032* method <code>first()</code>. Calling <code>absolute(-1)</code> is the2033* same as calling <code>last()</code>.2034*2035* @param row a positive number to indicate the row, starting row numbering from2036* the first row, which is <code>1</code>; a negative number to indicate2037* the row, starting row numbering from the last row, which is2038* <code>-1</code>; must not be <code>0</code>2039* @return <code>true</code> if the cursor is on the rowset; <code>false</code>2040* otherwise2041* @throws SQLException if the given cursor position is <code>0</code> or the2042* type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>2043*/2044public boolean absolute(int row) throws SQLException {2045return crsInternal.absolute(row);2046}20472048/**2049* Moves the cursor the specified number of rows from the current2050* position, with a positive number moving it forward and a2051* negative number moving it backward.2052* <P>2053* If the number is positive, the cursor moves the specified number of2054* rows toward the end of the rowset, starting at the current row.2055* For example, the following command, in which2056* <code>crs</code> is a <code>JoinRowSetImpl</code> object with 100 rows,2057* moves the cursor forward four rows from the current row. If the2058* current row is 50, the cursor would move to row 54.2059* <PRE><code>2060*2061* crs.relative(4);2062*2063* </code> </PRE>2064* <P>2065* If the number is negative, the cursor moves back toward the beginning2066* the specified number of rows, starting at the current row.2067* For example, calling the method2068* <code>absolute(-1)</code> positions the cursor on the last row,2069* <code>absolute(-2)</code> moves it on the next-to-last row, and so on.2070* If the <code>JoinRowSetImpl</code> object <code>crs</code> has five rows,2071* the following command moves the cursor to the fourth-to-last row, which2072* in the case of a rowset with five rows, is also the second row2073* from the beginning.2074* <PRE><code>2075*2076* crs.absolute(-4);2077*2078* </code> </PRE>2079*2080* If the number specified is larger than the number of rows, the cursor2081* will move to the position after the last row. If the number specified2082* would move the cursor one or more rows before the first row, the cursor2083* moves to the position before the first row. In both cases, this method2084* throws an <code>SQLException</code>.2085* <P>2086* Note: Calling <code>absolute(1)</code> is the same as calling the2087* method <code>first()</code>. Calling <code>absolute(-1)</code> is the2088* same as calling <code>last()</code>. Calling <code>relative(0)</code>2089* is valid, but it does not change the cursor position.2090*2091* @param rows an <code>int</code> indicating the number of rows to move2092* the cursor, starting at the current row; a positive number2093* moves the cursor forward; a negative number moves the cursor2094* backward; must not move the cursor past the valid2095* rows2096* @return <code>true</code> if the cursor is on a row in this2097* <code>JoinRowSetImpl</code> object; <code>false</code>2098* otherwise2099* @throws SQLException if there are no rows in this rowset, the cursor is2100* positioned either before the first row or after the last row, or2101* the rowset is type <code>ResultSet.TYPE_FORWARD_ONLY</code>2102*/2103public boolean relative(int rows) throws SQLException {2104return crsInternal.relative(rows);2105}21062107/**2108* Moves this <code>JoinRowSetImpl</code> object's cursor to the2109* previous row and returns <code>true</code> if the cursor is on2110* a valid row or <code>false</code> if it is not.2111* This method also notifies all listeners registered with this2112* <code>JoinRowSetImpl</code> object that its cursor has moved.2113* <P>2114* Note: calling the method <code>previous()</code> is not the same2115* as calling the method <code>relative(-1)</code>. This is true2116* because it is possible to call <code>previous()</code> from the insert2117* row, from after the last row, or from the current row, whereas2118* <code>relative</code> may only be called from the current row.2119* <P>2120* The method <code>previous</code> may used in a <code>while</code>2121* loop to iterate through a rowset starting after the last row2122* and moving toward the beginning. The loop ends when <code>previous</code>2123* returns <code>false</code>, meaning that there are no more rows.2124* For example, the following code fragment retrieves all the data in2125* the <code>JoinRowSetImpl</code> object <code>crs</code>, which has2126* three columns. Note that the cursor must initially be positioned2127* after the last row so that the first call to the method2128* <code>previous</code> places the cursor on the last line.2129* <PRE> <code>2130*2131* crs.afterLast();2132* while (previous()) {2133* String name = crs.getString(1);2134* int age = crs.getInt(2);2135* short ssn = crs.getShort(3);2136* System.out.println(name + " " + age + " " + ssn);2137* }2138*2139* </code> </PRE>2140* This method throws an <code>SQLException</code> if the cursor is not2141* on a row in the rowset, before the first row, or after the last row.2142*2143* @return <code>true</code> if the cursor is on a valid row;2144* <code>false</code> if it is before the first row or after the2145* last row2146* @throws SQLException if the cursor is not on a valid position or the2147* type of this rowset is <code>ResultSet.TYPE_FORWARD_ONLY</code>2148*/2149public boolean previous() throws SQLException {2150return crsInternal.previous();2151}21522153/**2154* Returns the index of the column whose name is <i>columnName</i>.2155*2156* @param columnName a <code>String</code> object giving the name of the2157* column for which the index will be returned; the name must2158* match the SQL name of a column in this <code>JoinRowSet</code>2159* object, ignoring case2160* @throws SQLException if the given column name does not match one of the2161* column names for this <code>JoinRowSet</code> object2162*/2163public int findColumn(String columnName) throws SQLException {2164return crsInternal.findColumn(columnName);2165}21662167/**2168* Indicates whether the current row of this <code>JoinRowSetImpl</code>2169* object has been updated. The value returned2170* depends on whether this rowset can detect updates: <code>false</code>2171* will always be returned if it does not detect updates.2172*2173* @return <code>true</code> if the row has been visibly updated2174* by the owner or another and updates are detected;2175* <code>false</code> otherwise2176* @throws SQLException if the cursor is on the insert row or not2177* on a valid row2178*2179* @see DatabaseMetaData#updatesAreDetected2180*/2181public boolean rowUpdated() throws SQLException {2182return crsInternal.rowUpdated();2183}21842185/**2186* Indicates whether the designated column of the current row of2187* this <code>JoinRowSetImpl</code> object has been updated. The2188* value returned depends on whether this rowset can detcted updates:2189* <code>false</code> will always be returned if it does not detect updates.2190*2191* @return <code>true</code> if the column updated2192* <code>false</code> otherwse2193* @throws SQLException if the cursor is on the insert row or not2194* on a valid row2195* @see DatabaseMetaData#updatesAreDetected2196*/2197public boolean columnUpdated(int indexColumn) throws SQLException {2198return crsInternal.columnUpdated(indexColumn);2199}22002201/**2202* Indicates whether the current row has been inserted. The value returned2203* depends on whether or not the rowset can detect visible inserts.2204*2205* @return <code>true</code> if a row has been inserted and inserts are detected;2206* <code>false</code> otherwise2207* @throws SQLException if the cursor is on the insert row or not2208* not on a valid row2209*2210* @see DatabaseMetaData#insertsAreDetected2211*/2212public boolean rowInserted() throws SQLException {2213return crsInternal.rowInserted();2214}22152216/**2217* Indicates whether the current row has been deleted. A deleted row2218* may leave a visible "hole" in a rowset. This method can be used to2219* detect such holes if the rowset can detect deletions. This method2220* will always return <code>false</code> if this rowset cannot detect2221* deletions.2222*2223* @return <code>true</code> if (1)the current row is blank, indicating that2224* the row has been deleted, and (2)deletions are detected;2225* <code>false</code> otherwise2226* @throws SQLException if the cursor is on a valid row in this rowset2227* @see DatabaseMetaData#deletesAreDetected2228*/2229public boolean rowDeleted() throws SQLException {2230return crsInternal.rowDeleted();2231}22322233/**2234* Sets the designated nullable column in the current row or the2235* insert row of this <code>JoinRowSetImpl</code> object with2236* <code>null</code> value.2237* <P>2238* This method updates a column value in the current row or the insert2239* row of this rowset; however, another method must be called to complete2240* the update process. If the cursor is on a row in the rowset, the2241* method {@link #updateRow} must be called to mark the row as updated2242* and to notify listeners that the row has changed.2243* If the cursor is on the insert row, the method {@link #insertRow}2244* must be called to insert the new row into this rowset and to notify2245* listeners that a row has changed.2246* <P>2247* In order to propagate updates in this rowset to the underlying2248* data source, an application must call the method acceptChanges2249* after it calls either <code>updateRow</code> or <code>insertRow</code>.2250*2251* @param columnIndex the first column is <code>1</code>, the second2252* is <code>2</code>, and so on; must be <code>1</code> or larger2253* and equal to or less than the number of columns in this rowset2254* @throws SQLException if (1) the given column index is out of bounds,2255* (2) the cursor is not on one of this rowset's rows or its2256* insert row, or (3) this rowset is2257* <code>ResultSet.CONCUR_READ_ONLY</code>2258*/2259public void updateNull(int columnIndex) throws SQLException {2260crsInternal.updateNull(columnIndex);2261}22622263/**2264* Sets the designated column in either the current row or the insert2265* row of this <code>JoinRowSetImpl</code> object with the given2266* <code>boolean</code> value.2267* <P>2268* This method updates a column value in the current row or the insert2269* row of this rowset, but it does not update the database.2270* If the cursor is on a row in the rowset, the2271* method {@link #updateRow} must be called to update the database.2272* If the cursor is on the insert row, the method {@link #insertRow}2273* must be called, which will insert the new row into both this rowset2274* and the database. Both of these methods must be called before the2275* cursor moves to another row.2276*2277* @param columnIndex the first column is <code>1</code>, the second2278* is <code>2</code>, and so on; must be <code>1</code> or larger2279* and equal to or less than the number of columns in this rowset2280* @param x the new column value2281* @throws SQLException if (1) the given column index is out of bounds,2282* (2) the cursor is not on one of this rowset's rows or its2283* insert row, or (3) this rowset is2284* <code>ResultSet.CONCUR_READ_ONLY</code>2285*/2286public void updateBoolean(int columnIndex, boolean x) throws SQLException {2287crsInternal.updateBoolean(columnIndex, x);2288}22892290/**2291* Sets the designated column in either the current row or the insert2292* row of this <code>JoinRowSetImpl</code> object with the given2293* <code>byte</code> value.2294* <P>2295* This method updates a column value in the current row or the insert2296* row of this rowset, but it does not update the database.2297* If the cursor is on a row in the rowset, the2298* method {@link #updateRow} must be called to update the database.2299* If the cursor is on the insert row, the method {@link #insertRow}2300* must be called, which will insert the new row into both this rowset2301* and the database. Both of these methods must be called before the2302* cursor moves to another row.2303*2304* @param columnIndex the first column is <code>1</code>, the second2305* is <code>2</code>, and so on; must be <code>1</code> or larger2306* and equal to or less than the number of columns in this rowset2307* @param x the new column value2308* @throws SQLException if (1) the given column index is out of bounds,2309* (2) the cursor is not on one of this rowset's rows or its2310* insert row, or (3) this rowset is2311* <code>ResultSet.CONCUR_READ_ONLY</code>2312*/2313public void updateByte(int columnIndex, byte x) throws SQLException {2314crsInternal.updateByte(columnIndex, x);2315}23162317/**2318* Sets the designated column in either the current row or the insert2319* row of this <code>JoinRowSetImpl</code> object with the given2320* <code>short</code> value.2321* <P>2322* This method updates a column value in the current row or the insert2323* row of this rowset, but it does not update the database.2324* If the cursor is on a row in the rowset, the2325* method {@link #updateRow} must be called to update the database.2326* If the cursor is on the insert row, the method {@link #insertRow}2327* must be called, which will insert the new row into both this rowset2328* and the database. Both of these methods must be called before the2329* cursor moves to another row.2330*2331* @param columnIndex the first column is <code>1</code>, the second2332* is <code>2</code>, and so on; must be <code>1</code> or larger2333* and equal to or less than the number of columns in this rowset2334* @param x the new column value2335* @throws SQLException if (1) the given column index is out of bounds,2336* (2) the cursor is not on one of this rowset's rows or its2337* insert row, or (3) this rowset is2338* <code>ResultSet.CONCUR_READ_ONLY</code>2339*/2340public void updateShort(int columnIndex, short x) throws SQLException {2341crsInternal.updateShort(columnIndex, x);2342}23432344/**2345* Sets the designated column in either the current row or the insert2346* row of this <code>JoinRowSetImpl</code> object with the given2347* <code>int</code> value.2348* <P>2349* This method updates a column value in the current row or the insert2350* row of this rowset, but it does not update the database.2351* If the cursor is on a row in the rowset, the2352* method {@link #updateRow} must be called to update the database.2353* If the cursor is on the insert row, the method {@link #insertRow}2354* must be called, which will insert the new row into both this rowset2355* and the database. Both of these methods must be called before the2356* cursor moves to another row.2357*2358* @param columnIndex the first column is <code>1</code>, the second2359* is <code>2</code>, and so on; must be <code>1</code> or larger2360* and equal to or less than the number of columns in this rowset2361* @param x the new column value2362* @throws SQLException if (1) the given column index is out of bounds,2363* (2) the cursor is not on one of this rowset's rows or its2364* insert row, or (3) this rowset is2365* <code>ResultSet.CONCUR_READ_ONLY</code>2366*/2367public void updateInt(int columnIndex, int x) throws SQLException {2368crsInternal.updateInt(columnIndex, x);2369}23702371/**2372* Sets the designated column in either the current row or the insert2373* row of this <code>JoinRowSetImpl</code> object with the given2374* <code>long</code> value.2375* <P>2376* This method updates a column value in the current row or the insert2377* row of this rowset, but it does not update the database.2378* If the cursor is on a row in the rowset, the2379* method {@link #updateRow} must be called to update the database.2380* If the cursor is on the insert row, the method {@link #insertRow}2381* must be called, which will insert the new row into both this rowset2382* and the database. Both of these methods must be called before the2383* cursor moves to another row.2384*2385* @param columnIndex the first column is <code>1</code>, the second2386* is <code>2</code>, and so on; must be <code>1</code> or larger2387* and equal to or less than the number of columns in this rowset2388* @param x the new column value2389* @throws SQLException if (1) the given column index is out of bounds,2390* (2) the cursor is not on one of this rowset's rows or its2391* insert row, or (3) this rowset is2392* <code>ResultSet.CONCUR_READ_ONLY</code>2393*/2394public void updateLong(int columnIndex, long x) throws SQLException {2395crsInternal.updateLong(columnIndex, x);2396}23972398/**2399* Sets the designated column in either the current row or the insert2400* row of this <code>JoinRowSetImpl</code> object with the given2401* <code>float</code> value.2402* <P>2403* This method updates a column value in the current row or the insert2404* row of this rowset, but it does not update the database.2405* If the cursor is on a row in the rowset, the2406* method {@link #updateRow} must be called to update the database.2407* If the cursor is on the insert row, the method {@link #insertRow}2408* must be called, which will insert the new row into both this rowset2409* and the database. Both of these methods must be called before the2410* cursor moves to another row.2411*2412* @param columnIndex the first column is <code>1</code>, the second2413* is <code>2</code>, and so on; must be <code>1</code> or larger2414* and equal to or less than the number of columns in this rowset2415* @param x the new column value2416* @throws SQLException if (1) the given column index is out of bounds,2417* (2) the cursor is not on one of this rowset's rows or its2418* insert row, or (3) this rowset is2419* <code>ResultSet.CONCUR_READ_ONLY</code>2420*/2421public void updateFloat(int columnIndex, float x) throws SQLException {2422crsInternal.updateFloat(columnIndex, x);2423}24242425/**2426* Sets the designated column in either the current row or the insert2427* row of this <code>JoinRowSetImpl</code> object with the given2428* <code>double</code> value.2429*2430* This method updates a column value in either the current row or2431* the insert row of this rowset, but it does not update the2432* database. If the cursor is on a row in the rowset, the2433* method {@link #updateRow} must be called to update the database.2434* If the cursor is on the insert row, the method {@link #insertRow}2435* must be called, which will insert the new row into both this rowset2436* and the database. Both of these methods must be called before the2437* cursor moves to another row.2438*2439* @param columnIndex the first column is <code>1</code>, the second2440* is <code>2</code>, and so on; must be <code>1</code> or larger2441* and equal to or less than the number of columns in this rowset2442* @param x the new column value2443* @throws SQLException if (1) the given column index is out of bounds,2444* (2) the cursor is not on one of this rowset's rows or its2445* insert row, or (3) this rowset is2446* <code>ResultSet.CONCUR_READ_ONLY</code>2447*/2448public void updateDouble(int columnIndex, double x) throws SQLException {2449crsInternal.updateDouble(columnIndex, x);2450}24512452/**2453* Sets the designated column in either the current row or the insert2454* row of this <code>JoinRowSetImpl</code> object with the given2455* <code>java.math.BigDecimal</code> object.2456* <P>2457* This method updates a column value in the current row or the insert2458* row of this rowset, but it does not update the database.2459* If the cursor is on a row in the rowset, the2460* method {@link #updateRow} must be called to update the database.2461* If the cursor is on the insert row, the method {@link #insertRow}2462* must be called, which will insert the new row into both this rowset2463* and the database. Both of these methods must be called before the2464* cursor moves to another row.2465*2466* @param columnIndex the first column is <code>1</code>, the second2467* is <code>2</code>, and so on; must be <code>1</code> or larger2468* and equal to or less than the number of columns in this rowset2469* @param x the new column value2470* @throws SQLException if (1) the given column index is out of bounds,2471* (2) the cursor is not on one of this rowset's rows or its2472* insert row, or (3) this rowset is2473* <code>ResultSet.CONCUR_READ_ONLY</code>2474*/2475public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {2476crsInternal.updateBigDecimal(columnIndex, x);2477}24782479/**2480* Sets the designated column in either the current row or the insert2481* row of this <code>JoinRowSetImpl</code> object with the given2482* <code>String</code> object.2483* <P>2484* This method updates a column value in either the current row or2485* the insert row of this rowset, but it does not update the2486* database. If the cursor is on a row in the rowset, the2487* method {@link #updateRow} must be called to mark the row as updated.2488* If the cursor is on the insert row, the method {@link #insertRow}2489* must be called to insert the new row into this rowset and mark it2490* as inserted. Both of these methods must be called before the2491* cursor moves to another row.2492* <P>2493* The method <code>acceptChanges</code> must be called if the2494* updated values are to be written back to the underlying database.2495*2496* @param columnIndex the first column is <code>1</code>, the second2497* is <code>2</code>, and so on; must be <code>1</code> or larger2498* and equal to or less than the number of columns in this rowset2499* @param x the new column value2500* @throws SQLException if (1) the given column index is out of bounds,2501* (2) the cursor is not on one of this rowset's rows or its2502* insert row, or (3) this rowset is2503* <code>ResultSet.CONCUR_READ_ONLY</code>2504*/2505public void updateString(int columnIndex, String x) throws SQLException {2506crsInternal.updateString(columnIndex, x);2507}25082509/**2510* Sets the designated column in either the current row or the insert2511* row of this <code>JoinRowSetImpl</code> object with the given2512* <code>byte</code> array.2513*2514* This method updates a column value in either the current row or2515* the insert row of this rowset, but it does not update the2516* database. If the cursor is on a row in the rowset, the2517* method {@link #updateRow} must be called to update the database.2518* If the cursor is on the insert row, the method {@link #insertRow}2519* must be called, which will insert the new row into both this rowset2520* and the database. Both of these methods must be called before the2521* cursor moves to another row.2522*2523* @param columnIndex the first column is <code>1</code>, the second2524* is <code>2</code>, and so on; must be <code>1</code> or larger2525* and equal to or less than the number of columns in this rowset2526* @param x the new column value2527* @throws SQLException if (1) the given column index is out of bounds,2528* (2) the cursor is not on one of this rowset's rows or its2529* insert row, or (3) this rowset is2530* <code>ResultSet.CONCUR_READ_ONLY</code>2531*/2532public void updateBytes(int columnIndex, byte x[]) throws SQLException {2533crsInternal.updateBytes(columnIndex, x);2534}25352536/**2537* Sets the designated column in either the current row or the insert2538* row of this <code>JoinRowSetImpl</code> object with the given2539* <code>Date</code> object.2540*2541* This method updates a column value in either the current row or2542* the insert row of this rowset, but it does not update the2543* database. If the cursor is on a row in the rowset, the2544* method {@link #updateRow} must be called to update the database.2545* If the cursor is on the insert row, the method {@link #insertRow}2546* must be called, which will insert the new row into both this rowset2547* and the database. Both of these methods must be called before the2548* cursor moves to another row.2549*2550* @param columnIndex the first column is <code>1</code>, the second2551* is <code>2</code>, and so on; must be <code>1</code> or larger2552* and equal to or less than the number of columns in this rowset2553* @param x the new column value2554* @throws SQLException if (1) the given column index is out of bounds,2555* (2) the cursor is not on one of this rowset's rows or its2556* insert row, (3) the type of the designated column is not2557* an SQL <code>DATE</code> or <code>TIMESTAMP</code>, or2558* (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2559*/2560public void updateDate(int columnIndex, java.sql.Date x) throws SQLException {2561crsInternal.updateDate(columnIndex, x);2562}25632564/**2565* Sets the designated column in either the current row or the insert2566* row of this <code>JoinRowSetImpl</code> object with the given2567* <code>Time</code> object.2568*2569* This method updates a column value in either the current row or2570* the insert row of this rowset, but it does not update the2571* database. If the cursor is on a row in the rowset, the2572* method {@link #updateRow} must be called to update the database.2573* If the cursor is on the insert row, the method {@link #insertRow}2574* must be called, which will insert the new row into both this rowset2575* and the database. Both of these methods must be called before the2576* cursor moves to another row.2577*2578* @param columnIndex the first column is <code>1</code>, the second2579* is <code>2</code>, and so on; must be <code>1</code> or larger2580* and equal to or less than the number of columns in this rowset2581* @param x the new column value2582* @throws SQLException if (1) the given column index is out of bounds,2583* (2) the cursor is not on one of this rowset's rows or its2584* insert row, (3) the type of the designated column is not2585* an SQL <code>TIME</code> or <code>TIMESTAMP</code>, or2586* (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2587*/2588public void updateTime(int columnIndex, java.sql.Time x) throws SQLException {2589crsInternal.updateTime(columnIndex, x);2590}25912592/**2593* Sets the designated column in either the current row or the insert2594* row of this <code>JoinRowSetImpl</code> object with the given2595* <code>Timestamp</code> object.2596*2597* This method updates a column value in either the current row or2598* the insert row of this rowset, but it does not update the2599* database. If the cursor is on a row in the rowset, the2600* method {@link #updateRow} must be called to update the database.2601* If the cursor is on the insert row, the method {@link #insertRow}2602* must be called, which will insert the new row into both this rowset2603* and the database. Both of these methods must be called before the2604* cursor moves to another row.2605*2606* @param columnIndex the first column is <code>1</code>, the second2607* is <code>2</code>, and so on; must be <code>1</code> or larger2608* and equal to or less than the number of columns in this rowset2609* @param x the new column value2610* @throws SQLException if (1) the given column index is out of bounds,2611* (2) the cursor is not on one of this rowset's rows or its2612* insert row, (3) the type of the designated column is not2613* an SQL <code>DATE</code>, <code>TIME</code>, or2614* <code>TIMESTAMP</code>, or (4) this rowset is2615* <code>ResultSet.CONCUR_READ_ONLY</code>2616*/2617public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException {2618crsInternal.updateTimestamp(columnIndex, x);2619}26202621/*2622* Sets the designated column in either the current row or the insert2623* row of this <code>JoinRowSetImpl</code> object with the given2624* ASCII stream value.2625* <P>2626* This method updates a column value in either the current row or2627* the insert row of this rowset, but it does not update the2628* database. If the cursor is on a row in the rowset, the2629* method {@link #updateRow} must be called to update the database.2630* If the cursor is on the insert row, the method {@link #insertRow}2631* must be called, which will insert the new row into both this rowset2632* and the database. Both of these methods must be called before the2633* cursor moves to another row.2634*2635* @param columnIndex the first column is <code>1</code>, the second2636* is <code>2</code>, and so on; must be <code>1</code> or larger2637* and equal to or less than the number of columns in this rowset2638* @param x the new column value2639* @param length the number of one-byte ASCII characters in the stream2640* @throws UnsupportedOperationException if this method is invoked2641*/2642public void updateAsciiStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {2643crsInternal.updateAsciiStream(columnIndex, x, length);2644}26452646/**2647* Sets the designated column in either the current row or the insert2648* row of this <code>JoinRowSetImpl</code> object with the given2649* <code>java.io.InputStream</code> object.2650* <P>2651* This method updates a column value in either the current row or2652* the insert row of this rowset, but it does not update the2653* database. If the cursor is on a row in the rowset, the2654* method {@link #updateRow} must be called to update the database.2655* If the cursor is on the insert row, the method {@link #insertRow}2656* must be called, which will insert the new row into both this rowset2657* and the database. Both of these methods must be called before the2658* cursor moves to another row.2659*2660* @param columnIndex the first column is <code>1</code>, the second2661* is <code>2</code>, and so on; must be <code>1</code> or larger2662* and equal to or less than the number of columns in this rowset2663* @param x the new column value; must be a <code>java.io.InputStream</code>2664* containing <code>BINARY</code>, <code>VARBINARY</code>, or2665* <code>LONGVARBINARY</code> data2666* @param length the length of the stream in bytes2667* @throws SQLException if (1) the given column index is out of bounds,2668* (2) the cursor is not on one of this rowset's rows or its2669* insert row, (3) the data in the stream is not binary, or2670* (4) this rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2671*/2672public void updateBinaryStream(int columnIndex, java.io.InputStream x, int length) throws SQLException {2673crsInternal.updateBinaryStream(columnIndex, x, length);2674}26752676/**2677* Sets the designated column in either the current row or the insert2678* row of this <code>JoinRowSetImpl</code> object with the given2679* <code>java.io.Reader</code> object.2680* <P>2681* This method updates a column value in either the current row or2682* the insert row of this rowset, but it does not update the2683* database. If the cursor is on a row in the rowset, the2684* method {@link #updateRow} must be called to update the database.2685* If the cursor is on the insert row, the method {@link #insertRow}2686* must be called, which will insert the new row into both this rowset2687* and the database. Both of these methods must be called before the2688* cursor moves to another row.2689*2690* @param columnIndex the first column is <code>1</code>, the second2691* is <code>2</code>, and so on; must be <code>1</code> or larger2692* and equal to or less than the number of columns in this rowset2693* @param x the new column value; must be a <code>java.io.Reader</code>2694* containing <code>BINARY</code>, <code>VARBINARY</code>,2695* <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,2696* or <code>LONGVARCHAR</code> data2697* @param length the length of the stream in characters2698* @throws SQLException if (1) the given column index is out of bounds,2699* (2) the cursor is not on one of this rowset's rows or its2700* insert row, (3) the data in the stream is not a binary or2701* character type, or (4) this rowset is2702* <code>ResultSet.CONCUR_READ_ONLY</code>2703*/2704public void updateCharacterStream(int columnIndex, java.io.Reader x, int length) throws SQLException {2705crsInternal.updateCharacterStream(columnIndex, x, length);2706}27072708/**2709* Sets the designated column in either the current row or the insert2710* row of this <code>JoinRowSetImpl</code> object with the given2711* <code>Object</code> value. The <code>scale</code> parameter indicates2712* the number of digits to the right of the decimal point and is ignored2713* if the new column value is not a type that will be mapped to an SQL2714* <code>DECIMAL</code> or <code>NUMERIC</code> value.2715* <P>2716* This method updates a column value in either the current row or2717* the insert row of this rowset, but it does not update the2718* database. If the cursor is on a row in the rowset, the2719* method {@link #updateRow} must be called to update the database.2720* If the cursor is on the insert row, the method {@link #insertRow}2721* must be called, which will insert the new row into both this rowset2722* and the database. Both of these methods must be called before the2723* cursor moves to another row.2724*2725* @param columnIndex the first column is <code>1</code>, the second2726* is <code>2</code>, and so on; must be <code>1</code> or larger2727* and equal to or less than the number of columns in this rowset2728* @param x the new column value2729* @param scale the number of digits to the right of the decimal point (for2730* <code>DECIMAL</code> and <code>NUMERIC</code> types only)2731* @throws SQLException if (1) the given column index is out of bounds,2732* (2) the cursor is not on one of this rowset's rows or its2733* insert row, or (3) this rowset is2734* <code>ResultSet.CONCUR_READ_ONLY</code>2735*/2736public void updateObject(int columnIndex, Object x, int scale) throws SQLException {2737crsInternal.updateObject(columnIndex, x, scale);2738}27392740/**2741* Sets the designated column in either the current row or the insert2742* row of this <code>JoinRowSetImpl</code> object with the given2743* <code>Object</code> value.2744* <P>2745* This method updates a column value in either the current row or2746* the insert row of this rowset, but it does not update the2747* database. If the cursor is on a row in the rowset, the2748* method {@link #updateRow} must be called to update the database.2749* If the cursor is on the insert row, the method {@link #insertRow}2750* must be called, which will insert the new row into both this rowset2751* and the database. Both of these methods must be called before the2752* cursor moves to another row.2753*2754* @param columnIndex the first column is <code>1</code>, the second2755* is <code>2</code>, and so on; must be <code>1</code> or larger2756* and equal to or less than the number of columns in this rowset2757* @param x the new column value2758* @throws SQLException if (1) the given column index is out of bounds,2759* (2) the cursor is not on one of this rowset's rows or its2760* insert row, or (3) this rowset is2761* <code>ResultSet.CONCUR_READ_ONLY</code>2762*/2763public void updateObject(int columnIndex, Object x) throws SQLException {2764crsInternal.updateObject(columnIndex, x);2765}27662767// columnName updates27682769/**2770* Sets the designated nullable column in the current row or the2771* insert row of this <code>JoinRowSetImpl</code> object with2772* <code>null</code> value.2773* <P>2774* This method updates a column value in the current row or the insert2775* row of this rowset, but it does not update the database.2776* If the cursor is on a row in the rowset, the2777* method {@link #updateRow} must be called to update the database.2778* If the cursor is on the insert row, the method {@link #insertRow}2779* must be called, which will insert the new row into both this rowset2780* and the database.2781*2782* @param columnName a <code>String</code> object that must match the2783* SQL name of a column in this rowset, ignoring case2784* @throws SQLException if (1) the given column name does not match the2785* name of a column in this rowset, (2) the cursor is not on2786* one of this rowset's rows or its insert row, or (3) this2787* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2788*/2789public void updateNull(String columnName) throws SQLException {2790crsInternal.updateNull(columnName);2791}27922793/**2794* Sets the designated column in either the current row or the insert2795* row of this <code>JoinRowSetImpl</code> object with the given2796* <code>boolean</code> value.2797* <P>2798* This method updates a column value in the current row or the insert2799* row of this rowset, but it does not update the database.2800* If the cursor is on a row in the rowset, the2801* method {@link #updateRow} must be called to update the database.2802* If the cursor is on the insert row, the method {@link #insertRow}2803* must be called, which will insert the new row into both this rowset2804* and the database. Both of these methods must be called before the2805* cursor moves to another row.2806*2807* @param columnName a <code>String</code> object that must match the2808* SQL name of a column in this rowset, ignoring case2809* @param x the new column value2810* @throws SQLException if (1) the given column name does not match the2811* name of a column in this rowset, (2) the cursor is not on2812* one of this rowset's rows or its insert row, or (3) this2813* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2814*/2815public void updateBoolean(String columnName, boolean x) throws SQLException {2816crsInternal.updateBoolean(columnName, x);2817}28182819/**2820* Sets the designated column in either the current row or the insert2821* row of this <code>JoinRowSetImpl</code> object with the given2822* <code>byte</code> value.2823* <P>2824* This method updates a column value in the current row or the insert2825* row of this rowset, but it does not update the database.2826* If the cursor is on a row in the rowset, the2827* method {@link #updateRow} must be called to update the database.2828* If the cursor is on the insert row, the method {@link #insertRow}2829* must be called, which will insert the new row into both this rowset2830* and the database. Both of these methods must be called before the2831* cursor moves to another row.2832*2833* @param columnName a <code>String</code> object that must match the2834* SQL name of a column in this rowset, ignoring case2835* @param x the new column value2836* @throws SQLException if (1) the given column name does not match the2837* name of a column in this rowset, (2) the cursor is not on2838* one of this rowset's rows or its insert row, or (3) this2839* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2840*/2841public void updateByte(String columnName, byte x) throws SQLException {2842crsInternal.updateByte(columnName, x);2843}28442845/**2846* Sets the designated column in either the current row or the insert2847* row of this <code>JoinRowSetImpl</code> object with the given2848* <code>short</code> value.2849* <P>2850* This method updates a column value in the current row or the insert2851* row of this rowset, but it does not update the database.2852* If the cursor is on a row in the rowset, the2853* method {@link #updateRow} must be called to update the database.2854* If the cursor is on the insert row, the method {@link #insertRow}2855* must be called, which will insert the new row into both this rowset2856* and the database. Both of these methods must be called before the2857* cursor moves to another row.2858*2859* @param columnName a <code>String</code> object that must match the2860* SQL name of a column in this rowset, ignoring case2861* @param x the new column value2862* @throws SQLException if (1) the given column name does not match the2863* name of a column in this rowset, (2) the cursor is not on2864* one of this rowset's rows or its insert row, or (3) this2865* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2866*/2867public void updateShort(String columnName, short x) throws SQLException {2868crsInternal.updateShort(columnName, x);2869}28702871/**2872* Sets the designated column in either the current row or the insert2873* row of this <code>JoinRowSetImpl</code> object with the given2874* <code>int</code> value.2875* <P>2876* This method updates a column value in the current row or the insert2877* row of this rowset, but it does not update the database.2878* If the cursor is on a row in the rowset, the2879* method {@link #updateRow} must be called to update the database.2880* If the cursor is on the insert row, the method {@link #insertRow}2881* must be called, which will insert the new row into both this rowset2882* and the database. Both of these methods must be called before the2883* cursor moves to another row.2884*2885* @param columnName a <code>String</code> object that must match the2886* SQL name of a column in this rowset, ignoring case2887* @param x the new column value2888* @throws SQLException if (1) the given column name does not match the2889* name of a column in this rowset, (2) the cursor is not on2890* one of this rowset's rows or its insert row, or (3) this2891* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2892*/2893public void updateInt(String columnName, int x) throws SQLException {2894crsInternal.updateInt(columnName, x);2895}28962897/**2898* Sets the designated column in either the current row or the insert2899* row of this <code>JoinRowSetImpl</code> object with the given2900* <code>long</code> value.2901* <P>2902* This method updates a column value in the current row or the insert2903* row of this rowset, but it does not update the database.2904* If the cursor is on a row in the rowset, the2905* method {@link #updateRow} must be called to update the database.2906* If the cursor is on the insert row, the method {@link #insertRow}2907* must be called, which will insert the new row into both this rowset2908* and the database. Both of these methods must be called before the2909* cursor moves to another row.2910*2911* @param columnName a <code>String</code> object that must match the2912* SQL name of a column in this rowset, ignoring case2913* @param x the new column value2914* @throws SQLException if (1) the given column name does not match the2915* name of a column in this rowset, (2) the cursor is not on2916* one of this rowset's rows or its insert row, or (3) this2917* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2918*/2919public void updateLong(String columnName, long x) throws SQLException {2920crsInternal.updateLong(columnName, x);2921}29222923/**2924* Sets the designated column in either the current row or the insert2925* row of this <code>JoinRowSetImpl</code> object with the given2926* <code>float</code> value.2927* <P>2928* This method updates a column value in the current row or the insert2929* row of this rowset, but it does not update the database.2930* If the cursor is on a row in the rowset, the2931* method {@link #updateRow} must be called to update the database.2932* If the cursor is on the insert row, the method {@link #insertRow}2933* must be called, which will insert the new row into both this rowset2934* and the database. Both of these methods must be called before the2935* cursor moves to another row.2936*2937* @param columnName a <code>String</code> object that must match the2938* SQL name of a column in this rowset, ignoring case2939* @param x the new column value2940* @throws SQLException if (1) the given column name does not match the2941* name of a column in this rowset, (2) the cursor is not on2942* one of this rowset's rows or its insert row, or (3) this2943* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2944*/2945public void updateFloat(String columnName, float x) throws SQLException {2946crsInternal.updateFloat(columnName, x);2947}29482949/**2950* Sets the designated column in either the current row or the insert2951* row of this <code>JoinRowSetImpl</code> object with the given2952* <code>double</code> value.2953*2954* This method updates a column value in either the current row or2955* the insert row of this rowset, but it does not update the2956* database. If the cursor is on a row in the rowset, the2957* method {@link #updateRow} must be called to update the database.2958* If the cursor is on the insert row, the method {@link #insertRow}2959* must be called, which will insert the new row into both this rowset2960* and the database. Both of these methods must be called before the2961* cursor moves to another row.2962*2963* @param columnName a <code>String</code> object that must match the2964* SQL name of a column in this rowset, ignoring case2965* @param x the new column value2966* @throws SQLException if (1) the given column name does not match the2967* name of a column in this rowset, (2) the cursor is not on2968* one of this rowset's rows or its insert row, or (3) this2969* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2970*/2971public void updateDouble(String columnName, double x) throws SQLException {2972crsInternal.updateDouble(columnName, x);2973}29742975/**2976* Sets the designated column in either the current row or the insert2977* row of this <code>JoinRowSetImpl</code> object with the given2978* <code>java.math.BigDecimal</code> object.2979* <P>2980* This method updates a column value in the current row or the insert2981* row of this rowset, but it does not update the database.2982* If the cursor is on a row in the rowset, the2983* method {@link #updateRow} must be called to update the database.2984* If the cursor is on the insert row, the method {@link #insertRow}2985* must be called, which will insert the new row into both this rowset2986* and the database. Both of these methods must be called before the2987* cursor moves to another row.2988*2989* @param columnName a <code>String</code> object that must match the2990* SQL name of a column in this rowset, ignoring case2991* @param x the new column value2992* @throws SQLException if (1) the given column name does not match the2993* name of a column in this rowset, (2) the cursor is not on2994* one of this rowset's rows or its insert row, or (3) this2995* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>2996*/2997public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {2998crsInternal.updateBigDecimal(columnName, x);2999}30003001/**3002* Sets the designated column in either the current row or the insert3003* row of this <code>JoinRowSetImpl</code> object with the given3004* <code>String</code> object.3005*3006* This method updates a column value in either the current row or3007* the insert row of this rowset, but it does not update the3008* database. If the cursor is on a row in the rowset, the3009* method {@link #updateRow} must be called to update the database.3010* If the cursor is on the insert row, the method {@link #insertRow}3011* must be called, which will insert the new row into both this rowset3012* and the database. Both of these methods must be called before the3013* cursor moves to another row.3014*3015* @param columnName a <code>String</code> object that must match the3016* SQL name of a column in this rowset, ignoring case3017* @param x the new column value3018* @throws SQLException if (1) the given column name does not match the3019* name of a column in this rowset, (2) the cursor is not on3020* one of this rowset's rows or its insert row, or (3) this3021* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3022*/3023public void updateString(String columnName, String x) throws SQLException {3024crsInternal.updateString(columnName, x);3025}30263027/**3028* Sets the designated column in either the current row or the insert3029* row of this <code>JoinRowSetImpl</code> object with the given3030* <code>byte</code> array.3031*3032* This method updates a column value in either the current row or3033* the insert row of this rowset, but it does not update the3034* database. If the cursor is on a row in the rowset, the3035* method {@link #updateRow} must be called to update the database.3036* If the cursor is on the insert row, the method {@link #insertRow}3037* must be called, which will insert the new row into both this rowset3038* and the database. Both of these methods must be called before the3039* cursor moves to another row.3040*3041* @param columnName a <code>String</code> object that must match the3042* SQL name of a column in this rowset, ignoring case3043* @param x the new column value3044* @throws SQLException if (1) the given column name does not match the3045* name of a column in this rowset, (2) the cursor is not on3046* one of this rowset's rows or its insert row, or (3) this3047* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3048*/3049public void updateBytes(String columnName, byte x[]) throws SQLException {3050crsInternal.updateBytes(columnName, x);3051}30523053/**3054* Sets the designated column in either the current row or the insert3055* row of this <code>JoinRowSetImpl</code> object with the given3056* <code>Date</code> object.3057*3058* This method updates a column value in either the current row or3059* the insert row of this rowset, but it does not update the3060* database. If the cursor is on a row in the rowset, the3061* method {@link #updateRow} must be called to update the database.3062* If the cursor is on the insert row, the method {@link #insertRow}3063* must be called, which will insert the new row into both this rowset3064* and the database. Both of these methods must be called before the3065* cursor moves to another row.3066*3067* @param columnName a <code>String</code> object that must match the3068* SQL name of a column in this rowset, ignoring case3069* @param x the new column value3070* @throws SQLException if (1) the given column name does not match the3071* name of a column in this rowset, (2) the cursor is not on3072* one of this rowset's rows or its insert row, (3) the type3073* of the designated column is not an SQL <code>DATE</code> or3074* <code>TIMESTAMP</code>, or (4) this rowset is3075* <code>ResultSet.CONCUR_READ_ONLY</code>3076*/3077public void updateDate(String columnName, java.sql.Date x) throws SQLException {3078crsInternal.updateDate(columnName, x);3079}30803081/**3082* Sets the designated column in either the current row or the insert3083* row of this <code>JoinRowSetImpl</code> object with the given3084* <code>Time</code> object.3085*3086* This method updates a column value in either the current row or3087* the insert row of this rowset, but it does not update the3088* database. If the cursor is on a row in the rowset, the3089* method {@link #updateRow} must be called to update the database.3090* If the cursor is on the insert row, the method {@link #insertRow}3091* must be called, which will insert the new row into both this rowset3092* and the database. Both of these methods must be called before the3093* cursor moves to another row.3094*3095* @param columnName a <code>String</code> object that must match the3096* SQL name of a column in this rowset, ignoring case3097* @param x the new column value3098* @throws SQLException if (1) the given column name does not match the3099* name of a column in this rowset, (2) the cursor is not on3100* one of this rowset's rows or its insert row, (3) the type3101* of the designated column is not an SQL <code>TIME</code> or3102* <code>TIMESTAMP</code>, or (4) this rowset is3103* <code>ResultSet.CONCUR_READ_ONLY</code>3104*/3105public void updateTime(String columnName, java.sql.Time x) throws SQLException {3106crsInternal.updateTime(columnName, x);3107}31083109/**3110* Sets the designated column in either the current row or the insert3111* row of this <code>JoinRowSetImpl</code> object with the given3112* <code>Timestamp</code> object.3113*3114* This method updates a column value in either the current row or3115* the insert row of this rowset, but it does not update the3116* database. If the cursor is on a row in the rowset, the3117* method {@link #updateRow} must be called to update the database.3118* If the cursor is on the insert row, the method {@link #insertRow}3119* must be called, which will insert the new row into both this rowset3120* and the database. Both of these methods must be called before the3121* cursor moves to another row.3122*3123* @param columnName a <code>String</code> object that must match the3124* SQL name of a column in this rowset, ignoring case3125* @param x the new column value3126* @throws SQLException if the given column index is out of bounds or3127* the cursor is not on one of this rowset's rows or its3128* insert row3129* @throws SQLException if (1) the given column name does not match the3130* name of a column in this rowset, (2) the cursor is not on3131* one of this rowset's rows or its insert row, (3) the type3132* of the designated column is not an SQL <code>DATE</code>,3133* <code>TIME</code>, or <code>TIMESTAMP</code>, or (4) this3134* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3135*/3136public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException {3137crsInternal.updateTimestamp(columnName, x);3138}31393140/**3141* Unsupported; throws an <code>UnsupportedOperationException</code>3142* if called.3143* <P>3144* Sets the designated column in either the current row or the insert3145* row of this <code>JoinRowSetImpl</code> object with the given3146* ASCII stream value.3147* <P>3148* This method updates a column value in either the current row or3149* the insert row of this rowset, but it does not update the3150* database. If the cursor is on a row in the rowset, the3151* method {@link #updateRow} must be called to update the database.3152* If the cursor is on the insert row, the method {@link #insertRow}3153* must be called, which will insert the new row into both this rowset3154* and the database. Both of these methods must be called before the3155* cursor moves to another row.3156*3157* @param columnName a <code>String</code> object that must match the3158* SQL name of a column in this rowset, ignoring case3159* @param x the new column value3160* @param length the number of one-byte ASCII characters in the stream3161* @throws UnsupportedOperationException if this method is invoked3162*/3163public void updateAsciiStream(String columnName, java.io.InputStream x, int length) throws SQLException {3164crsInternal.updateAsciiStream(columnName, x, length);3165}31663167/**3168* Sets the designated column in either the current row or the insert3169* row of this <code>JoinRowSetImpl</code> object with the given3170* <code>java.io.InputStream</code> object.3171* <P>3172* This method updates a column value in either the current row or3173* the insert row of this rowset, but it does not update the3174* database. If the cursor is on a row in the rowset, the3175* method {@link #updateRow} must be called to update the database.3176* If the cursor is on the insert row, the method {@link #insertRow}3177* must be called, which will insert the new row into both this rowset3178* and the database. Both of these methods must be called before the3179* cursor moves to another row.3180*3181* @param columnName a <code>String</code> object that must match the3182* SQL name of a column in this rowset, ignoring case3183* @param x the new column value; must be a <code>java.io.InputStream</code>3184* containing <code>BINARY</code>, <code>VARBINARY</code>, or3185* <code>LONGVARBINARY</code> data3186* @param length the length of the stream in bytes3187* @throws SQLException if (1) the given column name does not match the3188* name of a column in this rowset, (2) the cursor is not on3189* one of this rowset's rows or its insert row, (3) the data3190* in the stream is not binary, or (4) this rowset is3191* <code>ResultSet.CONCUR_READ_ONLY</code>3192*/3193public void updateBinaryStream(String columnName, java.io.InputStream x, int length) throws SQLException {3194crsInternal.updateBinaryStream(columnName, x, length);3195}31963197/**3198* Sets the designated column in either the current row or the insert3199* row of this <code>JoinRowSetImpl</code> object with the given3200* <code>java.io.Reader</code> object.3201* <P>3202* This method updates a column value in either the current row or3203* the insert row of this rowset, but it does not update the3204* database. If the cursor is on a row in the rowset, the3205* method {@link #updateRow} must be called to update the database.3206* If the cursor is on the insert row, the method {@link #insertRow}3207* must be called, which will insert the new row into both this rowset3208* and the database. Both of these methods must be called before the3209* cursor moves to another row.3210*3211* @param columnName a <code>String</code> object that must match the3212* SQL name of a column in this rowset, ignoring case3213* @param x the new column value; must be a <code>java.io.Reader</code>3214* containing <code>BINARY</code>, <code>VARBINARY</code>,3215* <code>LONGVARBINARY</code>, <code>CHAR</code>, <code>VARCHAR</code>,3216* or <code>LONGVARCHAR</code> data3217* @param length the length of the stream in characters3218* @throws SQLException if (1) the given column name does not match the3219* name of a column in this rowset, (2) the cursor is not on3220* one of this rowset's rows or its insert row, (3) the data3221* in the stream is not a binary or character type, or (4) this3222* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3223*/3224public void updateCharacterStream(String columnName, java.io.Reader x, int length) throws SQLException {3225crsInternal.updateCharacterStream(columnName, x, length);3226}32273228/**3229* Sets the designated column in either the current row or the insert3230* row of this <code>JoinRowSetImpl</code> object with the given3231* <code>Object</code> value. The <code>scale</code> parameter3232* indicates the number of digits to the right of the decimal point3233* and is ignored if the new column value is not a type that will be3234* mapped to an SQL <code>DECIMAL</code> or <code>NUMERIC</code> value.3235* <P>3236* This method updates a column value in either the current row or3237* the insert row of this rowset, but it does not update the3238* database. If the cursor is on a row in the rowset, the3239* method {@link #updateRow} must be called to update the database.3240* If the cursor is on the insert row, the method {@link #insertRow}3241* must be called, which will insert the new row into both this rowset3242* and the database. Both of these methods must be called before the3243* cursor moves to another row.3244*3245* @param columnName a <code>String</code> object that must match the3246* SQL name of a column in this rowset, ignoring case3247* @param x the new column value3248* @param scale the number of digits to the right of the decimal point (for3249* <code>DECIMAL</code> and <code>NUMERIC</code> types only)3250* @throws SQLException if the given column index is out of bounds or3251* the cursor is not on one of this rowset's rows or its3252* insert row3253* @throws SQLException if (1) the given column name does not match the3254* name of a column in this rowset, (2) the cursor is not on3255* one of this rowset's rows or its insert row, or (3) this3256* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3257*/3258public void updateObject(String columnName, Object x, int scale) throws SQLException {3259crsInternal.updateObject(columnName, x, scale);3260}32613262/**3263* Sets the designated column in either the current row or the insert3264* row of this <code>JoinRowSetImpl</code> object with the given3265* <code>Object</code> value.3266* <P>3267* This method updates a column value in either the current row or3268* the insert row of this rowset, but it does not update the3269* database. If the cursor is on a row in the rowset, the3270* method {@link #updateRow} must be called to update the database.3271* If the cursor is on the insert row, the method {@link #insertRow}3272* must be called, which will insert the new row into both this rowset3273* and the database. Both of these methods must be called before the3274* cursor moves to another row.3275*3276* @param columnName a <code>String</code> object that must match the3277* SQL name of a column in this rowset, ignoring case3278* @param x the new column value3279* @throws SQLException if (1) the given column name does not match the3280* name of a column in this rowset, (2) the cursor is not on3281* one of this rowset's rows or its insert row, or (3) this3282* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3283*/3284public void updateObject(String columnName, Object x) throws SQLException {3285crsInternal.updateObject(columnName, x);3286}32873288/**3289* Inserts the contents of this <code>JoinRowSetImpl</code> object's insert3290* row into this rowset immediately following the current row.3291* If the current row is the3292* position after the last row or before the first row, the new row will3293* be inserted at the end of the rowset. This method also notifies3294* listeners registered with this rowset that the row has changed.3295* <P>3296* The cursor must be on the insert row when this method is called.3297*3298* @throws SQLException if (1) the cursor is not on the insert row,3299* (2) one or more of the non-nullable columns in the insert3300* row has not been given a value, or (3) this rowset is3301* <code>ResultSet.CONCUR_READ_ONLY</code>3302*/3303public void insertRow() throws SQLException {3304crsInternal.insertRow();3305}33063307/**3308* Marks the current row of this <code>JoinRowSetImpl</code> object as3309* updated and notifies listeners registered with this rowset that the3310* row has changed.3311* <P>3312* This method cannot be called when the cursor is on the insert row, and3313* it should be called before the cursor moves to another row. If it is3314* called after the cursor moves to another row, this method has no effect,3315* and the updates made before the cursor moved will be lost.3316*3317* @throws SQLException if the cursor is on the insert row or this3318* rowset is <code>ResultSet.CONCUR_READ_ONLY</code>3319*/3320public void updateRow() throws SQLException {3321crsInternal.updateRow();3322}33233324/**3325* Deletes the current row from this <code>JoinRowSetImpl</code> object and3326* notifies listeners registered with this rowset that a row has changed.3327* This method cannot be called when the cursor is on the insert row.3328* <P>3329* This method marks the current row as deleted, but it does not delete3330* the row from the underlying data source. The method3331* <code>acceptChanges</code> must be called to delete the row in3332* the data source.3333*3334* @throws SQLException if (1) this method is called when the cursor3335* is on the insert row, before the first row, or after the3336* last row or (2) this rowset is3337* <code>ResultSet.CONCUR_READ_ONLY</code>3338*/3339public void deleteRow() throws SQLException {3340crsInternal.deleteRow();3341}33423343/**3344* Sets the current row with its original value and marks the row as3345* not updated, thus undoing any changes made to the row since the3346* last call to the methods <code>updateRow</code> or <code>deleteRow</code>.3347* This method should be called only when the cursor is on a row in3348* this rowset.3349*3350* @throws SQLException if the cursor is on the insert row, before the3351* first row, or after the last row3352*/3353public void refreshRow() throws SQLException {3354crsInternal.refreshRow();3355}33563357/**3358* Rolls back any updates made to the current row of this3359* <code>JoinRowSetImpl</code> object and notifies listeners that3360* a row has changed. To have an effect, this method3361* must be called after an <code>updateXXX</code> method has been3362* called and before the method <code>updateRow</code> has been called.3363* If no updates have been made or the method <code>updateRow</code>3364* has already been called, this method has no effect.3365* <P>3366* After <code>updateRow</code> is called it is the3367* <code>cancelRowUpdates</code> has no affect on the newly3368* inserted values. The method <code>cancelRowInsert</code> can3369* be used to remove any rows inserted into the RowSet.3370*3371* @throws SQLException if the cursor is on the insert row, before the3372* first row, or after the last row3373*/3374public void cancelRowUpdates() throws SQLException {3375crsInternal.cancelRowUpdates();3376}33773378/**3379* Moves the cursor for this <code>JoinRowSetImpl</code> object3380* to the insert row. The current row in the rowset is remembered3381* while the cursor is on the insert row.3382* <P>3383* The insert row is a special row associated with an updatable3384* rowset. It is essentially a buffer where a new row may3385* be constructed by calling the appropriate <code>updateXXX</code>3386* methods to assign a value to each column in the row. A complete3387* row must be constructed; that is, every column that is not nullable3388* must be assigned a value. In order for the new row to become part3389* of this rowset, the method <code>insertRow</code> must be called3390* before the cursor is moved back to the rowset.3391* <P>3392* Only certain methods may be invoked while the cursor is on the insert3393* row; many methods throw an exception if they are called while the3394* cursor is there. In addition to the <code>updateXXX</code>3395* and <code>insertRow</code> methods, only the <code>getXXX</code> methods3396* may be called when the cursor is on the insert row. A <code>getXXX</code>3397* method should be called on a column only after an <code>updateXXX</code>3398* method has been called on that column; otherwise, the value returned is3399* undetermined.3400*3401* @throws SQLException if this <code>JoinRowSetImpl</code> object is3402* <code>ResultSet.CONCUR_READ_ONLY</code>3403*/3404public void moveToInsertRow() throws SQLException {3405crsInternal.moveToInsertRow();3406}34073408/**3409* Moves the cursor for this <code>JoinRowSetImpl</code> object to3410* the current row. The current row is the row the cursor was on3411* when the method <code>moveToInsertRow</code> was called.3412* <P>3413* Calling this method has no effect unless it is called while the3414* cursor is on the insert row.3415*3416* @throws SQLException if an error occurs3417*/3418public void moveToCurrentRow() throws SQLException {3419crsInternal.moveToCurrentRow();3420}34213422/**3423* Returns <code>null</code>.3424*3425* @return <code>null</code>3426* @throws SQLException if an error occurs3427*/3428public Statement getStatement() throws SQLException {3429return crsInternal.getStatement();3430}34313432/**3433* Retrieves the value of the designated column in this3434* <code>JoinRowSetImpl</code> object as a <code>Ref</code> object3435* in the Java programming lanugage.3436*3437* @param columnIndex the first column is <code>1</code>, the second3438* is <code>2</code>, and so on; must be <code>1</code> or larger3439* and equal to or less than the number of columns in this rowset3440* @return a <code>Ref</code> object representing an SQL<code> REF</code> value3441* @throws SQLException if (1) the given column index is out of bounds,3442* (2) the cursor is not on one of this rowset's rows or its3443* insert row, or (3) the designated column does not store an3444* SQL <code>REF</code> value3445*/3446public Ref getRef(int columnIndex) throws SQLException {3447return crsInternal.getRef(columnIndex);3448}34493450/**3451* Retrieves the value of the designated column in this3452* <code>JoinRowSetImpl</code> object as a <code>Blob</code> object3453* in the Java programming lanugage.3454*3455* @param columnIndex the first column is <code>1</code>, the second3456* is <code>2</code>, and so on; must be <code>1</code> or larger3457* and equal to or less than the number of columns in this rowset3458* @return a <code>Blob</code> object representing an SQL <code>BLOB</code> value3459* @throws SQLException if (1) the given column index is out of bounds,3460* (2) the cursor is not on one of this rowset's rows or its3461* insert row, or (3) the designated column does not store an3462* SQL <code>BLOB</code> value3463*/3464public Blob getBlob(int columnIndex) throws SQLException {3465return crsInternal.getBlob(columnIndex);3466}34673468/**3469* Retrieves the value of the designated column in this3470* <code>JoinRowSetImpl</code> object as a <code>Clob</code> object3471* in the Java programming lanugage.3472*3473* @param columnIndex the first column is <code>1</code>, the second3474* is <code>2</code>, and so on; must be <code>1</code> or larger3475* and equal to or less than the number of columns in this rowset3476* @return a <code>Clob</code> object representing an SQL <code>CLOB</code> value3477* @throws SQLException if (1) the given column index is out of bounds,3478* (2) the cursor is not on one of this rowset's rows or its3479* insert row, or (3) the designated column does not store an3480* SQL <code>CLOB</code> value3481*/3482public Clob getClob(int columnIndex) throws SQLException {3483return crsInternal.getClob(columnIndex);3484}34853486/**3487* Retrieves the value of the designated column in this3488* <code>JoinRowSetImpl</code> object as an <code>Array</code> object3489* in the Java programming lanugage.3490*3491* @param columnIndex the first column is <code>1</code>, the second3492* is <code>2</code>, and so on; must be <code>1</code> or larger3493* and equal to or less than the number of columns in this rowset3494* @return an <code>Array</code> object representing an SQL3495* <code>ARRAY</code> value3496* @throws SQLException if (1) the given column index is out of bounds,3497* (2) the cursor is not on one of this rowset's rows or its3498* insert row, or (3) the designated column does not store an3499* SQL <code>ARRAY</code> value3500*/3501public Array getArray(int columnIndex) throws SQLException {3502return crsInternal.getArray(columnIndex);3503}35043505// ColumnName35063507/**3508* Retrieves the value of the designated column in this3509* <code>JoinRowSetImpl</code> object as a <code>Ref</code> object3510* in the Java programming lanugage.3511*3512* @param columnName a <code>String</code> object that must match the3513* SQL name of a column in this rowset, ignoring case3514* @return a <code>Ref</code> object representing an SQL<code> REF</code> value3515* @throws SQLException if (1) the given column name is not the name3516* of a column in this rowset, (2) the cursor is not on one of3517* this rowset's rows or its insert row, or (3) the column value3518* is not an SQL <code>REF</code> value3519*/3520public Ref getRef(String columnName) throws SQLException {3521return crsInternal.getRef(columnName);3522}35233524/**3525* Retrieves the value of the designated column in this3526* <code>JoinRowSetImpl</code> object as a <code>Blob</code> object3527* in the Java programming lanugage.3528*3529* @param columnName a <code>String</code> object that must match the3530* SQL name of a column in this rowset, ignoring case3531* @return a <code>Blob</code> object representing an SQL3532* <code>BLOB</code> value3533* @throws SQLException if (1) the given column name is not the name of3534* a column in this rowset, (2) the cursor is not on one of3535* this rowset's rows or its insert row, or (3) the designated3536* column does not store an SQL <code>BLOB</code> value3537*/3538public Blob getBlob(String columnName) throws SQLException {3539return crsInternal.getBlob(columnName);3540}35413542/**3543* Retrieves the value of the designated column in this3544* <code>JoinRowSetImpl</code> object as a <code>Clob</code> object3545* in the Java programming lanugage.3546*3547* @param columnName a <code>String</code> object that must match the3548* SQL name of a column in this rowset, ignoring case3549* @return a <code>Clob</code> object representing an SQL3550* <code>CLOB</code> value3551* @throws SQLException if (1) the given column name is not the name of3552* a column in this rowset, (2) the cursor is not on one of3553* this rowset's rows or its insert row, or (3) the designated3554* column does not store an SQL <code>CLOB</code> value3555*/3556public Clob getClob(String columnName) throws SQLException {3557return crsInternal.getClob(columnName);3558}35593560/**3561* Retrieves the value of the designated column in this3562* <code>JoinRowSetImpl</code> object as an <code>Array</code> object3563* in the Java programming lanugage.3564*3565* @param columnName a <code>String</code> object that must match the3566* SQL name of a column in this rowset, ignoring case3567* @return an <code>Array</code> object representing an SQL3568* <code>ARRAY</code> value3569* @throws SQLException if (1) the given column name is not the name of3570* a column in this rowset, (2) the cursor is not on one of3571* this rowset's rows or its insert row, or (3) the designated3572* column does not store an SQL <code>ARRAY</code> value3573*/3574public Array getArray(String columnName) throws SQLException {3575return crsInternal.getArray(columnName);3576}35773578/**3579* Retrieves the value of the designated column in the current row3580* of this <code>JoinRowSetImpl</code> object as a <code>java.sql.Date</code>3581* object, using the given <code>Calendar</code> object to construct an3582* appropriate millisecond value for the date.3583*3584* @param columnIndex the first column is <code>1</code>, the second3585* is <code>2</code>, and so on; must be <code>1</code> or larger3586* and equal to or less than the number of columns in the rowset3587* @param cal the <code>java.util.Calendar</code> object to use in3588* constructing the date3589* @return the column value; if the value is SQL <code>NULL</code>,3590* the result is <code>null</code>3591* @throws SQLException if (1) the given column name is not the name of3592* a column in this rowset, (2) the cursor is not on one of3593* this rowset's rows or its insert row, or (3) the designated3594* column does not store an SQL <code>DATE</code> or3595* <code>TIMESTAMP</code> value3596*/3597public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException {3598return crsInternal.getDate(columnIndex, cal);3599}36003601/**3602* Retrieves the value of the designated column in the current row3603* of this <code>JoinRowSetImpl</code> object as a <code>java.sql.Date</code>3604* object, using the given <code>Calendar</code> object to construct an3605* appropriate millisecond value for the date.3606*3607* @param columnName a <code>String</code> object that must match the3608* SQL name of a column in this rowset, ignoring case3609* @param cal the <code>java.util.Calendar</code> object to use in3610* constructing the date3611* @return the column value; if the value is SQL <code>NULL</code>,3612* the result is <code>null</code>3613* @throws SQLException if (1) the given column name is not the name of3614* a column in this rowset, (2) the cursor is not on one of3615* this rowset's rows or its insert row, or (3) the designated3616* column does not store an SQL <code>DATE</code> or3617* <code>TIMESTAMP</code> value3618*/3619public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException {3620return crsInternal.getDate(columnName, cal);3621}36223623/**3624* Retrieves the value of the designated column in the current row3625* of this <code>JoinRowSetImpl</code> object as a <code>java.sql.Time</code>3626* object, using the given <code>Calendar</code> object to construct an3627* appropriate millisecond value for the date.3628*3629* @param columnIndex the first column is <code>1</code>, the second3630* is <code>2</code>, and so on; must be <code>1</code> or larger3631* and equal to or less than the number of columns in the rowset3632* @param cal the <code>java.util.Calendar</code> object to use in3633* constructing the date3634* @return the column value; if the value is SQL <code>NULL</code>,3635* the result is <code>null</code>3636* @throws SQLException if (1) the given column name is not the name of3637* a column in this rowset, (2) the cursor is not on one of3638* this rowset's rows or its insert row, or (3) the designated3639* column does not store an SQL <code>TIME</code> or3640* <code>TIMESTAMP</code> value3641*/3642public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException {3643return crsInternal.getTime(columnIndex, cal);3644}36453646/**3647* Retrieves the value of the designated column in the current row3648* of this <code>JoinRowSetImpl</code> object as a <code>java.sql.Time</code>3649* object, using the given <code>Calendar</code> object to construct an3650* appropriate millisecond value for the date.3651*3652* @param columnName a <code>String</code> object that must match the3653* SQL name of a column in this rowset, ignoring case3654* @param cal the <code>java.util.Calendar</code> object to use in3655* constructing the date3656* @return the column value; if the value is SQL <code>NULL</code>,3657* the result is <code>null</code>3658* @throws SQLException if (1) the given column name is not the name of3659* a column in this rowset, (2) the cursor is not on one of3660* this rowset's rows or its insert row, or (3) the designated3661* column does not store an SQL <code>TIME</code> or3662* <code>TIMESTAMP</code> value3663*/3664public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException {3665return crsInternal.getTime(columnName, cal);3666}36673668/**3669* Retrieves the value of the designated column in the current row3670* of this <code>JoinRowSetImpl</code> object as a <code>java.sql.Timestamp</code>3671* object, using the given <code>Calendar</code> object to construct an3672* appropriate millisecond value for the date.3673*3674* @param columnIndex the first column is <code>1</code>, the second3675* is <code>2</code>, and so on; must be <code>1</code> or larger3676* and equal to or less than the number of columns in the rowset3677* @param cal the <code>java.util.Calendar</code> object to use in3678* constructing the date3679* @return the column value; if the value is SQL <code>NULL</code>,3680* the result is <code>null</code>3681* @throws SQLException if (1) the given column name is not the name of3682* a column in this rowset, (2) the cursor is not on one of3683* this rowset's rows or its insert row, or (3) the designated3684* column does not store an SQL <code>TIME</code> or3685* <code>TIMESTAMP</code> value3686*/3687public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {3688return crsInternal.getTimestamp(columnIndex, cal);3689}36903691/**3692* Retrieves the value of the designated column in the current row3693* of this <code>JoinRowSetImpl</code> object as a3694* <code>java.sql.Timestamp</code> object, using the given3695* <code>Calendar</code> object to construct an appropriate3696* millisecond value for the date.3697*3698* @param columnName a <code>String</code> object that must match the3699* SQL name of a column in this rowset, ignoring case3700* @param cal the <code>java.util.Calendar</code> object to use in3701* constructing the date3702* @return the column value; if the value is SQL <code>NULL</code>,3703* the result is <code>null</code>3704* @throws SQLException if (1) the given column name is not the name of3705* a column in this rowset, (2) the cursor is not on one of3706* this rowset's rows or its insert row, or (3) the designated3707* column does not store an SQL <code>DATE</code>,3708* <code>TIME</code>, or <code>TIMESTAMP</code> value3709*/3710public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {3711return crsInternal.getTimestamp(columnName, cal);3712}37133714/**3715* Sets the metadata for this <code>JoinRowSetImpl</code> object3716* with the given <code>RowSetMetaData</code> object.3717*3718* @param md a <code>RowSetMetaData</code> object instance containing3719* metadata about the columsn in the rowset3720* @throws SQLException if invalid meta data is supplied to the3721* rowset3722*/3723public void setMetaData(RowSetMetaData md) throws SQLException {3724crsInternal.setMetaData(md);3725}37263727public ResultSet getOriginal() throws SQLException {3728return crsInternal.getOriginal();3729}37303731/**3732* Returns a result set containing the original value of the rowset.3733* The cursor is positioned before the first row in the result set.3734* Only rows contained in the result set returned by getOriginal()3735* are said to have an original value.3736*3737* @return the original result set of the rowset3738* @throws SQLException if an error occurs produce the3739* <code>ResultSet</code> object3740*/3741public ResultSet getOriginalRow() throws SQLException {3742return crsInternal.getOriginalRow();3743}37443745/**3746* Returns a result set containing the original value of the current3747* row only.3748*3749* @throws SQLException if there is no current row3750* @see #setOriginalRow3751*/3752public void setOriginalRow() throws SQLException {3753crsInternal.setOriginalRow();3754}37553756/**3757* Returns the columns that make a key to uniquely identify a3758* row in this <code>JoinRowSetImpl</code> object.3759*3760* @return an array of column number that constites a primary3761* key for this rowset. This array should be empty3762* if no columns is representitive of a primary key3763* @throws SQLException if the rowset is empty or no columns3764* are designated as primary keys3765* @see #setKeyColumns3766*/3767public int[] getKeyColumns() throws SQLException {3768return crsInternal.getKeyColumns();3769}37703771/**3772* Sets this <code>JoinRowSetImpl</code> object's3773* <code>keyCols</code> field with the given array of column3774* numbers, which forms a key for uniquely identifying a row3775* in this rowset.3776*3777* @param cols an array of <code>int</code> indicating the3778* columns that form a primary key for this3779* <code>JoinRowSetImpl</code> object; every3780* element in the array must be greater than3781* <code>0</code> and less than or equal to the number3782* of columns in this rowset3783* @throws SQLException if any of the numbers in the3784* given array is not valid for this rowset3785* @see #getKeyColumns3786*/3787public void setKeyColumns(int[] cols) throws SQLException {3788crsInternal.setKeyColumns(cols);3789}37903791/**3792* Sets the designated column in either the current row or the insert3793* row of this <code>JoinRowSetImpl</code> object with the given3794* <code>Ref</code> value.3795* <P>3796* This method updates a column value in the current row or the insert3797* row of this rowset, but it does not update the database.3798* If the cursor is on a row in the rowset, the3799* method {@link #updateRow} must be called to update the database.3800* If the cursor is on the insert row, the method {@link #insertRow}3801* must be called, which will insert the new row into both this rowset3802* and the database. Either of these methods must be called before the3803* cursor moves to another row.3804*3805* @param columnIndex the first column is <code>1</code>, the second3806* is <code>2</code>, and so on; must be <code>1</code> or larger3807* and equal to or less than the number of columns in this rowset3808* @param ref the <code>java.sql.Ref</code> object that will be set as3809* the new column value3810* @throws SQLException if (1) the given column index is out of bounds,3811* (2) the cursor is not on one of this rowset's rows or its3812* insert row, or (3) this rowset is3813* <code>ResultSet.CONCUR_READ_ONLY</code>3814*/3815public void updateRef(int columnIndex, java.sql.Ref ref) throws SQLException {3816crsInternal.updateRef(columnIndex, ref);3817}38183819/**3820* Sets the designated column in either the current row or the insert3821* row of this <code>JoinRowSetImpl</code> object with the given3822* <code>Ref</code> value.3823* <P>3824* This method updates a column value in the current row or the insert3825* row of this rowset, but it does not update the database.3826* If the cursor is on a row in the rowset, the3827* method {@link #updateRow} must be called to update the database.3828* If the cursor is on the insert row, the method {@link #insertRow}3829* must be called, which will insert the new row into both this rowset3830* and the database. Either of these methods must be called before the3831* cursor moves to another row.3832*3833* @param columnName a <code>String</code> object giving the name of the column3834* to be updated; must match one of the column names in this3835* <code>JoinRowSetImpl</code> object3836* @param ref the <code>java.sql.Ref</code> object that will be set as3837* the new column value3838* @throws SQLException if (1) the given column name is not valid,3839* (2) the cursor is not on one of this rowset's rows or its3840* insert row, or (3) this rowset is3841* <code>ResultSet.CONCUR_READ_ONLY</code>3842*/3843public void updateRef(String columnName, java.sql.Ref ref) throws SQLException {3844crsInternal.updateRef(columnName, ref);3845}38463847/**3848* Sets the designated column in either the current row or the insert3849* row of this <code>JoinRowSetImpl</code> object with the given3850* <code>Clob</code> object.3851* <P>3852* This method updates a column value in the current row or the insert3853* row of this rowset, but it does not update the database.3854* If the cursor is on a row in the rowset, the3855* method {@link #updateRow} must be called to update the database.3856* If the cursor is on the insert row, the method {@link #insertRow}3857* must be called, which will insert the new row into both this rowset3858* and the database. Either of these methods must be called before the3859* cursor moves to another row.3860*3861* @param columnIndex the first column is <code>1</code>, the second3862* is <code>2</code>, and so on; must be <code>1</code> or larger3863* and equal to or less than the number of columns in this rowset3864* @param c the <code>java.sql.Clob</code> object that will be set as3865* the new column value3866* @throws SQLException if (1) the given column index is out of bounds,3867* (2) the cursor is not on one of this rowset's rows or its3868* insert row, or (3) this rowset is3869* <code>ResultSet.CONCUR_READ_ONLY</code>3870*/3871public void updateClob(int columnIndex, Clob c) throws SQLException {3872crsInternal.updateClob(columnIndex, c);3873}38743875/**3876* Sets the designated column in either the current row or the insert3877* row of this <code>JoinRowSetImpl</code> object with the given3878* <code>Clob</code> object.3879* <P>3880* This method updates a column value in the current row or the insert3881* row of this rowset, but it does not update the database.3882* If the cursor is on a row in the rowset, the3883* method {@link #updateRow} must be called to update the database.3884* If the cursor is on the insert row, the method {@link #insertRow}3885* must be called, which will insert the new row into both this rowset3886* and the database. Either of these methods must be called before the3887* cursor moves to another row.3888*3889* @param columnName a <code>String</code> object giving the name of the column3890* to be updated; must match one of the column names in this3891* <code>JoinRowSetImpl</code> object3892* @param c the <code>java.sql.Clob</code> object that will be set as3893* the new column value3894* @throws SQLException if (1) the given column name is not valid,3895* (2) the cursor is not on one of this rowset's rows or its3896* insert row, or (3) this rowset is3897* <code>ResultSet.CONCUR_READ_ONLY</code>3898*/3899public void updateClob(String columnName, Clob c) throws SQLException {3900crsInternal.updateClob(columnName, c);3901}39023903/**3904* Sets the designated column in either the current row or the insert3905* row of this <code>JoinRowSetImpl</code> object with the given3906* <code>Blob</code> value.3907* <P>3908* This method updates a column value in the current row or the insert3909* row of this rowset, but it does not update the database.3910* If the cursor is on a row in the rowset, the3911* method {@link #updateRow} must be called to update the database.3912* If the cursor is on the insert row, the method {@link #insertRow}3913* must be called, which will insert the new row into both this rowset3914* and the database. Either of these methods must be called before the3915* cursor moves to another row.3916*3917* @param columnIndex the first column is <code>1</code>, the second3918* is <code>2</code>, and so on; must be <code>1</code> or larger3919* and equal to or less than the number of columns in this rowset3920* @param b the <code>java.sql.Blob</code> object that will be set as3921* the new column value3922* @throws SQLException if (1) the given column index is out of bounds,3923* (2) the cursor is not on one of this rowset's rows or its3924* insert row, or (3) this rowset is3925* <code>ResultSet.CONCUR_READ_ONLY</code>3926*/3927public void updateBlob(int columnIndex, Blob b) throws SQLException {3928crsInternal.updateBlob(columnIndex, b);3929}39303931/**3932* Sets the designated column in either the current row or the insert3933* row of this <code>JoinRowSetImpl</code> object with the given3934* <code>Blob</code> object.3935* <P>3936* This method updates a column value in the current row or the insert3937* row of this rowset, but it does not update the database.3938* If the cursor is on a row in the rowset, the3939* method {@link #updateRow} must be called to update the database.3940* If the cursor is on the insert row, the method {@link #insertRow}3941* must be called, which will insert the new row into both this rowset3942* and the database. Either of these methods must be called before the3943* cursor moves to another row.3944*3945* @param columnName a <code>String</code> object giving the name of the column3946* to be updated; must match one of the column names in this3947* <code>JoinRowSetImpl</code> object3948* @param b the <code>java.sql.Blob</code> object that will be set as3949* the new column value3950* @throws SQLException if (1) the given column name is not valid,3951* (2) the cursor is not on one of this rowset's rows or its3952* insert row, or (3) this rowset is3953* <code>ResultSet.CONCUR_READ_ONLY</code>3954*/3955public void updateBlob(String columnName, Blob b) throws SQLException {3956crsInternal.updateBlob(columnName, b);3957}39583959/**3960* Sets the designated column in either the current row or the insert3961* row of this <code>JoinRowSetImpl</code> object with the given3962* <code>Array</code> object.3963* <P>3964* This method updates a column value in the current row or the insert3965* row of this rowset, but it does not update the database.3966* If the cursor is on a row in the rowset, the3967* method {@link #updateRow} must be called to update the database.3968* If the cursor is on the insert row, the method {@link #insertRow}3969* must be called, which will insert the new row into both this rowset3970* and the database. Either of these methods must be called before the3971* cursor moves to another row.3972*3973* @param columnIndex the first column is <code>1</code>, the second3974* is <code>2</code>, and so on; must be <code>1</code> or larger3975* and equal to or less than the number of columns in this rowset3976* @param a the <code>java.sql.Array</code> object that will be set as3977* the new column value3978* @throws SQLException if (1) the given column index is out of bounds,3979* (2) the cursor is not on one of this rowset's rows or its3980* insert row, or (3) this rowset is3981* <code>ResultSet.CONCUR_READ_ONLY</code>3982*/3983public void updateArray(int columnIndex, Array a) throws SQLException {3984crsInternal.updateArray(columnIndex, a);3985}39863987/**3988* Sets the designated column in either the current row or the insert3989* row of this <code>JoinRowSetImpl</code> object with the given3990* <code>Array</code> object.3991* <P>3992* This method updates a column value in the current row or the insert3993* row of this rowset, but it does not update the database.3994* If the cursor is on a row in the rowset, the3995* method {@link #updateRow} must be called to update the database.3996* If the cursor is on the insert row, the method {@link #insertRow}3997* must be called, which will insert the new row into both this rowset3998* and the database. Either of these methods must be called before the3999* cursor moves to another row.4000*4001* @param columnName a <code>String</code> object giving the name of the column4002* to be updated; must match one of the column names in this4003* <code>JoinRowSetImpl</code> object4004* @param a the <code>java.sql.Array</code> object that will be set as4005* the new column value4006* @throws SQLException if (1) the given column name is not valid,4007* (2) the cursor is not on one of this rowset's rows or its4008* insert row, or (3) this rowset is4009* <code>ResultSet.CONCUR_READ_ONLY</code>4010*/4011public void updateArray(String columnName, Array a) throws SQLException {4012crsInternal.updateArray(columnName, a);4013}40144015/**4016* Populates this <code>JoinRowSetImpl</code> object with data.4017* This form of the method uses the rowset's user, password, and url or4018* data source name properties to create a database4019* connection. If properties that are needed4020* have not been set, this method will throw an exception.4021* <P>4022* Another form of this method uses an existing JDBC <code>Connection</code>4023* object instead of creating a new one; therefore, it ignores the4024* properties used for establishing a new connection.4025* <P>4026* The query specified by the command property is executed to create a4027* <code>ResultSet</code> object from which to retrieve data.4028* The current contents of the rowset are discarded, and the4029* rowset's metadata is also (re)set. If there are outstanding updates,4030* they are also ignored.4031* <P>4032* The method <code>execute</code> closes any database connections that it4033* creates.4034*4035* @throws SQLException if an error occurs or the4036* necessary properties have not been set4037*/4038public void execute() throws SQLException {4039crsInternal.execute();4040}40414042/**4043* Populates this <code>JoinRowSetImpl</code> object with data,4044* using the given connection to produce the result set from4045* which data will be read. A second form of this method,4046* which takes no arguments, uses the values from this rowset's4047* user, password, and either url or data source properties to4048* create a new database connection. The form of <code>execute</code>4049* that is given a connection ignores these properties.4050*4051* @param conn A standard JDBC <code>Connection</code> object with valid4052* properties that the <code>JoinRowSet</code> implementation4053* can pass to a synchronization provider to establish a4054* connection to the datasource4055* @throws SQLException if an invalid <code>Connection</code> is supplied4056* or an error occurs in establishing the connection to the4057* data soure4058* @see java.sql.Connection4059*/4060public void execute(Connection conn) throws SQLException {4061crsInternal.execute(conn);4062}40634064/**4065* Provide interface coverage for getURL(int) in4066* ResultSet{@literal ->}RowSet4067*/4068public java.net.URL getURL(int columnIndex) throws SQLException {4069return crsInternal.getURL(columnIndex);4070}40714072/**4073* Provide interface coverage for getURL(String) in4074* ResultSet{@literal ->}RowSet4075*/4076public java.net.URL getURL(String columnName) throws SQLException {4077return crsInternal.getURL(columnName);4078}40794080/**4081* Creates a new <code>WebRowSet</code> object, populates it with the4082* data in the given <code>ResultSet</code> object, and writes it4083* to the given <code>java.io.Writer</code> object in XML format.4084*4085* @throws SQLException if an error occurs writing out the rowset4086* contents to XML4087*/4088public void writeXml(ResultSet rs, java.io.Writer writer)4089throws SQLException {4090wrs = new WebRowSetImpl();4091wrs.populate(rs);4092wrs.writeXml(writer);4093}40944095/**4096* Writes this <code>JoinRowSet</code> object to the given4097* <code>java.io.Writer</code> object in XML format. In4098* addition to the rowset's data, its properties and metadata4099* are also included.4100*4101* @throws SQLException if an error occurs writing out the rowset4102* contents to XML4103*/4104public void writeXml(java.io.Writer writer) throws SQLException {4105createWebRowSet().writeXml(writer);4106}41074108/**4109* Reads this <code>JoinRowSet</code> object in its XML format.4110*4111* @throws SQLException if a database access error occurs4112*/4113public void readXml(java.io.Reader reader) throws SQLException {4114wrs = new WebRowSetImpl();4115wrs.readXml(reader);4116crsInternal = (CachedRowSetImpl)wrs;4117}41184119// Stream based methods4120/**4121* Reads a stream based XML input to populate an <code>WebRowSet</code>4122*4123* @throws SQLException if a data source access occurs4124* @throws IOException if a IO exception occurs4125*/4126public void readXml(java.io.InputStream iStream) throws SQLException, IOException {4127wrs = new WebRowSetImpl();4128wrs.readXml(iStream);4129crsInternal = (CachedRowSetImpl)wrs;4130}41314132/**4133* Creates an output stream of the internal state and contents of a4134* <code>WebRowSet</code> for XML proceessing4135*4136* @throws SQLException if a datasource access occurs4137* @throws IOException if an IO exception occurs4138*/4139public void writeXml(java.io.OutputStream oStream) throws SQLException, IOException {4140createWebRowSet().writeXml(oStream);4141}41424143/**4144* Creates a new <code>WebRowSet</code> object, populates it with4145* the contents of the <code>ResultSet</code> and creates an output4146* streams the internal state and contents of the rowset for XML processing.4147*4148* @throws SQLException if a datasource access occurs4149* @throws IOException if an IO exception occurs4150*/4151public void writeXml(ResultSet rs, java.io.OutputStream oStream) throws SQLException, IOException {4152wrs = new WebRowSetImpl();4153wrs.populate(rs);4154wrs.writeXml(oStream);4155}41564157/**4158* %%% Javadoc comments to be added here4159*/4160private WebRowSet createWebRowSet() throws SQLException {4161if(wrs != null) {4162// check if it has already been initialized.4163return wrs;4164} else {4165wrs = new WebRowSetImpl();4166crsInternal.beforeFirst();4167wrs.populate(crsInternal);4168return wrs;4169}4170}41714172/**4173* Returns the last set SQL <code>JOIN</code> type in this JoinRowSetImpl4174* object4175*4176* @return joinType One of the standard JoinRowSet static field JOIN types4177* @throws SQLException if an error occurs determining the current join type4178*/4179public int getJoinType() throws SQLException {4180if (vecJoinType == null) {4181// Default JoinRowSet type4182this.setJoinType(JoinRowSet.INNER_JOIN);4183}4184Integer i = vecJoinType.get(vecJoinType.size()-1);4185return i.intValue();4186}41874188/**4189* The listener will be notified whenever an event occurs on this <code>JoinRowSet</code>4190* object.4191* <P>4192* A listener might, for example, be a table or graph that needs to4193* be updated in order to accurately reflect the current state of4194* the <code>RowSet</code> object.4195* <p>4196* <b>Note</b>: if the <code>RowSetListener</code> object is4197* <code>null</code>, this method silently discards the <code>null</code>4198* value and does not add a null reference to the set of listeners.4199* <p>4200* <b>Note</b>: if the listener is already set, and the new <code>RowSetListerner</code>4201* instance is added to the set of listeners already registered to receive4202* event notifications from this <code>RowSet</code>.4203*4204* @param listener an object that has implemented the4205* <code>javax.sql.RowSetListener</code> interface and wants to be notified4206* of any events that occur on this <code>JoinRowSet</code> object; May be4207* null.4208* @see #removeRowSetListener4209*/4210public void addRowSetListener(RowSetListener listener) {4211crsInternal.addRowSetListener(listener);4212}42134214/**4215* Removes the designated object from this <code>JoinRowSet</code> object's list of listeners.4216* If the given argument is not a registered listener, this method4217* does nothing.4218*4219* <b>Note</b>: if the <code>RowSetListener</code> object is4220* <code>null</code>, this method silently discards the <code>null</code>4221* value.4222*4223* @param listener a <code>RowSetListener</code> object that is on the list4224* of listeners for this <code>JoinRowSet</code> object4225* @see #addRowSetListener4226*/4227public void removeRowSetListener(RowSetListener listener) {4228crsInternal.removeRowSetListener(listener);4229}42304231/**4232* Converts this <code>JoinRowSetImpl</code> object to a collection4233* of tables. The sample implementation utilitizes the <code>TreeMap</code>4234* collection type.4235* This class guarantees that the map will be in ascending key order,4236* sorted according to the natural order for the key's class.4237*4238* @return a <code>Collection</code> object consisting of tables,4239* each of which is a copy of a row in this4240* <code>JoinRowSetImpl</code> object4241* @throws SQLException if an error occurs in generating the collection4242* @see #toCollection(int)4243* @see #toCollection(String)4244* @see java.util.TreeMap4245*/4246public Collection<?> toCollection() throws SQLException {4247return crsInternal.toCollection();4248}42494250/**4251* Returns the specified column of this <code>JoinRowSetImpl</code> object4252* as a <code>Collection</code> object. This method makes a copy of the4253* column's data and utilitizes the <code>Vector</code> to establish the4254* collection. The <code>Vector</code> class implements a growable array4255* objects allowing the individual components to be accessed using an4256* an integer index similar to that of an array.4257*4258* @return a <code>Collection</code> object that contains the value(s)4259* stored in the specified column of this4260* <code>JoinRowSetImpl</code>4261* object4262* @throws SQLException if an error occurs generated the collection; or4263* an invalid column is provided.4264* @see #toCollection()4265* @see #toCollection(String)4266* @see java.util.Vector4267*/4268public Collection<?> toCollection(int column) throws SQLException {4269return crsInternal.toCollection(column);4270}42714272/**4273* Returns the specified column of this <code>JoinRowSetImpl</code> object4274* as a <code>Collection</code> object. This method makes a copy of the4275* column's data and utilitizes the <code>Vector</code> to establish the4276* collection. The <code>Vector</code> class implements a growable array4277* objects allowing the individual components to be accessed using an4278* an integer index similar to that of an array.4279*4280* @return a <code>Collection</code> object that contains the value(s)4281* stored in the specified column of this4282* <code>JoinRowSetImpl</code>4283* object4284* @throws SQLException if an error occurs generated the collection; or4285* an invalid column is provided.4286* @see #toCollection()4287* @see #toCollection(int)4288* @see java.util.Vector4289*/4290public Collection<?> toCollection(String column) throws SQLException {4291return crsInternal.toCollection(column);4292}42934294/**4295* Creates a <code>RowSet</code> object that is a copy of4296* this <code>JoinRowSetImpl</code> object's table structure4297* and the constraints only.4298* There will be no data in the object being returned.4299* Updates made on a copy are not visible to the original rowset.4300* <P>4301* This helps in getting the underlying XML schema which can4302* be used as the basis for populating a <code>WebRowSet</code>.4303*4304* @return a new <code>CachedRowSet</code> object that is a copy4305* of this <code>JoinRowSetImpl</code> object's schema and4306* retains all the constraints on the original rowset but contains4307* no data4308* @throws SQLException if an error occurs in generating the copy4309* of the <code>CachedRowSet</code> object4310* @see #createShared4311* @see #createCopy4312* @see #createCopyNoConstraints4313* @see javax.sql.RowSetEvent4314* @see javax.sql.RowSetListener4315*/4316public CachedRowSet createCopySchema() throws SQLException {4317return crsInternal.createCopySchema();4318}43194320/**4321* {@inheritDoc}4322*/4323public void setSyncProvider(String providerStr) throws SQLException {4324crsInternal.setSyncProvider(providerStr);4325}43264327/**4328* {@inheritDoc}4329*/4330public void acceptChanges() throws SyncProviderException {4331crsInternal.acceptChanges();4332}43334334/**4335* {@inheritDoc}4336*/4337public SyncProvider getSyncProvider() throws SQLException {4338return crsInternal.getSyncProvider();4339}43404341/**4342* This method re populates the resBundle4343* during the deserialization process4344*4345*/4346private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {4347// Default state initialization happens here4348ois.defaultReadObject();4349// Initialization of transient Res Bundle happens here .4350try {4351resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();4352} catch(IOException ioe) {4353throw new RuntimeException(ioe);4354}43554356}43574358static final long serialVersionUID = -5590501621560008453L;4359}436043614362