EMMA Coverage Report (generated Wed Jun 28 22:15:27 PDT 2006)
[all classes][org.apache.derby.impl.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [EmbedResultSet.java]

nameclass, %method, %block, %line, %
EmbedResultSet.java100% (1/1)89%  (136/152)89%  (2861/3209)90%  (753.7/840)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EmbedResultSet100% (1/1)89%  (136/152)89%  (2861/3209)90%  (753.7/840)
EmbedResultSet (EmbedConnection, ResultSet, boolean, EmbedStatement, boolean)... 100% (1/1)95%  (100/105)97%  (25.2/26)
absolute (int): boolean 100% (1/1)100% (9/9)100% (2/2)
afterLast (): void 100% (1/1)100% (9/9)100% (3/3)
beforeFirst (): void 100% (1/1)100% (9/9)100% (3/3)
cancelRowUpdates (): void 100% (1/1)100% (47/47)100% (8/8)
checkExecIfClosed (String): void 100% (1/1)100% (15/15)100% (5/5)
checkIfClosed (String): void 100% (1/1)100% (9/9)100% (3/3)
checkOnRow (): DataValueDescriptor [] 100% (1/1)100% (11/11)100% (4/4)
checkRowPosition (int, String): boolean 100% (1/1)75%  (44/59)76%  (9.9/13)
checkScrollCursor (String): void 100% (1/1)100% (17/17)100% (3/3)
checksBeforeUpdateOrDelete (String, int): void 100% (1/1)100% (23/23)100% (7/7)
checksBeforeUpdateXXX (String, int): void 100% (1/1)100% (51/51)100% (9/9)
clearWarnings (): void 100% (1/1)100% (7/7)100% (3/3)
close (): void 100% (1/1)79%  (81/103)81%  (24.4/30)
closeCurrentStream (): void 100% (1/1)66%  (31/47)73%  (8.1/11)
closeOnTransactionError (Throwable): SQLException 100% (1/1)68%  (21/31)67%  (8/12)
compareTo (Object): int 100% (1/1)100% (9/9)100% (2/2)
dataTypeConversion (String, int): SQLException 100% (1/1)100% (12/12)100% (1/1)
dataTypeConversion (int, String): SQLException 100% (1/1)100% (12/12)100% (1/1)
deleteRow (): void 100% (1/1)100% (104/104)100% (22/22)
finalize (): void 100% (1/1)100% (9/9)100% (4/4)
findColumn (String): int 0%   (0/1)0%   (0/7)0%   (0/2)
findColumnName (String): int 100% (1/1)74%  (26/35)78%  (7/9)
first (): boolean 100% (1/1)100% (8/8)100% (2/2)
getAsciiStream (String): InputStream 0%   (0/1)0%   (0/6)0%   (0/1)
getAsciiStream (int): InputStream 100% (1/1)100% (29/29)100% (9/9)
getBinaryStream (String): InputStream 0%   (0/1)0%   (0/6)0%   (0/1)
getBinaryStream (int): InputStream 100% (1/1)84%  (95/113)89%  (25.7/29)
getBlob (String): Blob 0%   (0/1)0%   (0/6)0%   (0/1)
getBlob (int): Blob 100% (1/1)98%  (84/86)99%  (19.9/20)
getBoolean (String): boolean 100% (1/1)100% (6/6)100% (1/1)
getBoolean (int): boolean 100% (1/1)100% (19/19)100% (6/6)
getByte (String): byte 100% (1/1)100% (6/6)100% (1/1)
getByte (int): byte 100% (1/1)100% (19/19)100% (6/6)
getBytes (String): byte [] 100% (1/1)100% (6/6)100% (1/1)
getBytes (int): byte [] 100% (1/1)100% (47/47)100% (12/12)
getCharacterStream (String): Reader 0%   (0/1)0%   (0/6)0%   (0/1)
getCharacterStream (int): Reader 100% (1/1)84%  (130/155)87%  (33.8/39)
getClob (String): Clob 0%   (0/1)0%   (0/6)0%   (0/1)
getClob (int): Clob 100% (1/1)98%  (84/86)99%  (19.9/20)
getColumn (int): DataValueDescriptor 100% (1/1)61%  (14/23)67%  (4/6)
getColumnType (int): int 100% (1/1)69%  (18/26)75%  (3/4)
getConcurrency (): int 100% (1/1)100% (3/3)100% (1/1)
getCursorName (): String 100% (1/1)100% (7/7)100% (2/2)
getDVDforColumnToBeUpdated (int, String): DataValueDescriptor 100% (1/1)100% (37/37)100% (6/6)
getDate (String): Date 100% (1/1)100% (6/6)100% (1/1)
getDate (String, Calendar): Date 0%   (0/1)0%   (0/7)0%   (0/1)
getDate (int): Date 100% (1/1)100% (6/6)100% (1/1)
getDate (int, Calendar): Date 100% (1/1)100% (25/25)100% (8/8)
getDouble (String): double 100% (1/1)100% (6/6)100% (1/1)
getDouble (int): double 100% (1/1)100% (19/19)100% (6/6)
getFetchDirection (): int 100% (1/1)100% (10/10)100% (3/3)
getFetchSize (): int 100% (1/1)100% (10/10)100% (3/3)
getFloat (String): float 100% (1/1)100% (6/6)100% (1/1)
getFloat (int): float 100% (1/1)100% (19/19)100% (6/6)
getFullBaseTableName (ExecCursorTableReference): String 100% (1/1)100% (32/32)100% (3/3)
getInt (String): int 100% (1/1)100% (6/6)100% (1/1)
getInt (int): int 100% (1/1)100% (19/19)100% (6/6)
getLong (String): long 100% (1/1)100% (6/6)100% (1/1)
getLong (int): long 100% (1/1)100% (19/19)100% (6/6)
getMetaData (): ResultSetMetaData 100% (1/1)81%  (22/27)83%  (5/6)
getObject (String): Object 100% (1/1)100% (6/6)100% (1/1)
getObject (int): Object 100% (1/1)90%  (37/41)83%  (10/12)
getParameterValueSet (): ParameterValueSet 100% (1/1)100% (9/9)100% (3/3)
getRow (): int 100% (1/1)100% (7/7)100% (2/2)
getSQLText (): String 100% (1/1)100% (9/9)100% (3/3)
getShort (String): short 100% (1/1)100% (6/6)100% (1/1)
getShort (int): short 100% (1/1)100% (19/19)100% (6/6)
getStatement (): Statement 100% (1/1)100% (3/3)100% (1/1)
getString (String): String 100% (1/1)100% (6/6)100% (1/1)
getString (int): String 100% (1/1)100% (40/40)100% (10/10)
getTime (String): Time 100% (1/1)100% (6/6)100% (1/1)
getTime (String, Calendar): Time 0%   (0/1)0%   (0/7)0%   (0/1)
getTime (int): Time 100% (1/1)100% (6/6)100% (1/1)
getTime (int, Calendar): Time 100% (1/1)100% (25/25)100% (8/8)
getTimestamp (String): Timestamp 100% (1/1)100% (6/6)100% (1/1)
getTimestamp (String, Calendar): Timestamp 0%   (0/1)0%   (0/7)0%   (0/1)
getTimestamp (int): Timestamp 100% (1/1)100% (6/6)100% (1/1)
getTimestamp (int, Calendar): Timestamp 100% (1/1)100% (25/25)100% (8/8)
getType (): int 100% (1/1)100% (4/4)100% (1/1)
getURL (String): URL 100% (1/1)100% (2/2)100% (1/1)
getURL (int): URL 100% (1/1)100% (2/2)100% (1/1)
getWarnings (): SQLWarning 100% (1/1)100% (6/6)100% (2/2)
insertRow (): void 0%   (0/1)0%   (0/2)0%   (0/1)
isAfterLast (): boolean 100% (1/1)100% (5/5)100% (1/1)
isBeforeFirst (): boolean 100% (1/1)100% (5/5)100% (1/1)
isFirst (): boolean 100% (1/1)100% (5/5)100% (1/1)
isForUpdate (): boolean 100% (1/1)82%  (9/11)67%  (2/3)
isLast (): boolean 100% (1/1)100% (5/5)100% (1/1)
isMaxFieldSizeType (int): boolean 100% (1/1)95%  (21/22)95%  (1/1)
last (): boolean 100% (1/1)100% (8/8)100% (2/2)
movePosition (int, String): boolean 100% (1/1)100% (6/6)100% (1/1)
movePosition (int, int, String): boolean 100% (1/1)92%  (155/168)95%  (40/42)
moveToCurrentRow (): void 0%   (0/1)0%   (0/2)0%   (0/1)
moveToInsertRow (): void 0%   (0/1)0%   (0/2)0%   (0/1)
newEmbedResultSetMetaData (ResultDescription): EmbedResultSetMetaData 100% (1/1)100% (6/6)100% (1/1)
next (): boolean 100% (1/1)100% (41/41)100% (9/9)
noStateChangeException (Throwable): SQLException 100% (1/1)100% (5/5)100% (1/1)
previous (): boolean 100% (1/1)100% (8/8)100% (2/2)
refreshRow (): void 0%   (0/1)0%   (0/2)0%   (0/1)
relative (int): boolean 100% (1/1)100% (9/9)100% (2/2)
rowDeleted (): boolean 100% (1/1)100% (2/2)100% (1/1)
rowInserted (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
rowUpdated (): boolean 100% (1/1)100% (2/2)100% (1/1)
setApplicationStatement (Statement): void 100% (1/1)100% (4/4)100% (2/2)
setDynamicResultSet (EmbedStatement): void 100% (1/1)100% (8/8)100% (3/3)
setFetchDirection (int): void 100% (1/1)100% (7/7)100% (3/3)
setFetchSize (int): void 100% (1/1)100% (24/24)100% (5/5)
updateAsciiStream (String, InputStream, int): void 100% (1/1)100% (8/8)100% (2/2)
updateAsciiStream (int, InputStream, int): void 100% (1/1)82%  (33/40)85%  (11/13)
updateBinaryStream (String, InputStream, int): void 100% (1/1)100% (8/8)100% (2/2)
updateBinaryStream (int, InputStream, int): void 100% (1/1)77%  (27/35)75%  (9/12)
updateBinaryStreamInternal (int, InputStream, int, String): void 100% (1/1)76%  (13/17)60%  (3/5)
updateBlob (String, Blob): void 100% (1/1)100% (7/7)100% (2/2)
updateBlob (int, Blob): void 100% (1/1)87%  (26/30)88%  (7/8)
updateBoolean (String, boolean): void 100% (1/1)100% (7/7)100% (2/2)
updateBoolean (int, boolean): void 100% (1/1)100% (12/12)100% (5/5)
updateByte (String, byte): void 100% (1/1)100% (7/7)100% (2/2)
updateByte (int, byte): void 100% (1/1)100% (12/12)100% (5/5)
updateBytes (String, byte []): void 100% (1/1)100% (7/7)100% (2/2)
updateBytes (int, byte []): void 100% (1/1)100% (12/12)100% (5/5)
updateCharacterStream (String, Reader, int): void 100% (1/1)100% (8/8)100% (2/2)
updateCharacterStream (int, Reader, int): void 100% (1/1)77%  (27/35)75%  (9/12)
updateCharacterStreamInternal (int, Reader, int, String): void 100% (1/1)86%  (25/29)78%  (7/9)
updateClob (String, Clob): void 100% (1/1)100% (7/7)100% (2/2)
updateClob (int, Clob): void 100% (1/1)87%  (26/30)88%  (7/8)
updateDate (String, Date): void 100% (1/1)100% (7/7)100% (2/2)
updateDate (int, Date): void 100% (1/1)100% (12/12)100% (5/5)
updateDouble (String, double): void 100% (1/1)100% (7/7)100% (2/2)
updateDouble (int, double): void 100% (1/1)100% (12/12)100% (5/5)
updateFloat (String, float): void 100% (1/1)100% (7/7)100% (2/2)
updateFloat (int, float): void 100% (1/1)100% (12/12)100% (5/5)
updateInt (String, int): void 100% (1/1)100% (7/7)100% (2/2)
updateInt (int, int): void 100% (1/1)100% (12/12)100% (5/5)
updateLong (String, long): void 100% (1/1)100% (7/7)100% (2/2)
updateLong (int, long): void 100% (1/1)100% (12/12)100% (5/5)
updateNull (String): void 100% (1/1)100% (6/6)100% (2/2)
updateNull (int): void 100% (1/1)64%  (7/11)60%  (3/5)
updateObject (String, Object): void 100% (1/1)100% (7/7)100% (2/2)
updateObject (String, Object, int): void 0%   (0/1)0%   (0/8)0%   (0/2)
updateObject (int, Object): void 100% (1/1)89%  (140/158)90%  (45/50)
updateObject (int, Object, int): void 0%   (0/1)0%   (0/45)0%   (0/12)
updateRow (): void 100% (1/1)100% (208/208)100% (42/42)
updateShort (String, short): void 100% (1/1)100% (7/7)100% (2/2)
updateShort (int, short): void 100% (1/1)100% (12/12)100% (5/5)
updateString (String, String): void 100% (1/1)100% (7/7)100% (2/2)
updateString (int, String): void 100% (1/1)100% (12/12)100% (5/5)
updateTime (String, Time): void 100% (1/1)100% (7/7)100% (2/2)
updateTime (int, Time): void 100% (1/1)100% (12/12)100% (5/5)
updateTimestamp (String, Timestamp): void 100% (1/1)100% (7/7)100% (2/2)
updateTimestamp (int, Timestamp): void 100% (1/1)100% (12/12)100% (5/5)
wasNull (): boolean 100% (1/1)100% (6/6)100% (2/2)

1/*
2 
3   Derby - Class org.apache.derby.impl.jdbc.EmbedResultSet
4 
5   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
6 
7   Licensed under the Apache License, Version 2.0 (the "License");
8   you may not use this file except in compliance with the License.
9   You may obtain a copy of the License at
10 
11      http://www.apache.org/licenses/LICENSE-2.0
12 
13   Unless required by applicable law or agreed to in writing, software
14   distributed under the License is distributed on an "AS IS" BASIS,
15   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   See the License for the specific language governing permissions and
17   limitations under the License.
18 
19 */
20 
21package org.apache.derby.impl.jdbc;
22 
23import org.apache.derby.iapi.services.sanity.SanityManager;
24 
25import org.apache.derby.iapi.error.StandardException;
26 
27import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
28import org.apache.derby.iapi.sql.conn.StatementContext;
29 
30import org.apache.derby.iapi.sql.ResultSet;
31import org.apache.derby.iapi.sql.ParameterValueSet;
32import org.apache.derby.iapi.sql.execute.ExecutionFactory;
33import org.apache.derby.iapi.sql.execute.ExecCursorTableReference;
34import org.apache.derby.iapi.sql.execute.ExecRow;
35import org.apache.derby.iapi.sql.execute.NoPutResultSet;
36import org.apache.derby.impl.sql.execute.ScrollInsensitiveResultSet;
37 
38import org.apache.derby.iapi.sql.Activation;
39import org.apache.derby.iapi.sql.execute.CursorActivation;
40 
41import org.apache.derby.iapi.types.DataValueDescriptor;
42import org.apache.derby.iapi.types.RawToBinaryFormatStream;
43import org.apache.derby.iapi.types.ReaderToUTF8Stream;
44import org.apache.derby.iapi.types.UserDataValue;
45import org.apache.derby.iapi.types.VariableSizeDataValue;
46import org.apache.derby.iapi.sql.ResultDescription;
47import org.apache.derby.iapi.services.io.StreamStorable;
48 
49import org.apache.derby.iapi.services.io.LimitInputStream;
50import org.apache.derby.iapi.services.io.NewByteArrayInputStream;
51import org.apache.derby.iapi.services.io.LimitReader;
52import org.apache.derby.iapi.error.ExceptionSeverity;
53import org.apache.derby.iapi.reference.JDBC20Translation;
54import org.apache.derby.iapi.reference.JDBC30Translation;
55import org.apache.derby.iapi.reference.SQLState;
56import org.apache.derby.iapi.util.StringUtil;
57 
58/* can't import these due to name overlap:
59import java.sql.ResultSet;
60*/
61import java.sql.Blob;
62import java.sql.Clob;
63import java.sql.Statement;
64import java.sql.SQLException;
65import java.sql.SQLWarning;
66import java.sql.ResultSetMetaData;
67import java.sql.Date;
68import java.sql.Time;
69import java.sql.Timestamp;
70import java.sql.Types;
71 
72import java.io.InputStream;
73import java.io.IOException;
74import java.net.URL;
75 
76import java.util.Arrays;
77import java.util.Calendar;
78 
79/**
80 * A EmbedResultSet for results from the EmbedStatement family. 
81    <P><B>Supports</B>
82   <UL>
83   <LI> JSR 169
84   </UL>
85 * @author ames
86 */
87 
88public abstract class EmbedResultSet extends ConnectionChild 
89    implements java.sql.ResultSet, Comparable {
90 
91        // cursor movement
92        protected static final int FIRST = 1;
93        protected static final int NEXT = 2;
94        protected static final int LAST = 3;
95        protected static final int PREVIOUS = 4;
96        protected static final int BEFOREFIRST = 5;
97        protected static final int AFTERLAST = 6;
98        protected static final int ABSOLUTE = 7;
99        protected static final int RELATIVE = 8;
100 
101        /** 
102         * The currentRow contains the data of the current row of the resultset.
103         * If the containing row array is null, the cursor is not postioned on a 
104         * row 
105         */
106        private final ExecRow currentRow;        
107        protected boolean wasNull;
108    
109    /**
110     * Set if this ResultSet is definitely closed.
111     * If the connection has been closed, or the database
112     *  or system shutdown but the ResultSet has not been
113     *  closed explictly then this may be false. Once
114     *  this object detects the connection is closed
115     *  isClosed will be set to true.
116     */
117    boolean isClosed;
118    
119        private boolean isOnInsertRow;
120        private Object        currentStream;
121 
122        // immutable state
123        private ResultSet theResults;
124        private boolean forMetaData;
125        private ResultSetMetaData rMetaData;
126        private SQLWarning topWarning;
127 
128        // This activation is set by EmbedStatement
129        // for a single execution Activation. Ie.
130        // a ResultSet from a Statement.executeQuery().
131        // In this case the finalization of the ResultSet
132        // will mark the Activation as unused.
133        // c.f. EmbedPreparedStatement.finalize().
134        Activation finalizeActivation;
135 
136        // Order of creation 
137        final int order;
138 
139  
140        private final ResultDescription resultDescription;
141 
142    // max rows limit for this result set
143    private int maxRows;
144    // The Maximum field size limt set for this result set
145    private final int maxFieldSize;
146 
147    /*
148     * Incase of forward only cursors we limit the number of rows
149     * returned if the maxRows is set. The following varible is used
150     * to keep the count of number of rows returned to the user.
151     */
152    private int NumberofFetchedRows;
153 
154 
155        /**
156     * The statement object that originally created us.
157                we hang on to the statement to prevent GC from
158                closing it under us
159         */
160        private final EmbedStatement stmt;
161    
162    /**
163     * The statement that currently owns this ResultSet.
164     * Statements created in procedures are passed off
165     * to the Statement that called the procedure.
166     * This is to avoid the ResultSet being closed
167     * due to the Statement within the procedure
168     * or the nested Connection being closed.
169     */
170        private EmbedStatement owningStmt;
171    
172    /**
173     * Statement object the application used to
174     * create this ResultSet.
175     */
176    private Statement applicationStmt;
177    
178    private long timeoutMillis;
179 
180        private final boolean isAtomic;
181 
182        private final int concurrencyOfThisResultSet;
183 
184        /* updateRow is used to keep the values which are updated with updateXXX() 
185         * calls. It is used by both insertRow() and updateRow(). 
186         * It is initialized to null if the resultset is not updatable. 
187         */
188        private final ExecRow updateRow;
189        
190        /* These are the columns which have been updated so far. 
191         */
192        private boolean[] columnGotUpdated; 
193        private boolean currentRowHasBeenUpdated; //Gets set to true after first updateXXX on a row. Gets reset to false when the cursor moves off the row
194 
195    private int fetchDirection;
196    private int fetchSize;
197    
198    /**
199     * Indicates which columns have already been fetched
200     * as a stream for a row. Created on-demand by a getXXXStream call.
201     */
202    private boolean[] streamUsedFlags;
203    
204        /**
205         * This class provides the glue between the Cloudscape
206         * resultset and the JDBC resultset, mapping calls-to-calls.
207         */
208        public EmbedResultSet(EmbedConnection conn, ResultSet resultsToWrap,
209                boolean forMetaData, EmbedStatement stmt, boolean isAtomic)
210        throws SQLException {
211 
212                super(conn);
213 
214                if (SanityManager.DEBUG)
215                SanityManager.ASSERT(resultsToWrap!=null);
216                theResults = resultsToWrap;
217                this.forMetaData = forMetaData;
218        this.applicationStmt = this.stmt = owningStmt = stmt;
219 
220        this.timeoutMillis = stmt == null
221            ? 0L
222            : (long)stmt.getQueryTimeout() * 1000L;
223 
224                this.isAtomic = isAtomic;
225                
226 
227                //If the Statement object has CONCUR_READ_ONLY set on it then the concurrency on the ResultSet object will be CONCUR_READ_ONLY also.
228                //But, if the Statement object has CONCUR_UPDATABLE set on it, then the concurrency on the ResultSet object can be
229                //CONCUR_READ_ONLY or CONCUR_UPDATABLE depending on whether the underlying language resultset is updateable or not.
230                //If the underlying language resultset is not updateable, then the concurrency of the ResultSet object will be CONCUR_READ_ONLY
231                //and a warning will be issued on the ResultSet object.
232                if (stmt == null) concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
233                else if (stmt.getResultSetConcurrency() == JDBC20Translation.CONCUR_READ_ONLY)
234                        concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
235                else {
236                        if (!isForUpdate()) { //language resultset not updatable
237                                concurrencyOfThisResultSet = JDBC20Translation.CONCUR_READ_ONLY;
238                                SQLWarning w = StandardException.newWarning(SQLState.QUERY_NOT_QUALIFIED_FOR_UPDATABLE_RESULTSET);
239                                if (topWarning == null)
240                                        topWarning = w;
241                                else
242                                        topWarning.setNextWarning(w);
243                        } else
244                                        concurrencyOfThisResultSet = JDBC20Translation.CONCUR_UPDATABLE;
245                }
246 
247                // Fill in the column types
248                resultDescription = theResults.getResultDescription();
249                final ExecutionFactory factory = conn.getLanguageConnection().
250                        getLanguageConnectionFactory().getExecutionFactory();
251                final int columnCount = getMetaData().getColumnCount();
252                this.currentRow = factory.getValueRow(columnCount);
253                currentRow.setRowArray(null);
254 
255                // Only incur the cost of allocating and maintaining
256                // updated column information if the columns can be updated.
257                if (concurrencyOfThisResultSet == JDBC20Translation.CONCUR_UPDATABLE)
258                {
259                        //initialize arrays related to updateRow implementation
260                        columnGotUpdated = new boolean[columnCount];
261                        updateRow = factory.getValueRow(columnCount);
262                        for (int i = 1; i <= columnCount; i++) {
263                                updateRow.setColumn(i, resultDescription.getColumnDescriptor(i).
264                                                                        getType().getNull());
265                        }
266                        initializeUpdateRowModifiers();
267                } else {
268                        updateRow = null;
269                }
270 
271        // assign the max rows and maxfiled size limit for this result set
272        if (stmt != null)
273        {
274           // At connectivity level we handle only for forward only cursor
275           if (stmt.resultSetType == JDBC20Translation.TYPE_FORWARD_ONLY)
276               maxRows = stmt.maxRows;
277 
278           maxFieldSize = stmt.MaxFieldSize;
279        }
280                else
281                        maxFieldSize = 0;
282 
283                order = conn.getResultSetOrderId();
284        }
285 
286        /**
287                JDBC states that a ResultSet is closed when garbage collected.
288                We simply mark the activation as unused. Some later use
289                of the connection will clean everything up.
290 
291                @exception Throwable Allows any exception to be thrown during finalize
292        */
293        protected void finalize() throws Throwable {
294                super.finalize();
295 
296                if (finalizeActivation != null) {
297                        finalizeActivation.markUnused();
298                }                
299        }
300 
301        private void checkNotOnInsertRow() throws SQLException {
302                if (isOnInsertRow) {
303                        throw newSQLException(SQLState.NO_CURRENT_ROW);
304                }
305        }
306 
307        // checkOnRow protects us from making requests of
308        // resultSet that would fail with NullPointerExceptions
309        // or milder problems due to not having a row.
310        protected final void checkOnRow() throws SQLException 
311        {
312                if (currentRow.getRowArray() == null) {
313                        throw newSQLException(SQLState.NO_CURRENT_ROW);
314                } 
315        }
316 
317        /**
318         * Initializes the currentRowHasBeenUpdated and columnGotUpdated fields
319         */
320        private void initializeUpdateRowModifiers() {
321                currentRowHasBeenUpdated = false;
322                Arrays.fill(columnGotUpdated, false);
323        }
324 
325        /**
326                Check the column is in range *and* return the JDBC type of the column.
327 
328                @exception SQLException ResultSet is not on a row or columnIndex is out of range.
329        */
330        final int getColumnType(int columnIndex) throws SQLException {
331                if (!isOnInsertRow) checkOnRow(); // first make sure there's a row
332                
333                if (columnIndex < 1 ||
334                    columnIndex > resultDescription.getColumnCount())
335                        throw newSQLException(SQLState.COLUMN_NOT_FOUND, 
336                         new Integer(columnIndex));
337 
338                return resultDescription.getColumnDescriptor(columnIndex).getType().getJDBCTypeId();
339        }
340 
341        /*
342         * java.sql.ResultSet interface
343         */
344    /**
345     * A ResultSet is initially positioned before its first row; the
346     * first call to next makes the first row the current row; the
347     * second call makes the second row the current row, etc.
348     *
349     * <P>If an input stream from the previous row is open, it is
350     * implicitly closed. The ResultSet's warning chain is cleared
351     * when a new row is read.
352     *
353     * @return true if the new current row is valid; false if there
354     * are no more rows
355         * @exception SQLException thrown on failure.
356     */
357    public boolean next() throws SQLException 
358        {
359        // we seem to have some trigger paths which don't have
360        // statement initialized, may not need this check in those cases
361        if (maxRows !=0 )
362        {
363            NumberofFetchedRows++;    
364            // check whether we hit the maxRows limit 
365            if (NumberofFetchedRows > maxRows) 
366            {
367                //we return false for the next call when maxRows is hit
368                closeCurrentStream();
369                return false;
370            }
371        }
372            return movePosition(NEXT, 0, "next");
373        }
374 
375        protected boolean movePosition(int position, String positionText)
376                throws SQLException
377        {
378                return movePosition(position, 0, positionText);
379        }
380 
381        protected boolean movePosition(int position, int row, String positionText)
382                throws SQLException
383        {
384                closeCurrentStream();        // closing currentStream does not depend on the
385                                                                // underlying connection.  Do this outside of
386                                                                // the connection synchronization.
387 
388                checkExecIfClosed(positionText);        // checking result set closure does not depend
389                                                                // on the underlying connection.  Do this
390                                                                // outside of the connection synchronization.
391 
392                if (isOnInsertRow) {
393                        moveToCurrentRow();
394                }
395 
396 
397                synchronized (getConnectionSynchronization()) {
398 
399                                        setupContextStack();
400                    try {
401                                LanguageConnectionContext lcc = getEmbedConnection().getLanguageConnection();
402                                final ExecRow newRow;
403                    try {
404 
405                                /* Push and pop a StatementContext around a next call
406                                 * so that the ResultSet will get correctly closed down
407                                 * on an error.
408                                 * (Cache the LanguageConnectionContext)
409                                 */
410                StatementContext statementContext =
411                    lcc.pushStatementContext(isAtomic, 
412                                             concurrencyOfThisResultSet==JDBC20Translation.CONCUR_READ_ONLY, 
413                                             getSQLText(),
414                                             getParameterValueSet(),
415                                             false, timeoutMillis);
416 
417                                switch (position)
418                                {
419                                        case BEFOREFIRST:
420                                                newRow = theResults.setBeforeFirstRow();
421                                                break;
422 
423                                        case FIRST:
424                                                newRow = theResults.getFirstRow();
425                                                break;
426 
427                                        case NEXT:
428                                                newRow = theResults.getNextRow();
429                                                break;
430 
431                                        case LAST:
432                                                newRow = theResults.getLastRow();
433                                                break;
434 
435                                        case AFTERLAST:
436                                                newRow = theResults.setAfterLastRow();
437                                                break;
438 
439                                        case PREVIOUS:
440                                                newRow = theResults.getPreviousRow();
441                                                break;
442 
443                                        case ABSOLUTE:
444                                                newRow = theResults.getAbsoluteRow(row);
445                                                break;
446 
447                                        case RELATIVE:
448                                                newRow = theResults.getRelativeRow(row);
449                                                break;
450 
451                                        default:
452                                                newRow = null;
453                                                if (SanityManager.DEBUG)
454                                                {
455                                                        SanityManager.THROWASSERT(
456                                                                "Unexpected value for position - " + position);
457                                                }
458                                }
459 
460                                lcc.popStatementContext(statementContext, null);
461                                
462                    } catch (Throwable t) {
463                                /*
464                                 * Need to close the result set here because the error might
465                                 * cause us to lose the current connection if this is an XA
466                                 * connection and we won't be able to do the close later
467                                 */
468                                throw closeOnTransactionError(t);
469                        }
470         
471                        SQLWarning w = theResults.getWarnings();
472                        if (w != null) {
473                                if (topWarning == null)
474                                        topWarning = w;
475                                else
476                                        topWarning.setNextWarning(w);
477                        }
478                        
479                        boolean onRow = (newRow!=null);
480                        if (onRow) {
481                                currentRow.setRowArray(newRow.getRowArray());
482                        } else {
483                                currentRow.setRowArray(null);
484                        }
485                        
486 
487                        //if (onRow && !(currentRow instanceof org.apache.derby.impl.sql.execute.ValueRow))
488                        //        System.out.println(currentRow.getClass());
489 
490                    // The ResultSet may implicitly close when when the ResultSet type 
491                    // is TYPE_FORWARD_ONLY and the next method of ResultSet returns 
492                    // false. This will cause a commit if autocommit = true.
493                    if (!onRow && (position == NEXT)) {
494 
495                     // In case of resultset for MetaData, we will only commit
496                     // if we are the only statement currently opened for this
497                     // connection; otherwise we don't want to affect other
498                     // resultSet's by committing the MetaData one.
499                     // There is no internal xact (xact isolation) for MetaData type
500                     // of resultSet; therefore committing (to release locks) would end
501                     // up committing all the other resultSet for this connection.
502                     //
503                     // We do synchronize on the connection, therefore Activation count
504                     // should be valid and protected.
505                     //
506                        //LanguageConnectionContext lcc = getEmbedConnection().getLanguageConnection();
507                     if (forMetaData && (lcc.getActivationCount() > 1)) {
508                             // we do not want to commit here as there seems to be other
509                             // statements/resultSets currently opened for this connection.
510                     } else if (owningStmt != null && 
511                                    owningStmt.getResultSetType() == TYPE_FORWARD_ONLY) {
512                                 // allow the satement to commit if required.
513                             owningStmt.resultSetClosing(this);
514                     }
515                    }
516 
517                        // Clear the indication of which columns were fetched as streams.
518                        if (streamUsedFlags != null)
519                            Arrays.fill(streamUsedFlags, false);
520                        if (columnGotUpdated != null && currentRowHasBeenUpdated) {
521                                initializeUpdateRowModifiers();
522                        }
523                        
524                        return onRow;
525                        } finally {
526                            restoreContextStack();
527                        }
528                }
529 
530        }
531 
532 
533 
534 
535    /**
536     * In some cases, it is desirable to immediately release a
537     * ResultSet's database and JDBC resources instead of waiting for
538     * this to happen when it is automatically closed; the close
539     * method provides this immediate release.
540     *
541     * <P><B>Note:</B> A ResultSet is automatically closed by the
542     * Statement that generated it when that Statement is closed,
543     * re-executed, or is used to retrieve the next result from a
544     * sequence of multiple results. A ResultSet is also automatically
545     * closed when it is garbage collected.
546         * @exception SQLException thrown on failure.
547     */
548    public void close() throws SQLException        {
549 
550                /* if this result is already closed, don't try to close again
551                 * we may have closed it earlier because of an error and trying
552                 * to close again will cause a different problem if the connection
553                 * has been closed as in XA error handling
554                 */
555                if (isClosed)
556                        return;
557 
558                closeCurrentStream();        // closing currentStream does not depend on the
559                                                                // underlying connection.  Do this outside of
560                                                                // the connection synchronization.
561                // Would like to throw an exception if already closed, but
562                // some code assumes you can close a ResultSet more than once.
563                // checkIfClosed("close");
564 
565                // synchronize out here so the close and the autocommit are
566                // both in the same sync block.
567                synchronized (getConnectionSynchronization()) {
568 
569                        try {
570                                setupContextStack(); // make sure there's context
571                        } catch (SQLException se) {
572                                // we may get an exception here if this is part of an XA transaction
573                                // and the transaction has been committed
574                                // just give up and return
575                                return;
576                        }
577 
578                        try        {
579                                try        {
580                                    theResults.finish(); // release the result set, don't just close it
581                                } catch (Throwable t) {
582                                        throw handleException(t);
583                                }
584 
585                            // In case of resultset for MetaData, we will only commit
586                        // if we are the only statement currently opened for this
587                        // connection; otherwise we don't want to affect other
588                        // resultSet's by committing the MetaData one.
589                        // There is no internal xact (xact isolation) for MetaData type
590                        // of resultSet; therefore committing (to release locks) would end
591                        // up committing all the other resultSet for this connection.
592                        //
593                        // We do synchronize on the connection, therefore Activation count
594                        // should be valid and protected.
595                        //
596                        if (forMetaData) {
597 
598                                        LanguageConnectionContext lcc = getEmbedConnection().getLanguageConnection();
599                                if (lcc.getActivationCount() > 1) {
600                                       // we do not want to commit here as there seems to be other
601                                          // statements/resultSets currently opened for this connection.
602                                        } else if (owningStmt != null)
603                                                // allow the satement to commit if required.
604                                             owningStmt.resultSetClosing(this);
605                
606                                } else if (owningStmt != null) {
607                                                // allow the satement to commit if required.
608                                             owningStmt.resultSetClosing(this);
609                             }
610 
611                        } finally {
612                                isClosed = true;
613                            restoreContextStack();
614                        }
615 
616                        // the idea is to release resources, so:
617                        currentRow.setRowArray(null);
618                        rMetaData = null; // let it go, we can make a new one
619 
620                        // we hang on to theResults and messenger
621                        // in case more calls come in on this resultSet
622                }
623 
624        }
625 
626    /**
627     * A column may have the value of SQL NULL; wasNull reports whether
628     * the last column read had this special value.
629     * Note that you must first call getXXX on a column to try to read
630     * its value and then call wasNull() to find if the value was
631     * the SQL NULL.
632     *
633     * <p> we take the least exception approach and simply return false
634     * if no column has been read yet.
635     *
636     * @return true if last column read was SQL NULL
637         *
638         * @exception SQLException                Thrown if this ResultSet is closed
639     */
640    public final boolean wasNull() throws SQLException {
641                checkIfClosed("wasNull");
642                return wasNull;
643        }
644 
645    //======================================================================
646    // Methods for accessing results by column index
647    //======================================================================
648 
649    /**
650     * Get the value of a column in the current row as a Java String.
651     *
652     * @param columnIndex the first column is 1, the second is 2, ...
653     * @return the column value; if the value is SQL NULL, the result is null
654         * @exception SQLException thrown on failure.
655     */
656    public final String getString(int columnIndex) throws SQLException {
657        checkIfClosed("getString");
658 
659                        try {
660 
661                                DataValueDescriptor dvd = getColumn(columnIndex);
662 
663                                if (wasNull = dvd.isNull())
664                                        return null;
665 
666                                String value = dvd.getString();
667 
668                                // check for the max field size limit 
669                if (maxFieldSize > 0 && isMaxFieldSizeType(getColumnType(columnIndex)))
670                {
671                    if (value.length() > maxFieldSize )
672                    {
673                        value = value.substring(0, maxFieldSize);
674                    }
675                }
676     
677                                return value;
678 
679                        } catch (Throwable t) {
680                                throw noStateChangeException(t);
681                        }
682        }
683 
684    /**
685     * Get the value of a column in the current row as a Java boolean.
686     *
687     * @param columnIndex the first column is 1, the second is 2, ...
688     * @return the column value; if the value is SQL NULL, the result is false
689         * @exception SQLException thrown on failure.
690     */
691    public final boolean getBoolean(int columnIndex) throws SQLException {
692                checkIfClosed("getBoolean");
693 
694                try {
695 
696                        DataValueDescriptor dvd = getColumn(columnIndex);
697 
698                        if (wasNull = dvd.isNull())
699                                return false;
700 
701                        return dvd.getBoolean();
702 
703                } catch (StandardException t) {
704                        throw noStateChangeException(t);
705                }
706        }
707 
708    /**
709     * Get the value of a column in the current row as a Java byte.
710     *
711     * @param columnIndex the first column is 1, the second is 2, ...
712     * @return the column value; if the value is SQL NULL, the result is 0
713         * @exception SQLException thrown on failure.
714     */
715    public final byte getByte(int columnIndex) throws SQLException {
716                checkIfClosed("getByte");
717                try {
718 
719                        DataValueDescriptor dvd = getColumn(columnIndex);
720 
721                        if (wasNull = dvd.isNull())
722                                return 0;
723 
724                        return dvd.getByte();
725 
726                } catch (StandardException t) {
727                        throw noStateChangeException(t);
728                }
729        }
730 
731    /**
732     * Get the value of a column in the current row as a Java short.
733     *
734     * @param columnIndex the first column is 1, the second is 2, ...
735     * @return the column value; if the value is SQL NULL, the result is 0
736         * @exception SQLException thrown on failure.
737     */
738    public final short getShort(int columnIndex) throws SQLException {
739                checkIfClosed("getShort");
740 
741                try {
742 
743                        DataValueDescriptor dvd = getColumn(columnIndex);
744 
745                        if (wasNull = dvd.isNull())
746                                return 0;
747 
748                        return dvd.getShort();
749 
750                } catch (StandardException t) {
751                        throw noStateChangeException(t);
752                }
753        }
754 
755    /**
756     * Get the value of a column in the current row as a Java int.
757     *
758     * @param columnIndex the first column is 1, the second is 2, ...
759     * @return the column value; if the value is SQL NULL, the result is 0
760         * @exception SQLException thrown on failure.
761     */
762    public final int getInt(int columnIndex) throws SQLException        {
763                checkIfClosed("getInt");
764                try {
765 
766                        DataValueDescriptor dvd = getColumn(columnIndex);
767 
768                        if (wasNull = dvd.isNull())
769                                return 0;
770 
771                        return dvd.getInt();
772 
773                } catch (StandardException t) {
774                        throw noStateChangeException(t);
775                }
776        }
777 
778    /**
779     * Get the value of a column in the current row as a Java long.
780     *
781     * @param columnIndex the first column is 1, the second is 2, ...
782     * @return the column value; if the value is SQL NULL, the result is 0
783         * @exception SQLException thrown on failure.
784     */
785    public final long getLong(int columnIndex) throws SQLException {
786                checkIfClosed("getLong");
787                try {
788 
789                        DataValueDescriptor dvd = getColumn(columnIndex);
790 
791                        if (wasNull = dvd.isNull())
792                                return 0;
793 
794                        return dvd.getLong();
795 
796                } catch (StandardException t)        {
797                        throw noStateChangeException(t);
798                }
799        }
800 
801    /**
802     * Get the value of a column in the current row as a Java float.
803     *
804     * @param columnIndex the first column is 1, the second is 2, ...
805     * @return the column value; if the value is SQL NULL, the result is 0
806         * @exception SQLException thrown on failure.
807     */
808    public final float getFloat(int columnIndex) throws SQLException {
809                checkIfClosed("getFloat");
810                try {
811 
812                        DataValueDescriptor dvd = getColumn(columnIndex);
813 
814                        if (wasNull = dvd.isNull())
815                                return 0.0F;
816 
817                        return dvd.getFloat();
818 
819                } catch (StandardException t)        {
820                        throw noStateChangeException(t);
821                }
822        }
823 
824    /**
825     * Get the value of a column in the current row as a Java double.
826     *
827     * @param columnIndex the first column is 1, the second is 2, ...
828     * @return the column value; if the value is SQL NULL, the result is 0
829         * @exception SQLException thrown on failure.
830     */
831    public final double getDouble(int columnIndex) throws SQLException {
832                checkIfClosed("getDouble");
833                try {
834 
835                        DataValueDescriptor dvd = getColumn(columnIndex);
836 
837                        if (wasNull = dvd.isNull())
838                                return 0.0;
839 
840                        return dvd.getDouble();
841 
842                } catch (StandardException t)        {
843                        throw noStateChangeException(t);
844                }
845        }
846 
847    /**
848     * Get the value of a column in the current row as a Java byte array.
849     * The bytes represent the raw values returned by the driver.
850     *
851     * @param columnIndex the first column is 1, the second is 2, ...
852     * @return the column value; if the value is SQL NULL, the result is null
853         * @exception SQLException thrown on failure.
854     */
855    public final byte[] getBytes(int columnIndex) throws SQLException        {
856                checkIfClosed("getBytes");
857                try {
858 
859                        DataValueDescriptor dvd = getColumn(columnIndex);
860 
861                        if (wasNull = dvd.isNull())
862                                return null;
863 
864                        byte[] value = dvd.getBytes();
865 
866            // check for the max field size limit 
867            if (maxFieldSize > 0 && isMaxFieldSizeType(getColumnType(columnIndex)))
868            {
869                 if (value.length > maxFieldSize)
870                 {
871                     byte [] limited_value = new byte[maxFieldSize];
872                     System.arraycopy(value, 0, limited_value, 
873                                                   0 , maxFieldSize);
874                     value = limited_value;
875                 }
876             }
877                        
878                        return value;
879 
880                } catch (StandardException t) {
881                        throw noStateChangeException(t);
882                }
883        }
884 
885    /**
886     * Get the value of a column in the current row as a java.sql.Date object.
887     *
888     * @param columnIndex the first column is 1, the second is 2, ...
889     * @return the column value; if the value is SQL NULL, the result is null
890         * @exception SQLException thrown on failure.
891     */
892    public final Date getDate(int columnIndex) throws SQLException {
893        return getDate( columnIndex, (Calendar) null);
894        }
895 
896    /**
897     * Get the value of a column in the current row as a java.sql.Time object.
898     *
899     * @param columnIndex the first column is 1, the second is 2, ...
900     * @return the column value; if the value is SQL NULL, the result is null
901         * @exception SQLException thrown on failure.
902     */
903    public final Time getTime(int columnIndex) throws SQLException {
904        return getTime( columnIndex, (Calendar) null);
905        }
906 
907    /**
908     * Get the value of a column in the current row as a java.sql.Timestamp object.
909     *
910     * @param columnIndex the first column is 1, the second is 2, ...
911     * @return the column value; if the value is SQL NULL, the result is null
912         * @exception SQLException thrown on failure.
913     */
914    public final Timestamp getTimestamp(int columnIndex) throws SQLException {
915        return getTimestamp( columnIndex, (Calendar) null);
916        }
917 
918    /**
919     * JDBC 2.0
920     *
921     * Get the value of a column in the current row as a java.sql.Date 
922     * object.  Use the calendar to construct an appropriate millisecond
923     * value for the Date, if the underlying database doesn't store
924     * timezone information.
925     *
926     * @param columnIndex the first column is 1, the second is 2, ...
927     * @param cal the calendar to use in constructing the date
928     * @return the column value; if the value is SQL NULL, the result is null
929     * @exception SQLException if a database-access error occurs.
930     */
931    public java.sql.Date getDate(int columnIndex, Calendar cal)
932        throws SQLException 
933    {
934                checkIfClosed("getDate");
935                try {
936 
937                        DataValueDescriptor dvd = getColumn(columnIndex);
938 
939                        if (wasNull = dvd.isNull())
940                                return null;
941 
942            if( cal == null)
943                cal = getCal();
944            
945                        return dvd.getDate( cal);
946 
947                } catch (StandardException t) {
948                        throw noStateChangeException(t);
949                }
950    }
951 
952    /**
953     * JDBC 2.0
954     *
955     * Get the value of a column in the current row as a java.sql.Date 
956     * object. Use the calendar to construct an appropriate millisecond
957     * value for the Date, if the underlying database doesn't store
958     * timezone information.
959     *
960     * @param columnName is the SQL name of the column
961     * @param cal the calendar to use in constructing the date
962     * @return the column value; if the value is SQL NULL, the result is null
963     * @exception SQLException if a database-access error occurs.
964     */
965    public java.sql.Date getDate(String columnName, Calendar cal) 
966                throws SQLException 
967        {
968                checkIfClosed("getDate");
969                return getDate( findColumnName(columnName), cal);
970        }
971 
972    /**
973     * JDBC 2.0
974     *
975     * Get the value of a column in the current row as a java.sql.Time 
976     * object. Use the calendar to construct an appropriate millisecond
977     * value for the Time, if the underlying database doesn't store
978     * timezone information.
979     *
980     * @param columnIndex the first column is 1, the second is 2, ...
981     * @param cal the calendar to use in constructing the time
982     * @return the column value; if the value is SQL NULL, the result is null
983     * @exception SQLException if a database-access error occurs.
984     */
985    public java.sql.Time getTime(int columnIndex, Calendar cal)
986        throws SQLException 
987    {
988                checkIfClosed("getTime");
989                try {
990 
991                        DataValueDescriptor dvd = getColumn(columnIndex);
992 
993                        if (wasNull = dvd.isNull())
994                                return null;
995 
996            if( cal == null)
997                cal = getCal();
998                        return dvd.getTime( cal);
999 
1000                } catch (StandardException t) {
1001                        throw noStateChangeException(t);
1002                }
1003    }
1004 
1005    /**
1006     * JDBC 2.0
1007     *
1008     * Get the value of a column in the current row as a java.sql.Time 
1009     * object. Use the calendar to construct an appropriate millisecond
1010     * value for the Time, if the underlying database doesn't store
1011     * timezone information.
1012     *
1013     * @param columnName is the SQL name of the column
1014     * @param cal the calendar to use in constructing the time
1015     * @return the column value; if the value is SQL NULL, the result is null
1016     * @exception SQLException if a database-access error occurs.
1017     */
1018    public java.sql.Time getTime(String columnName, Calendar cal)
1019           throws SQLException 
1020        {
1021                checkIfClosed("getTime");
1022                return getTime( findColumnName( columnName), cal);
1023        }
1024 
1025    /**
1026     * JDBC 2.0
1027     *
1028     * Get the value of a column in the current row as a java.sql.Timestamp 
1029     * object. Use the calendar to construct an appropriate millisecond
1030     * value for the Timestamp, if the underlying database doesn't store
1031     * timezone information.
1032     *
1033     * @param columnName is the SQL name of the column
1034     * @param cal the calendar to use in constructing the timestamp
1035     * @return the column value; if the value is SQL NULL, the result is null
1036     * @exception SQLException if a database-access error occurs.
1037     */
1038    public java.sql.Timestamp getTimestamp(String columnName, Calendar cal)     
1039      throws SQLException 
1040        {
1041                checkIfClosed("getTimestamp");
1042                return getTimestamp(findColumnName(columnName), cal);
1043        }
1044 
1045    /**
1046     * JDBC 2.0
1047     *
1048     * Get the value of a column in the current row as a java.sql.Timestamp 
1049     * object. Use the calendar to construct an appropriate millisecond
1050     * value for the Timestamp, if the underlying database doesn't store
1051     * timezone information.
1052     *
1053     * @param columnIndex the first column is 1, the second is 2, ...
1054     * @param cal the calendar to use in constructing the timestamp
1055     * @return the column value; if the value is SQL NULL, the result is null
1056     * @exception SQLException if a database-access error occurs.
1057     */
1058    public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) 
1059        throws SQLException 
1060    {
1061                checkIfClosed("getTimestamp");
1062                try {
1063 
1064                        DataValueDescriptor dvd = getColumn(columnIndex);
1065 
1066                        if (wasNull = dvd.isNull())
1067                                return null;
1068 
1069            if( cal == null)
1070                cal = getCal();
1071                        return dvd.getTimestamp( cal);
1072 
1073                } catch (StandardException t) {
1074                        throw noStateChangeException(t);
1075                }
1076    }
1077 
1078        /**
1079     * JDBC 2.0
1080     *
1081     * <p>Get the value of a column in the current row as a java.io.Reader.
1082     *
1083     * @exception SQLException database error.
1084     */
1085    public final java.io.Reader getCharacterStream(int columnIndex)
1086                throws SQLException
1087        {
1088                checkIfClosed("getCharacterStream");
1089                int lmfs;
1090                int colType = getColumnType(columnIndex);
1091                switch (colType) {
1092                case Types.CHAR:
1093                case Types.VARCHAR:
1094                case Types.LONGVARCHAR:
1095                        lmfs = maxFieldSize;
1096                        break;
1097                case Types.CLOB: // Embedded and JCC extension - CLOB is not subject to max field size.
1098                        lmfs = 0;
1099                        break;
1100 
1101                // JDBC says to support these, but no defintion exists for the output.
1102                // match JCC which treats the bytes as a UTF16-BE stream
1103                case Types.BINARY:
1104                case Types.VARBINARY:
1105                case Types.LONGVARBINARY:
1106                case Types.BLOB:
1107                        try {
1108                                java.io.InputStream is = getBinaryStream(columnIndex);
1109                                if (is == null)
1110                                        return null;
1111                                java.io.Reader r = new java.io.InputStreamReader(is, "UTF-16BE");
1112                                currentStream = r;
1113                                return r;
1114                        } catch (java.io.UnsupportedEncodingException uee) {
1115                                throw new SQLException(uee.getMessage());
1116                        }
1117                default:
1118                        throw dataTypeConversion("java.io.Reader", columnIndex);
1119                }
1120 
1121                Object syncLock = getConnectionSynchronization();
1122 
1123                synchronized (syncLock) {
1124 
1125                boolean pushStack = false;
1126                try {
1127 
1128                    useStream(columnIndex);
1129 
1130                        DataValueDescriptor dvd = getColumn(columnIndex);
1131 
1132                        if (wasNull = dvd.isNull()) { return null; }
1133 
1134                        pushStack = true;
1135                        setupContextStack();
1136 
1137                        StreamStorable ss = (StreamStorable) dvd;
1138 
1139                        InputStream stream = ss.returnStream();
1140 
1141                        if (stream == null) {
1142 
1143                                String val = dvd.getString();
1144                                if (lmfs > 0) {
1145                                        if (val.length() > lmfs)
1146                                                val = val.substring(0, lmfs);
1147                                }
1148                                java.io.Reader ret = new java.io.StringReader(val);
1149                                currentStream = ret;
1150                                return ret;
1151                        }
1152 
1153                        java.io.Reader ret = new UTF8Reader(stream, lmfs, this, syncLock);
1154                        currentStream = ret;
1155                        return ret;
1156 
1157                } catch (Throwable t) {
1158                        throw noStateChangeException(t);
1159                } finally {
1160                        if (pushStack) { restoreContextStack(); }
1161                }
1162          }
1163     }
1164 
1165    /**
1166                Pushes a converter on top of getCharacterStream().
1167         *
1168     * @param columnIndex the first column is 1, the second is 2, ...
1169     * @return a Java input stream that delivers the database column value
1170     * as a stream of one byte ASCII characters.  If the value is SQL NULL
1171     * then the result is null.
1172         * @exception SQLException thrown on failure.
1173     */
1174    public final InputStream getAsciiStream(int columnIndex) throws SQLException {
1175                checkIfClosed("getAsciiStream");
1176                int colType = getColumnType(columnIndex);
1177                switch (colType) {
1178                case Types.CHAR:
1179                case Types.VARCHAR:
1180                case Types.LONGVARCHAR:
1181                case Types.CLOB: // Embedded and JCC extension
1182                        break;
1183 
1184                // JDBC says to support these, we match JCC by returning the raw bytes.
1185                case Types.BINARY:
1186                case Types.VARBINARY:
1187                case Types.LONGVARBINARY:
1188                case Types.BLOB:
1189                        return getBinaryStream(columnIndex);
1190 
1191                default:
1192                        throw dataTypeConversion("java.io.InputStream(ASCII)", columnIndex);
1193                }
1194 
1195                java.io.Reader reader = getCharacterStream(columnIndex);
1196                if (reader == null)
1197                        return null;
1198 
1199                return new ReaderToAscii(reader);
1200        }
1201 
1202    /**
1203         * Get the column as an InputStream. If the column is already of type
1204           InputStream then just return it, otherwise convert the column to a set
1205           of bytes and create a stream out of the bytes.
1206     *
1207     * @param columnIndex the first column is 1, the second is 2, ...
1208     * @return a Java input stream that delivers the database column value
1209     * as a stream of uninterpreted bytes.  If the value is SQL NULL
1210     * then the result is null.
1211         * @exception SQLException thrown on failure.
1212     */
1213    public final InputStream getBinaryStream(int columnIndex) throws SQLException {
1214                checkIfClosed("getBinaryStream");
1215                int lmfs;
1216                int colType = getColumnType(columnIndex);
1217                switch (colType) {
1218                case Types.BINARY:
1219                case Types.VARBINARY:
1220                case Types.LONGVARBINARY:
1221                        lmfs = maxFieldSize;
1222                        break;
1223                case Types.BLOB:
1224                        lmfs = 0;
1225                        break;
1226 
1227                default:
1228                        throw dataTypeConversion("java.io.InputStream", columnIndex);
1229                }
1230 
1231                Object syncLock = getConnectionSynchronization();
1232 
1233                synchronized (syncLock) {
1234 
1235                boolean pushStack = false;
1236                try {
1237                    
1238                    useStream(columnIndex);
1239 
1240                        DataValueDescriptor dvd = getColumn(columnIndex);
1241 
1242                        if (wasNull = dvd.isNull()) { return null; }
1243 
1244                        pushStack = true;
1245                        setupContextStack();
1246 
1247                        StreamStorable ss = (StreamStorable) dvd;
1248 
1249                        InputStream stream = ss.returnStream();
1250 
1251                        if (stream == null)
1252                        {
1253                                stream = new NewByteArrayInputStream(dvd.getBytes());
1254                        } else
1255                        {
1256                                stream = new BinaryToRawStream(stream, dvd);
1257                        }
1258 
1259            if (lmfs > 0)
1260            {
1261                // Just wrap the InputStream with a LimitInputStream class
1262                LimitInputStream  limitResultIn = new  LimitInputStream(stream);
1263                limitResultIn.setLimit(lmfs);
1264                stream = limitResultIn;
1265            }
1266                        currentStream = stream;
1267                        return stream;
1268 
1269                } catch (Throwable t) {
1270                        throw noStateChangeException(t);
1271                } finally {
1272                        if (pushStack) { restoreContextStack(); }
1273                }
1274          }
1275        }
1276 
1277    //======================================================================
1278    // Methods for accessing results by column name
1279    //======================================================================
1280 
1281 
1282    /**
1283     * Get the value of a column in the current row as a Java String.
1284     *
1285     * @param columnName is the SQL name of the column
1286     * @return the column value; if the value is SQL NULL, the result is null
1287         * @exception SQLException thrown on failure.
1288     */
1289    public final String getString(String columnName) throws SQLException {
1290        checkIfClosed("getString");
1291            return (getString(findColumnName(columnName)));
1292        }
1293 
1294    /**
1295     * Get the value of a column in the current row as a Java boolean.
1296     *
1297     * @param columnName is the SQL name of the column
1298     * @return the column value; if the value is SQL NULL, the result is false
1299         * @exception SQLException thrown on failure.
1300     */
1301    public final boolean getBoolean(String columnName) throws SQLException {
1302        checkIfClosed("getBoolean");
1303            return (getBoolean(findColumnName(columnName)));
1304        }
1305 
1306    /**
1307     * Get the value of a column in the current row as a Java byte.
1308     *
1309     * @param columnName is the SQL name of the column
1310     * @return the column value; if the value is SQL NULL, the result is 0
1311         * @exception SQLException thrown on failure.
1312     */
1313    public final byte getByte(String columnName) throws SQLException        {
1314        checkIfClosed("getByte");
1315            return (getByte(findColumnName(columnName)));
1316        }
1317 
1318    /**
1319     * Get the value of a column in the current row as a Java short.
1320     *
1321     * @param columnName is the SQL name of the column
1322     * @return the column value; if the value is SQL NULL, the result is 0
1323         * @exception SQLException thrown on failure.
1324     */
1325    public final short getShort(String columnName) throws SQLException {
1326        checkIfClosed("getShort");
1327            return (getShort(findColumnName(columnName)));
1328        }
1329 
1330    /**
1331     * Get the value of a column in the current row as a Java int.
1332     *
1333     * @param columnName is the SQL name of the column
1334     * @return the column value; if the value is SQL NULL, the result is 0
1335         * @exception SQLException thrown on failure.
1336     */
1337    public final int getInt(String columnName) throws SQLException {
1338        checkIfClosed("getInt");
1339            return (getInt(findColumnName(columnName)));
1340        }
1341 
1342    /**
1343     * Get the value of a column in the current row as a Java long.
1344     *
1345     * @param columnName is the SQL name of the column
1346     * @return the column value; if the value is SQL NULL, the result is 0
1347         * @exception SQLException thrown on failure.
1348     */
1349    public final long getLong(String columnName) throws SQLException {
1350        checkIfClosed("getLong");
1351            return (getLong(findColumnName(columnName)));
1352        }
1353 
1354    /**
1355     * Get the value of a column in the current row as a Java float.
1356     *
1357     * @param columnName is the SQL name of the column
1358     * @return the column value; if the value is SQL NULL, the result is 0
1359         * @exception SQLException thrown on failure.
1360     */
1361    public final float getFloat(String columnName) throws SQLException {
1362        checkIfClosed("getFloat");
1363            return (getFloat(findColumnName(columnName)));
1364        }
1365 
1366    /**
1367     * Get the value of a column in the current row as a Java double.
1368     *
1369     * @param columnName is the SQL name of the column
1370     * @return the column value; if the value is SQL NULL, the result is 0
1371         * @exception SQLException thrown on failure.
1372     */
1373    public final double getDouble(String columnName) throws SQLException {
1374        checkIfClosed("getDouble");
1375            return (getDouble(findColumnName(columnName)));
1376        }
1377 
1378    /**
1379     * Get the value of a column in the current row as a Java byte array.
1380     * The bytes represent the raw values returned by the driver.
1381     *
1382     * @param columnName is the SQL name of the column
1383     * @return the column value; if the value is SQL NULL, the result is null
1384         * @exception SQLException thrown on failure.
1385     */
1386    public final byte[] getBytes(String columnName) throws SQLException {
1387        checkIfClosed("getBytes");
1388            return (getBytes(findColumnName(columnName)));
1389        }
1390 
1391    /**
1392     * Get the value of a column in the current row as a java.sql.Date object.
1393     *
1394     * @param columnName is the SQL name of the column
1395     * @return the column value; if the value is SQL NULL, the result is null
1396         * @exception SQLException thrown on failure.
1397     */
1398    public final Date getDate(String columnName) throws SQLException {
1399        checkIfClosed("getDate");
1400            return (getDate(findColumnName(columnName)));
1401        }
1402 
1403    /**
1404     * Get the value of a column in the current row as a java.sql.Time object.
1405     *
1406     * @param columnName is the SQL name of the column
1407     * @return the column value; if the value is SQL NULL, the result is null
1408         * @exception SQLException thrown on failure.
1409     */
1410    public final Time getTime(String columnName) throws SQLException {
1411        checkIfClosed("getTime");
1412            return (getTime(findColumnName(columnName)));
1413        }
1414 
1415    /**
1416     * Get the value of a column in the current row as a java.sql.Timestamp object.
1417     *
1418     * @param columnName is the SQL name of the column
1419     * @return the column value; if the value is SQL NULL, the result is null
1420         * @exception SQLException thrown on failure.
1421     */
1422    public final Timestamp getTimestamp(String columnName) throws SQLException {
1423        checkIfClosed("getTimestamp");
1424            return (getTimestamp(findColumnName(columnName)));
1425        }
1426 
1427        /**
1428     * JDBC 2.0
1429     *
1430     * <p>Get the value of a column in the current row as a java.io.Reader.
1431         *
1432         * @exception SQLException Feature not implemented for now.
1433     */
1434    public final java.io.Reader getCharacterStream(String columnName)
1435    throws SQLException {
1436        checkIfClosed("getCharacterStream");
1437            return (getCharacterStream(findColumnName(columnName)));
1438    }
1439 
1440    /**
1441     * A column value can be retrieved as a stream of ASCII characters
1442     * and then read in chunks from the stream.  This method is particularly
1443     * suitable for retrieving large LONGVARCHAR values.  The JDBC driver will
1444     * do any necessary conversion from the database format into ASCII.
1445     *
1446     * <P><B>Note:</B> All the data in the returned stream must
1447     * be read prior to getting the value of any other column. The
1448     * next call to a get method implicitly closes the stream.
1449     *
1450     * @param columnName is the SQL name of the column
1451     * @return a Java input stream that delivers the database column value
1452     * as a stream of one byte ASCII characters.  If the value is SQL NULL
1453     * then the result is null.
1454         * @exception SQLException thrown on failure.
1455     */
1456    public final InputStream getAsciiStream(String columnName) throws SQLException {
1457        checkIfClosed("getAsciiStream");
1458            return (getAsciiStream(findColumnName(columnName)));
1459        }
1460 
1461    /**
1462     * A column value can be retrieved as a stream of uninterpreted bytes
1463     * and then read in chunks from the stream.  This method is particularly
1464     * suitable for retrieving large LONGVARBINARY values.
1465     *
1466     * <P><B>Note:</B> All the data in the returned stream must
1467     * be read prior to getting the value of any other column. The
1468     * next call to a get method implicitly closes the stream.
1469     *
1470     * @param columnName is the SQL name of the column
1471     * @return a Java input stream that delivers the database column value
1472     * as a stream of uninterpreted bytes.  If the value is SQL NULL
1473     * then the result is null.
1474         * @exception SQLException thrown on failure.
1475     */
1476    public final InputStream getBinaryStream(String columnName) throws SQLException {
1477        checkIfClosed("getBinaryStream");
1478            return (getBinaryStream(findColumnName(columnName)));
1479        }
1480 
1481    /**
1482         * JDBC 3.0
1483         * 
1484         * Retrieves the value of the designated column in the current row of this
1485         * ResultSet object as a java.net.URL object in the Java programming
1486         * language.
1487         * 
1488         * @param columnIndex -
1489         *            the first column is 1, the second is 2
1490         * @return the column value as a java.net.URL object, if the value is SQL
1491         *         NULL, the value returned is null in the Java programming language
1492         * @exception SQLException
1493         *                Feature not implemented for now.
1494         */
1495        public URL getURL(int columnIndex) throws SQLException {
1496                throw Util.notImplemented();
1497        }
1498 
1499        /**
1500         * JDBC 3.0
1501         * 
1502         * Retrieves the value of the designated column in the current row of this
1503         * ResultSet object as a java.net.URL object in the Java programming
1504         * language.
1505         * 
1506         * @param columnName -
1507         *            the SQL name of the column
1508         * @return the column value as a java.net.URL object, if the value is SQL
1509         *         NULL, the value returned is null in the Java programming language
1510         * @exception SQLException
1511         *                Feature not implemented for now.
1512         */
1513        public URL getURL(String columnName) throws SQLException {
1514                throw Util.notImplemented();
1515        }
1516 
1517        //=====================================================================
1518    // Advanced features:
1519    //=====================================================================
1520 
1521    /**
1522     * <p>The first warning reported by calls on this ResultSet is
1523     * returned. Subsequent ResultSet warnings will be chained to this
1524     * SQLWarning.
1525     *
1526     * <P>The warning chain is automatically cleared each time a new
1527     * row is read.
1528     *
1529     * <P><B>Note:</B> This warning chain only covers warnings caused
1530     * by ResultSet methods.  Any warning caused by statement methods
1531     * (such as reading OUT parameters) will be chained on the
1532     * Statement object.
1533     *
1534     * @return the first SQLWarning or null
1535         *
1536         * @exception SQLException         Thrown if this ResultSet is closed
1537     */
1538    public final SQLWarning getWarnings() throws SQLException {
1539                checkIfClosed("getWarnings");
1540                return topWarning;
1541        }
1542 
1543    /**
1544     * After this call getWarnings returns null until a new warning is
1545     * reported for this ResultSet.
1546         *
1547         * @exception SQLException        Thrown if this ResultSet is closed
1548     */
1549    public final void clearWarnings() throws SQLException {
1550                checkIfClosed("clearWarnings");
1551                topWarning = null;
1552        }
1553 
1554    /**
1555     * Get the name of the SQL cursor used by this ResultSet.
1556     *
1557     * <P>In SQL, a result table is retrieved through a cursor that is
1558     * named. The current row of a result can be updated or deleted
1559     * using a positioned update/delete statement that references the
1560     * cursor name.
1561     *
1562     * <P>JDBC supports this SQL feature by providing the name of the
1563     * SQL cursor used by a ResultSet. The current row of a ResultSet
1564     * is also the current row of this SQL cursor.
1565     *
1566     * <P><B>Note:</B> If positioned update is not supported a
1567     * SQLException is thrown
1568     *
1569     * @return the ResultSet's SQL cursor name
1570         * @exception SQLException thrown on failure.
1571     */
1572    public final String getCursorName() throws SQLException {
1573 
1574          checkIfClosed("getCursorName");        // checking result set closure does not depend
1575                                                                // on the underlying connection.  Do this
1576                                                                // outside of the connection synchronization.
1577          
1578          return theResults.getCursorName();
1579        }
1580 
1581    /**
1582     * The number, types and properties of a ResultSet's columns
1583     * are provided by the getMetaData method.
1584     *
1585     * @return the description of a ResultSet's columns
1586         * @exception SQLException thrown on failure.
1587     */
1588    public ResultSetMetaData getMetaData() throws SQLException {
1589 
1590          checkIfClosed("getMetaData");        // checking result set closure does not depend
1591                                                                // on the underlying connection.  Do this
1592                                                                // outside of the connection synchronization.
1593 
1594          synchronized (getConnectionSynchronization()) {
1595 
1596 
1597                if (rMetaData == null) {
1598                        // cache this object and keep returning it
1599                        rMetaData = newEmbedResultSetMetaData(resultDescription);
1600                }
1601                return rMetaData;
1602          }
1603        }
1604    
1605    /**
1606     * JDBC 4.0
1607     * 
1608     * <p>
1609     * Retrieves the holdability for this <code>ResultSet</code>
1610     * object.
1611     * 
1612     * @return either <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code>
1613     *         or <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
1614     * @exception SQLException
1615     *                if a database error occurs
1616     */
1617    public final int getHoldability() throws SQLException {
1618        checkIfClosed("getHoldability");
1619        if (theResults.getActivation().getResultSetHoldability()) {
1620            return JDBC30Translation.HOLD_CURSORS_OVER_COMMIT;
1621        }
1622        return JDBC30Translation.CLOSE_CURSORS_AT_COMMIT;
1623    }
1624 
1625    /**
1626     * <p>Get the value of a column in the current row as a Java object.
1627     *
1628     * <p>This method will return the value of the given column as a
1629     * Java object.  The type of the Java object will be the default
1630     * Java Object type corresponding to the column's SQL type,
1631     * following the mapping specified in the JDBC spec.
1632     *
1633     * <p>This method may also be used to read datatabase specific abstract
1634     * data types.
1635         *
1636         * JDBC 2.0
1637     *
1638     * New behavior for getObject().
1639     * The behavior of method getObject() is extended to materialize  
1640     * data of SQL user-defined types.  When the column @columnIndex is 
1641     * a structured or distinct value, the behavior of this method is as 
1642     * if it were a call to: getObject(columnIndex, 
1643     * this.getStatement().getConnection().getTypeMap()).
1644     *
1645     * @param columnIndex the first column is 1, the second is 2, ...
1646     * @return A java.lang.Object holding the column value.
1647         * @exception SQLException thrown on failure.
1648     */
1649    public final Object getObject(int columnIndex) throws SQLException {
1650        checkIfClosed("getObject");
1651 
1652                // need special handling for some types.
1653                int colType = getColumnType(columnIndex);
1654                switch (colType) {
1655                case Types.CHAR:
1656                case Types.VARCHAR:
1657                case Types.LONGVARCHAR:
1658                        // handles maxfield size correctly
1659                        return getString(columnIndex);
1660 
1661                case Types.CLOB:
1662                        return getClob(columnIndex);
1663 
1664                case Types.BINARY:
1665                case Types.VARBINARY:
1666                case Types.LONGVARBINARY:
1667                        // handles maxfield size correctly
1668                        return getBytes(columnIndex);
1669 
1670                case Types.BLOB:
1671                        return getBlob(columnIndex);
1672 
1673                default:
1674                        break;
1675                }
1676 
1677                try {
1678 
1679                        DataValueDescriptor dvd = getColumn(columnIndex);
1680                        if (wasNull = dvd.isNull())
1681                                return null;
1682 
1683                        return dvd.getObject();
1684 
1685                } catch (StandardException t) {
1686                        throw noStateChangeException(t);
1687                }
1688        }
1689 
1690    /**
1691     * <p>Get the value of a column in the current row as a Java object.
1692     *
1693     * <p>This method will return the value of the given column as a
1694     * Java object.  The type of the Java object will be the default
1695     * Java Object type corresponding to the column's SQL type,
1696     * following the mapping specified in the JDBC spec.
1697     *
1698     * <p>This method may also be used to read datatabase specific abstract
1699     * data types.
1700     *
1701     * JDBC 2.0
1702     *
1703     * New behavior for getObject().
1704     * The behavior of method getObject() is extended to materialize  
1705     * data of SQL user-defined types.  When the column @columnName is 
1706     * a structured or distinct value, the behavior of this method is as 
1707     * if it were a call to: getObject(columnName, 
1708     * this.getStatement().getConnection().getTypeMap()).
1709     *
1710     * @param columnName is the SQL name of the column
1711     * @return A java.lang.Object holding the column value.
1712         * @exception SQLException thrown on failure.
1713     */
1714    public final Object getObject(String columnName) throws SQLException {
1715        checkIfClosed("getObject");
1716            return (getObject(findColumnName(columnName)));
1717        }
1718 
1719 
1720    //----------------------------------------------------------------
1721 
1722    /**
1723     * Map a Resultset column name to a ResultSet column index.
1724     *
1725     * @param columnName the name of the column
1726     * @return the column index
1727         * @exception SQLException thrown on failure.
1728     */
1729        public final int findColumn(String columnName) throws SQLException {
1730                checkIfClosed("findColumn");
1731                return findColumnName(columnName);
1732        }
1733        
1734    /////////////////////////////////////////////////////////////////////////
1735    //
1736    //      JDBC 2.0        -       New public methods
1737    //
1738    /////////////////////////////////////////////////////////////////////////
1739 
1740 
1741        //---------------------------------------------------------------------
1742        // Getter's and Setter's
1743        //---------------------------------------------------------------------
1744 
1745        /**
1746         * JDBC 2.0
1747         * 
1748         * Return the Statement that produced the ResultSet.
1749         * 
1750         * @return the Statment that produced the result set, or null if the result
1751         *         was produced some other way.
1752         * @exception SQLException if a database error occurs or the
1753         * result set is closed
1754         */
1755        public final Statement getStatement() throws SQLException
1756    {
1757            checkIfClosed("getStatement");
1758            return applicationStmt;
1759    }
1760    
1761    /**
1762     * Set the application Statement object that created this ResultSet.
1763     * Used when the Statement objects returned to the application
1764     * are wrapped for XA.
1765     */
1766    public final void setApplicationStatement(Statement applicationStmt)
1767    {
1768        this.applicationStmt = applicationStmt;
1769    }
1770 
1771        //---------------------------------------------------------------------
1772        // Traversal/Positioning
1773        //---------------------------------------------------------------------
1774 
1775        /**
1776         * JDBC 2.0
1777         * 
1778         * <p>
1779         * Determine if the cursor is before the first row in the result set.
1780         * 
1781         * @return true if before the first row, false otherwise. Returns false when
1782         *         the result set contains no rows.
1783         * @exception SQLException
1784         *                Thrown on error.
1785         */
1786        public boolean isBeforeFirst() throws SQLException {
1787                return checkRowPosition(ResultSet.ISBEFOREFIRST, "isBeforeFirst");
1788        }
1789 
1790        /**
1791         * JDBC 2.0
1792         * 
1793         * <p>
1794         * Determine if the cursor is after the last row in the result set.
1795         * 
1796         * @return true if after the last row, false otherwise. Returns false when
1797         *         the result set contains no rows.
1798         * @exception SQLException
1799         *                Thrown on error.
1800         */
1801        public boolean isAfterLast() throws SQLException {
1802                return checkRowPosition(ResultSet.ISAFTERLAST, "isAfterLast");
1803        }
1804 
1805        /**
1806         * JDBC 2.0
1807         * 
1808         * <p>
1809         * Determine if the cursor is on the first row of the result set.
1810         * 
1811         * @return true if on the first row, false otherwise.
1812         * @exception SQLException
1813         *                Thrown on error.
1814         */
1815        public boolean isFirst() throws SQLException {
1816                return checkRowPosition(ResultSet.ISFIRST, "isFirst");
1817        }
1818 
1819        /**
1820         * JDBC 2.0
1821         * 
1822         * <p>
1823         * Determine if the cursor is on the last row of the result set. Note:
1824         * Calling isLast() may be expensive since the JDBC driver might need to
1825         * fetch ahead one row in order to determine whether the current row is the
1826         * last row in the result set.
1827         * 
1828         * @return true if on the last row, false otherwise.
1829         * @exception SQLException
1830         *                Thrown on error.
1831         */
1832        public boolean isLast() throws SQLException {
1833                return checkRowPosition(ResultSet.ISLAST, "isLast");
1834        }
1835 
1836        /**
1837         * JDBC 2.0
1838         * 
1839         * <p>
1840         * Moves to the front of the result set, just before the first row. Has no
1841         * effect if the result set contains no rows.
1842         * 
1843         * @exception SQLException
1844         *                if a database-access error occurs, or result set type is
1845         *                TYPE_FORWARD_ONLY
1846         */
1847        public void beforeFirst() throws SQLException {
1848                // beforeFirst is only allowed on scroll cursors
1849                checkScrollCursor("beforeFirst()");
1850                movePosition(BEFOREFIRST, "beforeFirst");
1851        }
1852 
1853        /**
1854         * JDBC 2.0
1855         * 
1856         * <p>
1857         * Moves to the end of the result set, just after the last row. Has no
1858         * effect if the result set contains no rows.
1859         * 
1860         * @exception SQLException
1861         *                if a database-access error occurs, or result set type is
1862         *                TYPE_FORWARD_ONLY.
1863         */
1864        public void afterLast() throws SQLException {
1865                // afterLast is only allowed on scroll cursors
1866                checkScrollCursor("afterLast()");
1867                movePosition(AFTERLAST, "afterLast");
1868        }
1869 
1870        /**
1871         * JDBC 2.0
1872         * 
1873         * <p>
1874         * Moves to the first row in the result set.
1875         * 
1876         * @return true if on a valid row, false if no rows in the result set.
1877         * @exception SQLException
1878         *                if a database-access error occurs, or result set type is
1879         *                TYPE_FORWARD_ONLY.
1880         */
1881        public boolean first() throws SQLException {
1882                // first is only allowed on scroll cursors
1883                checkScrollCursor("first()");
1884                return movePosition(FIRST, "first");
1885        }
1886 
1887        /**
1888         * JDBC 2.0
1889         * 
1890         * <p>
1891         * Moves to the last row in the result set.
1892         * 
1893         * @return true if on a valid row, false if no rows in the result set.
1894         * @exception SQLException
1895         *                if a database-access error occurs, or result set type is
1896         *                TYPE_FORWARD_ONLY.
1897         */
1898        public boolean last() throws SQLException {
1899                // last is only allowed on scroll cursors
1900                checkScrollCursor("last()");
1901                return movePosition(LAST, "last");
1902        }
1903 
1904        /**
1905         * JDBC 2.0
1906         * 
1907         * <p>
1908         * Determine the current row number. The first row is number 1, the second
1909         * number 2, etc.
1910         * 
1911         * @return the current row number, else return 0 if there is no current row
1912         * @exception SQLException
1913         *                if a database-access error occurs.
1914         */
1915        public int getRow() throws SQLException {
1916                // getRow() is only allowed on scroll cursors
1917                checkScrollCursor("getRow()");
1918 
1919                /*
1920                 * * We probably needn't bother getting the text of * the underlying
1921                 * statement but it is better to be * consistent and we aren't
1922                 * particularly worried * about performance of getRow().
1923                 */
1924                return theResults.getRowNumber();
1925        }
1926 
1927        /**
1928         * JDBC 2.0
1929         * 
1930         * <p>
1931         * Move to an absolute row number in the result set.
1932         * 
1933         * <p>
1934         * If row is positive, moves to an absolute row with respect to the
1935         * beginning of the result set. The first row is row 1, the second is row 2,
1936         * etc.
1937         * 
1938         * <p>
1939         * If row is negative, moves to an absolute row position with respect to the
1940         * end of result set. For example, calling absolute(-1) positions the cursor
1941         * on the last row, absolute(-2) indicates the next-to-last row, etc.
1942         * 
1943         * <p>
1944         * An attempt to position the cursor beyond the first/last row in the result
1945         * set, leaves the cursor before/after the first/last row, respectively.
1946         * 
1947         * <p>
1948         * Note: Calling absolute(1) is the same as calling first(). Calling
1949         * absolute(-1) is the same as calling last().
1950         * 
1951         * @return true if on the result set, false if off.
1952         * @exception SQLException
1953         *                if a database-access error occurs, or row is 0, or result
1954         *                set type is TYPE_FORWARD_ONLY.
1955         */
1956        public boolean absolute(int row) throws SQLException {
1957                // absolute is only allowed on scroll cursors
1958                checkScrollCursor("absolute()");
1959                return movePosition(ABSOLUTE, row, "absolute");
1960        }
1961 
1962        /**
1963         * JDBC 2.0
1964         * 
1965         * <p>
1966         * Moves a relative number of rows, either positive or negative. Attempting
1967         * to move beyond the first/last row in the result set positions the cursor
1968         * before/after the the first/last row. Calling relative(0) is valid, but
1969         * does not change the cursor position.
1970         * 
1971         * <p>
1972         * Note: Calling relative(1) is different than calling next() since is makes
1973         * sense to call next() when there is no current row, for example, when the
1974         * cursor is positioned before the first row or after the last row of the
1975         * result set.
1976         * 
1977         * @return true if on a row, false otherwise.
1978         * @exception SQLException
1979         *                if a database-access error occurs, or there is no current
1980         *                row, or result set type is TYPE_FORWARD_ONLY.
1981         */
1982        public boolean relative(int row) throws SQLException {
1983                // absolute is only allowed on scroll cursors
1984                checkScrollCursor("relative()");
1985                return movePosition(RELATIVE, row, "relative");
1986        }
1987 
1988        /**
1989         * JDBC 2.0
1990         * 
1991         * <p>
1992         * Moves to the previous row in the result set.
1993         * 
1994         * <p>
1995         * Note: previous() is not the same as relative(-1) since it makes sense to
1996         * call previous() when there is no current row.
1997         * 
1998         * @return true if on a valid row, false if off the result set.
1999         * @exception SQLException
2000         *                if a database-access error occurs, or result set type is
2001         *                TYPE_FORWAR_DONLY.
2002         */
2003        public boolean previous() throws SQLException {
2004                // previous is only allowed on scroll cursors
2005                checkScrollCursor("previous()");
2006                return movePosition(PREVIOUS, "previous");
2007        }
2008 
2009        //---------------------------------------------------------------------
2010        // Properties
2011        //---------------------------------------------------------------------
2012 
2013        /**
2014         * JDBC 2.0
2015         * 
2016         * Give a hint as to the direction in which the rows in this result set will
2017         * be processed. The initial value is determined by the statement that
2018         * produced the result set. The fetch direction may be changed at any time.
2019         * 
2020         * @exception SQLException
2021         *                if a database-access error occurs, or the result set type
2022         *                is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
2023         */
2024        public void setFetchDirection(int direction) throws SQLException {
2025                checkScrollCursor("setFetchDirection()");
2026                /*
2027                 * FetchDirection is meaningless to us. We just save it off and return
2028                 * the current value if asked.
2029                 */
2030                fetchDirection = direction;
2031        }
2032 
2033        /**
2034         * JDBC 2.0
2035         * 
2036         * Return the fetch direction for this result set.
2037         * 
2038         * @exception SQLException
2039         *                if a database-access error occurs
2040         */
2041        public int getFetchDirection() throws SQLException {
2042                checkIfClosed("getFetchDirection");
2043                if (fetchDirection == 0) {
2044                        // value is not set at the result set level
2045                        // get it from the statement level
2046                        return stmt.getFetchDirection();
2047                } else
2048                        return fetchDirection;
2049        }
2050 
2051        /**
2052         * JDBC 2.0
2053         * 
2054         * Give the JDBC driver a hint as to the number of rows that should be
2055         * fetched from the database when more rows are needed for this result set.
2056         * If the fetch size specified is zero, then the JDBC driver ignores the
2057         * value, and is free to make its own best guess as to what the fetch size
2058         * should be. The default value is set by the statement that creates the
2059         * result set. The fetch size may be changed at any time.
2060         * 
2061         * @param rows
2062         *            the number of rows to fetch
2063         * @exception SQLException
2064         *                if a database-access error occurs, or the condition 0 <=
2065         *                rows <= this.getMaxRows() is not satisfied.
2066         */
2067        public void setFetchSize(int rows) throws SQLException {
2068                checkIfClosed("setFetchSize");
2069                if (rows < 0 || (stmt.getMaxRows() != 0 && rows > stmt.getMaxRows())) {
2070                        throw Util.generateCsSQLException(SQLState.INVALID_FETCH_SIZE,
2071                                        new Integer(rows));
2072                } else if (rows > 0) // if it is zero ignore the call
2073                {
2074                        fetchSize = rows;
2075                }
2076        }
2077 
2078        /**
2079         * JDBC 2.0
2080         * 
2081         * Return the fetch size for this result set.
2082         * 
2083         * @exception SQLException
2084         *                if a database-access error occurs
2085         */
2086        public int getFetchSize() throws SQLException {
2087                checkIfClosed("getFetchSize");
2088                if (fetchSize == 0) {
2089                        // value is not set at the result set level
2090                        //  get the default value from the statement
2091                        return stmt.getFetchSize();
2092                } else
2093                        return fetchSize;
2094        }
2095 
2096        /**
2097         * JDBC 2.0
2098         * 
2099         * Return the type of this result set. The type is determined based on the
2100         * statement that created the result set.
2101         * 
2102         * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
2103         *         TYPE_SCROLL_SENSITIVE
2104         * @exception SQLException
2105         *                if a database-access error occurs
2106         */
2107        public int getType() throws SQLException {
2108                checkIfClosed("getType");
2109                return stmt.getResultSetType();
2110        }
2111 
2112        /**
2113         * JDBC 2.0
2114         * 
2115         * Return the concurrency of this result set. The concurrency is determined
2116         * as follows If Statement object has CONCUR_READ_ONLY concurrency, then
2117         * ResultSet object will also have the CONCUR_READ_ONLY concurrency. But if
2118         * Statement object has CONCUR_UPDATABLE concurrency, then the concurrency
2119         * of ResultSet object depends on whether the underlying language resultset
2120         * is updatable or not. If the language resultset is updatable, then JDBC
2121         * ResultSet object will also have the CONCUR_UPDATABLE concurrency. If
2122         * lanugage resultset is not updatable, then JDBC ResultSet object
2123         * concurrency will be set to CONCUR_READ_ONLY.
2124         * 
2125         * @return the concurrency type, CONCUR_READ_ONLY, etc.
2126         * @exception SQLException
2127         *                if a database-access error occurs
2128         */
2129        public int getConcurrency() throws SQLException {
2130                checkIfClosed("getConcurrency");
2131                return concurrencyOfThisResultSet;
2132        }
2133 
2134    //---------------------------------------------------------------------
2135        // Updates
2136        //---------------------------------------------------------------------
2137 
2138        /**
2139         * JDBC 2.0
2140         * 
2141         * Determine if the current row has been updated. The value returned depends
2142         * on whether or not the result set can detect updates.
2143         * 
2144         * @return true if the row has been visibly updated by the owner or another,
2145         *         and updates are detected
2146         * @exception SQLException
2147         *                if a database-access error occurs
2148         * 
2149         * @see EmbedDatabaseMetaData#updatesAreDetected
2150         */
2151        public boolean rowUpdated() throws SQLException {
2152                checkIfClosed("rowUpdated");
2153                checkNotOnInsertRow();
2154                checkOnRow();
2155 
2156        boolean rvalue = false;
2157 
2158                try {
2159                        if (isForUpdate() && 
2160                                        getType() == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
2161                                rvalue = ((ScrollInsensitiveResultSet)theResults).isUpdated();
2162                        }
2163                } catch (Throwable t) {
2164                                handleException(t);
2165                }
2166                return rvalue;
2167        }
2168 
2169        /**
2170         * JDBC 2.0
2171         * 
2172         * Determine if the current row has been inserted. The value returned
2173         * depends on whether or not the result set can detect visible inserts.
2174         * 
2175         * @return true if inserted and inserts are detected
2176         * @exception SQLException
2177         *                if a database-access error occurs
2178         * 
2179         * @see EmbedDatabaseMetaData#insertsAreDetected
2180         */
2181        public boolean rowInserted() throws SQLException {
2182                checkIfClosed("rowInserted");
2183                checkNotOnInsertRow();
2184                checkOnRow();
2185 
2186                return false;
2187        }
2188 
2189        /**
2190         * JDBC 2.0
2191         *
2192         * Determine if this row has been deleted. A deleted row may leave a visible
2193         * "hole" in a result set. This method can be used to detect holes in a
2194         * result set. The value returned depends on whether or not the result set
2195         * can detect deletions.
2196         *
2197         * @return true if deleted and deletes are detected
2198         * @exception SQLException
2199         *                if a database-access error occurs
2200         *
2201         * @see EmbedDatabaseMetaData#deletesAreDetected
2202         */
2203        public boolean rowDeleted() throws SQLException {
2204                checkIfClosed("rowUpdated");
2205                checkNotOnInsertRow();
2206                checkOnRow();
2207 
2208        boolean rvalue = false;
2209 
2210                try {
2211                        if (isForUpdate() && 
2212                                        getType() == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE) {
2213                                rvalue = ((ScrollInsensitiveResultSet)theResults).isDeleted();
2214                        }
2215                } catch (Throwable t) {
2216                        handleException(t);
2217                }
2218                return rvalue;
2219        }
2220 
2221        //do following few checks before accepting updateXXX resultset api
2222        protected void checksBeforeUpdateXXX(String methodName, int columnIndex) throws SQLException {
2223      checksBeforeUpdateOrDelete(methodName, columnIndex);
2224 
2225      //1)Make sure for updateXXX methods, the column position is not out of range
2226      ResultDescription rd = theResults.getResultDescription();
2227      if (columnIndex < 1 || columnIndex > rd.getColumnCount())
2228        throw Util.generateCsSQLException(SQLState.LANG_INVALID_COLUMN_POSITION,
2229                                        new Integer(columnIndex), String.valueOf(rd.getColumnCount()));
2230 
2231      //2)Make sure the column corresponds to a column in the base table and it is not a derived column
2232      if (rd.getColumnDescriptor(columnIndex).getSourceTableName() == null)
2233        throw Util.generateCsSQLException(SQLState.COLUMN_NOT_FROM_BASE_TABLE,
2234                                        methodName);
2235 
2236      //3)If column not updatable then throw an exception
2237      if (!getMetaData().isWritable(columnIndex))
2238        throw Util.generateCsSQLException(SQLState.LANG_COLUMN_NOT_UPDATABLE_IN_CURSOR,
2239                                        theResults.getResultDescription().getColumnDescriptor(columnIndex).getName(),
2240                                        getCursorName());
2241        }
2242 
2243        //do following few checks before accepting updateRow or deleteRow
2244        //1)Make sure JDBC ResultSet is not closed
2245        //2)Make sure this is an updatable ResultSet
2246        //3)Make sure JDBC ResultSet is positioned on a row
2247        //4)Make sure underneath language resultset is not closed
2248        protected void checksBeforeUpdateOrDelete(String methodName, int columnIndex) throws SQLException {
2249 
2250      //1)Make sure JDBC ResultSet is not closed
2251      checkIfClosed(methodName);
2252 
2253      //2)Make sure this is an updatable ResultSet
2254      checkUpdatableCursor(methodName);
2255 
2256      //3)Make sure JDBC ResultSet is positioned on a row
2257      if (!isOnInsertRow) checkOnRow(); // make sure there's a current row
2258      //in case of autocommit on, if there was an exception which caused runtime rollback in this transaction prior to this call,
2259      //the rollback code will mark the language resultset closed (it doesn't mark the JDBC ResultSet closed).
2260      //That is why alongwith the earlier checkIfClosed call in this method, there is a check for language resultset close as well.
2261 
2262      //4)Make sure underneath language resultset is not closed
2263      if (theResults.isClosed())
2264        throw Util.generateCsSQLException(SQLState.LANG_RESULT_SET_NOT_OPEN, methodName);
2265        }
2266 
2267        //mark the column as updated and return DataValueDescriptor for it. It will be used by updateXXX methods to put new values
2268        protected DataValueDescriptor getDVDforColumnToBeUpdated(int columnIndex, String updateMethodName) throws StandardException, SQLException {
2269      checksBeforeUpdateXXX(updateMethodName, columnIndex);
2270      columnGotUpdated[columnIndex-1] = true;
2271      currentRowHasBeenUpdated = true;
2272      
2273      return updateRow.getColumn(columnIndex);
2274        }
2275 
2276    /* do following few checks before accepting insertRow
2277     * 1) Make sure JDBC ResultSet is not closed
2278     * 2) Make sure this is an updatable ResultSet
2279     * 3) Make sure JDBC ResultSet is positioned on insertRow
2280     * 4) Make sure underneath language resultset is not closed
2281     */
2282    protected void checksBeforeInsert() throws SQLException {
2283        // 1)Make sure JDBC ResultSet is not closed
2284        checkIfClosed("insertRow");
2285 
2286        // 2)Make sure this is an updatable ResultSet
2287        // if not updatable resultset, then throw exception
2288        checkUpdatableCursor("insertRow");
2289 
2290        // 3)Make sure JDBC ResultSet is positioned on insertRow
2291        if (!isOnInsertRow) {
2292            throw newSQLException(SQLState.CURSOR_NOT_POSITIONED_ON_INSERT_ROW);
2293        }
2294 
2295        // 4)Make sure underneath language resultset is not closed
2296        if (theResults.isClosed()) {
2297            throw Util.generateCsSQLException(SQLState.LANG_RESULT_SET_NOT_OPEN, "insertRow");
2298        }
2299    }
2300 
2301    
2302    /**
2303         * JDBC 2.0
2304         * 
2305         * Give a nullable column a null value.
2306         * 
2307         * The updateXXX() methods are used to update column values in the current
2308         * row, or the insert row. The updateXXX() methods do not update the
2309         * underlying database, instead the updateRow() or insertRow() methods are
2310         * called to update the database.
2311         * 
2312         * @param columnIndex
2313         *            the first column is 1, the second is 2, ...
2314         * @exception SQLException
2315         *                if a database-access error occurs
2316         */
2317        public void updateNull(int columnIndex) throws SQLException {
2318                try {
2319                        getDVDforColumnToBeUpdated(columnIndex, "updateNull").setToNull();
2320                } catch (StandardException t) {
2321                        throw noStateChangeException(t);
2322                }
2323        }
2324 
2325        /**
2326         * JDBC 2.0
2327         *
2328         * Update a column with a boolean value.
2329         *
2330         * The updateXXX() methods are used to update column values in the current
2331         * row, or the insert row. The updateXXX() methods do not update the
2332         * underlying database, instead the updateRow() or insertRow() methods are
2333         * called to update the database.
2334         *
2335         * @param columnIndex
2336         *            the first column is 1, the second is 2, ...
2337         * @param x
2338         *            the new column value
2339         * @exception SQLException
2340         *                if a database-access error occurs
2341         */
2342        public void updateBoolean(int columnIndex, boolean x) throws SQLException {
2343                try {
2344                        getDVDforColumnToBeUpdated(columnIndex, "updateBoolean").setValue(x);
2345                } catch (StandardException t) {
2346                        throw noStateChangeException(t);
2347                }
2348        }
2349 
2350        /**
2351         * JDBC 2.0
2352         *
2353         * Update a column with a byte value.
2354         *
2355         * The updateXXX() methods are used to update column values in the current
2356         * row, or the insert row. The updateXXX() methods do not update the
2357         * underlying database, instead the updateRow() or insertRow() methods are
2358         * called to update the database.
2359         *
2360         * @param columnIndex
2361         *            the first column is 1, the second is 2, ...
2362         * @param x
2363         *            the new column value
2364         * @exception SQLException
2365         *                if a database-access error occurs
2366         */
2367        public void updateByte(int columnIndex, byte x) throws SQLException {
2368                try {
2369                        getDVDforColumnToBeUpdated(columnIndex, "updateByte").setValue(x);
2370                } catch (StandardException t) {
2371                        throw noStateChangeException(t);
2372                }
2373        }
2374 
2375        /**
2376         * JDBC 2.0
2377         *
2378         * Update a column with a short value.
2379         *
2380         * The updateXXX() methods are used to update column values in the current
2381         * row, or the insert row. The updateXXX() methods do not update the
2382         * underlying database, instead the updateRow() or insertRow() methods are
2383         * called to update the database.
2384         *
2385         * @param columnIndex
2386         *            the first column is 1, the second is 2, ...
2387         * @param x
2388         *            the new column value
2389         * @exception SQLException
2390         *                if a database-access error occurs
2391         */
2392        public void updateShort(int columnIndex, short x) throws SQLException {
2393                try {
2394                        getDVDforColumnToBeUpdated(columnIndex, "updateShort").setValue(x);
2395                } catch (StandardException t) {
2396                        throw noStateChangeException(t);
2397                }
2398        }
2399 
2400        /**
2401         * JDBC 2.0
2402         *
2403         * Update a column with an integer value.
2404         *
2405         * The updateXXX() methods are used to update column values in the current
2406         * row, or the insert row. The updateXXX() methods do not update the
2407         * underlying database, instead the updateRow() or insertRow() methods are
2408         * called to update the database.
2409         *
2410         * @param columnIndex
2411         *            the first column is 1, the second is 2, ...
2412         * @param x
2413         *            the new column value
2414         * @exception SQLException
2415         *                if a database-access error occurs
2416         */
2417        public void updateInt(int columnIndex, int x) throws SQLException {
2418                try {
2419                        getDVDforColumnToBeUpdated(columnIndex, "updateInt").setValue(x);
2420                } catch (StandardException t) {
2421                        throw noStateChangeException(t);
2422                }
2423        }
2424 
2425        /**
2426         * JDBC 2.0
2427         *
2428         * Update a column with a long value.
2429         *
2430         * The updateXXX() methods are used to update column values in the current
2431         * row, or the insert row. The updateXXX() methods do not update the
2432         * underlying database, instead the updateRow() or insertRow() methods are
2433         * called to update the database.
2434         *
2435         * @param columnIndex
2436         *            the first column is 1, the second is 2, ...
2437         * @param x
2438         *            the new column value
2439         * @exception SQLException
2440         *                if a database-access error occurs
2441         */
2442        public void updateLong(int columnIndex, long x) throws SQLException {
2443                try {
2444                        getDVDforColumnToBeUpdated(columnIndex, "updateLong").setValue(x);
2445                } catch (StandardException t) {
2446                        throw noStateChangeException(t);
2447                }
2448        }
2449 
2450        /**
2451         * JDBC 2.0
2452         *
2453         * Update a column with a float value.
2454         *
2455         * The updateXXX() methods are used to update column values in the current
2456         * row, or the insert row. The updateXXX() methods do not update the
2457         * underlying database, instead the updateRow() or insertRow() methods are
2458         * called to update the database.
2459         *
2460         * @param columnIndex
2461         *            the first column is 1, the second is 2, ...
2462         * @param x
2463         *            the new column value
2464         * @exception SQLException
2465         *                if a database-access error occurs
2466         */
2467        public void updateFloat(int columnIndex, float x) throws SQLException {
2468                try {
2469                        getDVDforColumnToBeUpdated(columnIndex, "updateFloat").setValue(x);
2470                } catch (StandardException t) {
2471                        throw noStateChangeException(t);
2472                }
2473        }
2474 
2475        /**
2476         * JDBC 2.0
2477         *
2478         * Update a column with a Double value.
2479         *
2480         * The updateXXX() methods are used to update column values in the current
2481         * row, or the insert row. The updateXXX() methods do not update the
2482         * underlying database, instead the updateRow() or insertRow() methods are
2483         * called to update the database.
2484         * 
2485         * @param columnIndex
2486         *            the first column is 1, the second is 2, ...
2487         * @param x
2488         *            the new column value
2489         * @exception SQLException
2490         *                if a database-access error occurs
2491         */
2492        public void updateDouble(int columnIndex, double x) throws SQLException {
2493                try {
2494                        getDVDforColumnToBeUpdated(columnIndex, "updateDouble").setValue(x);
2495                } catch (StandardException t) {
2496                        throw noStateChangeException(t);
2497                }
2498        }
2499 
2500        /**
2501         * JDBC 2.0
2502         * 
2503         * Update a column with a String value.
2504         * 
2505         * The updateXXX() methods are used to update column values in the current
2506         * row, or the insert row. The updateXXX() methods do not update the
2507         * underlying database, instead the updateRow() or insertRow() methods are
2508         * called to update the database.
2509         * 
2510         * @param columnIndex
2511         *            the first column is 1, the second is 2, ...
2512         * @param x
2513         *            the new column value
2514         * @exception SQLException
2515         *                if a database-access error occurs
2516         */
2517        public void updateString(int columnIndex, String x) throws SQLException {
2518                try {
2519                        getDVDforColumnToBeUpdated(columnIndex, "updateString").setValue(x);
2520                } catch (StandardException t) {
2521                        throw noStateChangeException(t);
2522                }
2523        }
2524 
2525        /**
2526         * JDBC 2.0
2527         * 
2528         * Update a column with a byte array value.
2529         * 
2530         * The updateXXX() methods are used to update column values in the current
2531         * row, or the insert row. The updateXXX() methods do not update the
2532         * underlying database, instead the updateRow() or insertRow() methods are
2533         * called to update the database.
2534         * 
2535         * @param columnIndex
2536         *            the first column is 1, the second is 2, ...
2537         * @param x
2538         *            the new column value
2539         * @exception SQLException
2540         *                if a database-access error occurs
2541         */
2542        public void updateBytes(int columnIndex, byte x[]) throws SQLException {
2543                try {
2544                        getDVDforColumnToBeUpdated(columnIndex, "updateBytes").setValue(x);
2545                } catch (StandardException t) {
2546                        throw noStateChangeException(t);
2547                }
2548        }
2549 
2550        /**
2551         * JDBC 2.0
2552         *
2553         * Update a column with a Date value.
2554         *
2555         * The updateXXX() methods are used to update column values in the current
2556         * row, or the insert row. The updateXXX() methods do not update the
2557         * underlying database, instead the updateRow() or insertRow() methods are
2558         * called to update the database.
2559         *
2560         * @param columnIndex
2561         *            the first column is 1, the second is 2, ...
2562         * @param x
2563         *            the new column value
2564         * @exception SQLException
2565         *                if a database-access error occurs
2566         */
2567        public void updateDate(int columnIndex, java.sql.Date x)
2568                        throws SQLException {
2569                try {
2570                        getDVDforColumnToBeUpdated(columnIndex, "updateDate").setValue(x);
2571                } catch (StandardException t) {
2572                        throw noStateChangeException(t);
2573                }
2574        }
2575 
2576        /**
2577         * JDBC 2.0
2578         *
2579         * Update a column with a Time value.
2580         *
2581         * The updateXXX() methods are used to update column values in the current
2582         * row, or the insert row. The updateXXX() methods do not update the
2583         * underlying database, instead the updateRow() or insertRow() methods are
2584         * called to update the database.
2585         *
2586         * @param columnIndex
2587         *            the first column is 1, the second is 2, ...
2588         * @param x
2589         *            the new column value
2590         * @exception SQLException
2591         *                if a database-access error occurs
2592         */
2593        public void updateTime(int columnIndex, java.sql.Time x)
2594                        throws SQLException {
2595                try {
2596                        getDVDforColumnToBeUpdated(columnIndex, "updateTime").setValue(x);
2597                } catch (StandardException t) {
2598                        throw noStateChangeException(t);
2599                }
2600        }
2601 
2602        /**
2603         * JDBC 2.0
2604         *
2605         * Update a column with a Timestamp value.
2606         *
2607         * The updateXXX() methods are used to update column values in the current
2608         * row, or the insert row. The updateXXX() methods do not update the
2609         * underlying database, instead the updateRow() or insertRow() methods are
2610         * called to update the database.
2611         *
2612         * @param columnIndex
2613         *            the first column is 1, the second is 2, ...
2614         * @param x
2615         *            the new column value
2616         * @exception SQLException
2617         *                if a database-access error occurs
2618         */
2619        public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
2620                        throws SQLException {
2621                try {
2622                        getDVDforColumnToBeUpdated(columnIndex, "updateTimestamp").setValue(x);
2623                } catch (StandardException t) {
2624                        throw noStateChangeException(t);
2625                }
2626        }
2627 
2628        /**
2629         * JDBC 2.0
2630         *
2631         * Update a column with an ascii stream value.
2632         *
2633         * The updateXXX() methods are used to update column values in the current
2634         * row, or the insert row. The updateXXX() methods do not update the
2635         * underlying database, instead the updateRow() or insertRow() methods are
2636         * called to update the database.
2637         *
2638         * @param columnIndex
2639         *            the first column is 1, the second is 2, ...
2640         * @param x
2641         *            the new column value
2642         * @param length
2643         *            the length of the stream
2644         * @exception SQLException
2645         *                if a database-access error occurs
2646         */
2647        public void updateAsciiStream(int columnIndex, java.io.InputStream x,
2648                        int length) throws SQLException {
2649                checksBeforeUpdateXXX("updateAsciiStream", columnIndex);
2650 
2651                int colType = getColumnType(columnIndex);
2652                switch (colType) {
2653                        case Types.CHAR:
2654                        case Types.VARCHAR:
2655                        case Types.LONGVARCHAR:
2656                        case Types.CLOB:
2657                                break;
2658                        default:
2659                                throw dataTypeConversion(columnIndex, "java.io.InputStream");
2660                }
2661 
2662                java.io.Reader r = null;
2663                if (x != null)
2664                {
2665                        try {
2666                                r = new java.io.InputStreamReader(x, "ISO-8859-1");
2667                        } catch (java.io.UnsupportedEncodingException uee) {
2668                                throw new SQLException(uee.getMessage());
2669                        }
2670                }
2671                updateCharacterStream(columnIndex, r, length);
2672        }
2673 
2674        /**
2675         * JDBC 2.0
2676         *
2677         * Update a column with a binary stream value.
2678         *
2679         * The updateXXX() methods are used to update column values in the current
2680         * row, or the insert row. The updateXXX() methods do not update the
2681         * underlying database, instead the updateRow() or insertRow() methods are
2682         * called to update the database.
2683         *
2684         * @param columnIndex
2685         *            the first column is 1, the second is 2, ...
2686         * @param x
2687         *            the new column value
2688         * @param length
2689         *            the length of the stream
2690         * @exception SQLException
2691         *                if a database-access error occurs
2692         */
2693        public void updateBinaryStream(int columnIndex, java.io.InputStream x,
2694                        int length) throws SQLException {
2695                checksBeforeUpdateXXX("updateBinaryStream", columnIndex);
2696                int colType = getColumnType(columnIndex);
2697                switch (colType) {
2698                        case Types.BINARY:
2699                        case Types.VARBINARY:
2700                        case Types.LONGVARBINARY:
2701                        case Types.BLOB:
2702                                break;
2703                        default:
2704                                throw dataTypeConversion(columnIndex, "java.io.InputStream");
2705                }
2706 
2707                if (x == null)
2708                {
2709                        updateNull(columnIndex);
2710                        return;
2711                }
2712 
2713                updateBinaryStreamInternal(columnIndex, x, length,"updateBinaryStream");
2714        }
2715 
2716        private void updateBinaryStreamInternal(int columnIndex,
2717                                                java.io.InputStream x, long length, String updateMethodName)
2718            throws SQLException
2719        {
2720        if (length < 0)
2721            throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
2722        
2723        // max number of bytes that can be set to be inserted 
2724        // in Derby is 2Gb-1 (ie Integer.MAX_VALUE). 
2725        // (e.g into a blob column).
2726        if (length > Integer.MAX_VALUE ) {
2727            throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
2728                    getColumnSQLType(columnIndex));
2729        }
2730        
2731        try {
2732                        getDVDforColumnToBeUpdated(columnIndex, updateMethodName).setValue(
2733                    new RawToBinaryFormatStream(x, (int) length), (int) length);
2734                } catch (StandardException t) {
2735                        throw noStateChangeException(t);
2736                }
2737        }
2738 
2739        /**
2740         * JDBC 2.0
2741         * 
2742         * Update a column with a character stream value.
2743         * 
2744         * The updateXXX() methods are used to update column values in the current
2745         * row, or the insert row. The updateXXX() methods do not update the
2746         * underlying database, instead the updateRow() or insertRow() methods are
2747         * called to update the database.
2748         * 
2749         * @param columnIndex
2750         *            the first column is 1, the second is 2, ...
2751         * @param x
2752         *            the new column value
2753         * @param length
2754         *            the length of the stream
2755         * @exception SQLException
2756         *                if a database-access error occurs
2757         */
2758        public void updateCharacterStream(int columnIndex, java.io.Reader x,
2759                        int length) throws SQLException {
2760                //If the column type is the right datatype, this method will eventually call getDVDforColumnToBeUpdated which will check for
2761                //the read only resultset. But for other datatypes, we want to catch if this updateCharacterStream is being issued
2762                //against a read only resultset. And that is the reason for call to checksBeforeUpdateXXX here.
2763                checksBeforeUpdateXXX("updateCharacterStream", columnIndex);
2764                int colType = getColumnType(columnIndex);
2765                switch (colType) {
2766                        case Types.CHAR:
2767                        case Types.VARCHAR:
2768                        case Types.LONGVARCHAR:
2769                        case Types.CLOB:
2770                                break;
2771                        default:
2772                                throw dataTypeConversion(columnIndex, "java.io.Reader");
2773                }
2774                updateCharacterStreamInternal(columnIndex, x, length, "updateCharacterStream");
2775        }
2776 
2777    private void updateCharacterStreamInternal(int columnIndex,
2778                                                java.io.Reader reader, long length, String updateMethodName)
2779            throws SQLException
2780        {
2781                try {
2782 
2783            if (reader == null)
2784            {
2785                updateNull(columnIndex);
2786                return;
2787            }
2788            
2789            // check for -ve length here 
2790            if (length < 0) 
2791                throw newSQLException(SQLState.NEGATIVE_STREAM_LENGTH);
2792 
2793            // max number of characters that can be set to be inserted 
2794            // in Derby is 2Gb-1 (ie Integer.MAX_VALUE). 
2795            // (e.g into a CLOB column).
2796            if (length > Integer.MAX_VALUE ) {
2797                throw newSQLException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE,
2798                        getColumnSQLType(columnIndex));
2799            } 
2800           
2801            // length is +ve. at this point, all checks for negative
2802            // length has already been done
2803            int usableLength = (int) length;
2804            int truncationLength = 0;
2805 
2806            // Currently long varchar does not allow for truncation of
2807            // trailing blanks.  For char and varchar types, current mechanism 
2808            // of materializing when using streams seems fine given their max
2809            // limits. This change is fix for DERBY-352: Insert of clobs using
2810            // streams should not materialize the entire stream into memory
2811            // In case of clobs, the truncation of trailing blanks is
2812            // factored in when reading from the stream without materializing
2813            // the entire stream, and so the special casing for clob below.
2814            if (getColumnType(columnIndex) == Types.CLOB) {
2815                // Need column width to figure out if truncation is
2816                // needed
2817                int colWidth = resultDescription.getColumnDescriptor(
2818                        columnIndex).getType().getMaximumWidth();
2819 
2820                // It is possible that the length of the stream passed
2821                // in is greater than the column width, in which case the data
2822                // from the stream needs to be truncated.
2823                // usableLength is the length of the data from stream
2824                // that can be used which is min(colWidth,length) provided
2825                // length - colWidth has trailing blanks only
2826                if (usableLength > colWidth) {                   
2827                    truncationLength = usableLength - colWidth;
2828                    usableLength = colWidth;
2829                }
2830            }
2831 
2832            ReaderToUTF8Stream utfIn = new ReaderToUTF8Stream(
2833                    reader, usableLength, truncationLength);
2834            
2835            getDVDforColumnToBeUpdated(columnIndex, updateMethodName).setValue(
2836                    utfIn, (int) usableLength);
2837        } catch (StandardException t) {
2838            throw noStateChangeException(t);
2839        }
2840        }
2841 
2842        /**
2843         * JDBC 2.0
2844         *
2845         * Update a column with an Object value.
2846         *
2847         * The updateXXX() methods are used to update column values in the current
2848         * row, or the insert row. The updateXXX() methods do not update the
2849         * underlying database, instead the updateRow() or insertRow() methods are
2850         * called to update the database.
2851         *
2852         * @param columnIndex
2853         *            the first column is 1, the second is 2, ...
2854         * @param x
2855         *            the new column value
2856         * @param scale
2857         *            For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
2858         *            this is the number of digits after the decimal. For all other
2859         *            types this value will be ignored.
2860         * @exception SQLException
2861         *                if a database-access error occurs
2862         */
2863        public void updateObject(int columnIndex, Object x, int scale)
2864                        throws SQLException {
2865                updateObject(columnIndex, x);
2866                /*
2867                * If the parameter type is DECIMAL or NUMERIC, then
2868                * we need to set them to the passed scale.
2869                */
2870                int colType = getColumnType(columnIndex);
2871                if ((colType == Types.DECIMAL) || (colType == Types.NUMERIC)) {
2872                        if (scale < 0)
2873                                throw newSQLException(SQLState.BAD_SCALE_VALUE, new Integer(scale));
2874 
2875                        try {
2876                                DataValueDescriptor value = updateRow.getColumn(columnIndex);
2877 
2878                                int origvaluelen = value.getLength();
2879                                ((VariableSizeDataValue)
2880                                                value).setWidth(VariableSizeDataValue.IGNORE_PRECISION,
2881                                                        scale,
2882                                                        false);
2883 
2884                        } catch (StandardException t) {
2885                                throw EmbedResultSet.noStateChangeException(t);
2886                        }
2887                }
2888        }
2889 
2890        /**
2891         * JDBC 2.0
2892         *
2893         * Update a column with an Object value.
2894         *
2895         * The updateXXX() methods are used to update column values in the current
2896         * row, or the insert row. The updateXXX() methods do not update the
2897         * underlying database, instead the updateRow() or insertRow() methods are
2898         * called to update the database.
2899         *
2900         * @param columnIndex
2901         *            the first column is 1, the second is 2, ...
2902         * @param x
2903         *            the new column value
2904         * @exception SQLException
2905         *                if a database-access error occurs
2906         */
2907        public void updateObject(int columnIndex, Object x) throws SQLException {
2908                checksBeforeUpdateXXX("updateObject", columnIndex);
2909                int colType = getColumnType(columnIndex);
2910                if (colType == org.apache.derby.iapi.reference.JDBC20Translation.SQL_TYPES_JAVA_OBJECT) {
2911                        try {
2912                                ((UserDataValue) getDVDforColumnToBeUpdated(columnIndex, "updateObject")).setValue(x);
2913                                return;
2914                        } catch (StandardException t) {
2915                                throw noStateChangeException(t);
2916                        }
2917                }
2918 
2919                if (x == null) {
2920                        updateNull(columnIndex);
2921                        return;
2922                }
2923 
2924                if (x instanceof String) {
2925                        updateString(columnIndex, (String) x);
2926                        return;
2927                }
2928 
2929                if (x instanceof Boolean) {
2930                        updateBoolean(columnIndex, ((Boolean) x).booleanValue());
2931                        return;
2932                }
2933 
2934                if (x instanceof Short) {
2935                        updateShort(columnIndex, ((Short) x).shortValue());
2936                        return;
2937                }
2938 
2939                if (x instanceof Integer) {
2940                        updateInt(columnIndex, ((Integer) x).intValue());
2941                        return;
2942                }
2943 
2944                if (x instanceof Long) {
2945                        updateLong(columnIndex, ((Long) x).longValue());
2946                        return;
2947                }
2948 
2949                if (x instanceof Float) {
2950                        updateFloat(columnIndex, ((Float) x).floatValue());
2951                        return;
2952                }
2953 
2954                if (x instanceof Double) {
2955                        updateDouble(columnIndex, ((Double) x).doubleValue());
2956                        return;
2957                }
2958 
2959                if (x instanceof byte[]) {
2960                        updateBytes(columnIndex, (byte[]) x);
2961                        return;
2962                }
2963 
2964                if (x instanceof Date) {
2965                        updateDate(columnIndex, (Date) x);
2966                        return;
2967                }
2968 
2969                if (x instanceof Time) {
2970                        updateTime(columnIndex, (Time) x);
2971                        return;
2972                }
2973 
2974                if (x instanceof Timestamp) {
2975                        updateTimestamp(columnIndex, (Timestamp) x);
2976                        return;
2977                }
2978 
2979                if (x instanceof Blob) {
2980                        updateBlob(columnIndex, (Blob) x);
2981                        return;
2982                }
2983 
2984                if (x instanceof Clob) {
2985                        updateClob(columnIndex, (Clob) x);
2986                        return;
2987                }
2988 
2989                throw dataTypeConversion(columnIndex, x.getClass().getName());
2990        }
2991 
2992        /**
2993         * JDBC 2.0
2994         * 
2995         * Update a column with a null value.
2996         * 
2997         * The updateXXX() methods are used to update column values in the current
2998         * row, or the insert row. The updateXXX() methods do not update the
2999         * underlying database, instead the updateRow() or insertRow() methods are
3000         * called to update the database.
3001         * 
3002         * @param columnName
3003         *            the name of the column
3004         * @exception SQLException
3005         *                if a database-access error occurs
3006         */
3007        public void updateNull(String columnName) throws SQLException {
3008                checkIfClosed("updateNull");
3009                updateNull(findColumnName(columnName));
3010        }
3011 
3012        /**
3013         * JDBC 2.0
3014         * 
3015         * Update a column with a boolean value.
3016         * 
3017         * The updateXXX() methods are used to update column values in the current
3018         * row, or the insert row. The updateXXX() methods do not update the
3019         * underlying database, instead the updateRow() or insertRow() methods are
3020         * called to update the database.
3021         * 
3022         * @param columnName
3023         *            the name of the column
3024         * @param x
3025         *            the new column value
3026         * @exception SQLException
3027         *                if a database-access error occurs
3028         */
3029        public void updateBoolean(String columnName, boolean x) throws SQLException {
3030                checkIfClosed("updateBoolean");
3031                updateBoolean(findColumnName(columnName), x);
3032        }
3033 
3034        /**
3035         * JDBC 2.0
3036         * 
3037         * Update a column with a byte value.
3038         * 
3039         * The updateXXX() methods are used to update column values in the current
3040         * row, or the insert row. The updateXXX() methods do not update the
3041         * underlying database, instead the updateRow() or insertRow() methods are
3042         * called to update the database.
3043         * 
3044         * @param columnName
3045         *            the name of the column
3046         * @param x
3047         *            the new column value
3048         * @exception SQLException
3049         *                if a database-access error occurs
3050         */
3051        public void updateByte(String columnName, byte x) throws SQLException {
3052                checkIfClosed("updateByte");
3053                updateByte(findColumnName(columnName), x);
3054        }
3055 
3056        /**
3057         * JDBC 2.0
3058         * 
3059         * Update a column with a short value.
3060         * 
3061         * The updateXXX() methods are used to update column values in the current
3062         * row, or the insert row. The updateXXX() methods do not update the
3063         * underlying database, instead the updateRow() or insertRow() methods are
3064         * called to update the database.
3065         * 
3066         * @param columnName
3067         *            the name of the column
3068         * @param x
3069         *            the new column value
3070         * @exception SQLException
3071         *                if a database-access error occurs
3072         */
3073        public void updateShort(String columnName, short x) throws SQLException {
3074                checkIfClosed("updateShort");
3075                updateShort(findColumnName(columnName), x);
3076        }
3077 
3078        /**
3079         * JDBC 2.0
3080         * 
3081         * Update a column with an integer value.
3082         * 
3083         * The updateXXX() methods are used to update column values in the current
3084         * row, or the insert row. The updateXXX() methods do not update the
3085         * underlying database, instead the updateRow() or insertRow() methods are
3086         * called to update the database.
3087         * 
3088         * @param columnName
3089         *            the name of the column
3090         * @param x
3091         *            the new column value
3092         * @exception SQLException
3093         *                if a database-access error occurs
3094         */
3095        public void updateInt(String columnName, int x) throws SQLException {
3096                checkIfClosed("updateInt");
3097                updateInt(findColumnName(columnName), x);
3098        }
3099 
3100        /**
3101         * JDBC 2.0
3102         * 
3103         * Update a column with a long value.
3104         * 
3105         * The updateXXX() methods are used to update column values in the current
3106         * row, or the insert row. The updateXXX() methods do not update the
3107         * underlying database, instead the updateRow() or insertRow() methods are
3108         * called to update the database.
3109         * 
3110         * @param columnName
3111         *            the name of the column
3112         * @param x
3113         *            the new column value
3114         * @exception SQLException
3115         *                if a database-access error occurs
3116         */
3117        public void updateLong(String columnName, long x) throws SQLException {
3118                checkIfClosed("updateLong");
3119                updateLong(findColumnName(columnName), x);
3120        }
3121 
3122        /**
3123         * JDBC 2.0
3124         * 
3125         * Update a column with a float value.
3126         * 
3127         * The updateXXX() methods are used to update column values in the current
3128         * row, or the insert row. The updateXXX() methods do not update the
3129         * underlying database, instead the updateRow() or insertRow() methods are
3130         * called to update the database.
3131         * 
3132         * @param columnName
3133         *            the name of the column
3134         * @param x
3135         *            the new column value
3136         * @exception SQLException
3137         *                if a database-access error occurs
3138         */
3139        public void updateFloat(String columnName, float x) throws SQLException {
3140                checkIfClosed("updateFloat");
3141                updateFloat(findColumnName(columnName), x);
3142        }
3143 
3144        /**
3145         * JDBC 2.0
3146         * 
3147         * Update a column with a double value.
3148         * 
3149         * The updateXXX() methods are used to update column values in the current
3150         * row, or the insert row. The updateXXX() methods do not update the
3151         * underlying database, instead the updateRow() or insertRow() methods are
3152         * called to update the database.
3153         * 
3154         * @param columnName
3155         *            the name of the column
3156         * @param x
3157         *            the new column value
3158         * @exception SQLException
3159         *                if a database-access error occurs
3160         */
3161        public void updateDouble(String columnName, double x) throws SQLException {
3162                checkIfClosed("updateDouble");
3163                updateDouble(findColumnName(columnName), x);
3164        }
3165 
3166        /**
3167         * JDBC 2.0
3168         * 
3169         * Update a column with a String value.
3170         * 
3171         * The updateXXX() methods are used to update column values in the current
3172         * row, or the insert row. The updateXXX() methods do not update the
3173         * underlying database, instead the updateRow() or insertRow() methods are
3174         * called to update the database.
3175         * 
3176         * @param columnName
3177         *            the name of the column
3178         * @param x
3179         *            the new column value
3180         * @exception SQLException
3181         *                if a database-access error occurs
3182         */
3183        public void updateString(String columnName, String x) throws SQLException {
3184                checkIfClosed("updateString");
3185                updateString(findColumnName(columnName), x);
3186        }
3187 
3188        /**
3189         * JDBC 2.0
3190         * 
3191         * Update a column with a byte array value.
3192         * 
3193         * The updateXXX() methods are used to update column values in the current
3194         * row, or the insert row. The updateXXX() methods do not update the
3195         * underlying database, instead the updateRow() or insertRow() methods are
3196         * called to update the database.
3197         * 
3198         * @param columnName
3199         *            the name of the column
3200         * @param x
3201         *            the new column value
3202         * @exception SQLException
3203         *                if a database-access error occurs
3204         */
3205        public void updateBytes(String columnName, byte x[]) throws SQLException {
3206                checkIfClosed("updateBytes");
3207                updateBytes(findColumnName(columnName), x);
3208        }
3209 
3210        /**
3211         * JDBC 2.0
3212         * 
3213         * Update a column with a Date value.
3214         * 
3215         * The updateXXX() methods are used to update column values in the current
3216         * row, or the insert row. The updateXXX() methods do not update the
3217         * underlying database, instead the updateRow() or insertRow() methods are
3218         * called to update the database.
3219         * 
3220         * @param columnName
3221         *            the name of the column
3222         * @param x
3223         *            the new column value
3224         * @exception SQLException
3225         *                if a database-access error occurs
3226         */
3227        public void updateDate(String columnName, java.sql.Date x)
3228                        throws SQLException {
3229                checkIfClosed("updateDate");
3230                updateDate(findColumnName(columnName), x);
3231        }
3232 
3233        /**
3234         * JDBC 2.0
3235         * 
3236         * Update a column with a Time value.
3237         * 
3238         * The updateXXX() methods are used to update column values in the current
3239         * row, or the insert row. The updateXXX() methods do not update the
3240         * underlying database, instead the updateRow() or insertRow() methods are
3241         * called to update the database.
3242         * 
3243         * @param columnName
3244         *            the name of the column
3245         * @param x
3246         *            the new column value
3247         * @exception SQLException
3248         *                if a database-access error occurs
3249         */
3250        public void updateTime(String columnName, java.sql.Time x)
3251                        throws SQLException {
3252                checkIfClosed("updateTime");
3253                updateTime(findColumnName(columnName), x);
3254        }
3255 
3256        /**
3257         * JDBC 2.0
3258         * 
3259         * Update a column with a Timestamp value.
3260         * 
3261         * The updateXXX() methods are used to update column values in the current
3262         * row, or the insert row. The updateXXX() methods do not update the
3263         * underlying database, instead the updateRow() or insertRow() methods are
3264         * called to update the database.
3265         * 
3266         * @param columnName
3267         *            the name of the column
3268         * @param x
3269         *            the new column value
3270         * @exception SQLException
3271         *                if a database-access error occurs
3272         */
3273        public void updateTimestamp(String columnName, java.sql.Timestamp x)
3274                        throws SQLException {
3275                checkIfClosed("updateTimestamp");
3276                updateTimestamp(findColumnName(columnName), x);
3277        }
3278 
3279        /**
3280         * JDBC 2.0
3281         * 
3282         * Update a column with an ascii stream value.
3283         * 
3284         * The updateXXX() methods are used to update column values in the current
3285         * row, or the insert row. The updateXXX() methods do not update the
3286         * underlying database, instead the updateRow() or insertRow() methods are
3287         * called to update the database.
3288         * 
3289         * @param columnName
3290         *            the name of the column
3291         * @param x
3292         *            the new column value
3293         * @param length
3294         *            of the stream
3295         * @exception SQLException
3296         *                if a database-access error occurs
3297         */
3298        public void updateAsciiStream(String columnName, java.io.InputStream x,
3299                        int length) throws SQLException {
3300                checkIfClosed("updateAsciiStream");
3301                updateAsciiStream(findColumnName(columnName), x, length);
3302        }
3303 
3304        /**
3305         * JDBC 2.0
3306         * 
3307         * Update a column with a binary stream value.
3308         * 
3309         * The updateXXX() methods are used to update column values in the current
3310         * row, or the insert row. The updateXXX() methods do not update the
3311         * underlying database, instead the updateRow() or insertRow() methods are
3312         * called to update the database.
3313         * 
3314         * @param columnName
3315         *            the name of the column
3316         * @param x
3317         *            the new column value
3318         * @param length
3319         *            of the stream
3320         * @exception SQLException
3321         *                if a database-access error occurs
3322         */
3323        public void updateBinaryStream(String columnName, java.io.InputStream x,
3324                        int length) throws SQLException {
3325                checkIfClosed("updateBinaryStream");
3326                updateBinaryStream(findColumnName(columnName), x, length);
3327        }
3328 
3329        /**
3330         * JDBC 2.0
3331         * 
3332         * Update a column with a character stream value.
3333         * 
3334         * The updateXXX() methods are used to update column values in the current
3335         * row, or the insert row. The updateXXX() methods do not update the
3336         * underlying database, instead the updateRow() or insertRow() methods are
3337         * called to update the database.
3338         * 
3339         * @param columnName
3340         *            the name of the column
3341         * @param reader
3342         *            the new column value
3343         * @param length
3344         *            length of the stream
3345         * @exception SQLException
3346         *                if a database-access error occurs
3347         */
3348        public void updateCharacterStream(String columnName, java.io.Reader reader,
3349                        int length) throws SQLException {
3350                checkIfClosed("updateCharacterStream");
3351                updateCharacterStream(findColumnName(columnName), reader, length);
3352        }
3353 
3354        /**
3355         * JDBC 2.0
3356         *
3357         * Update a column with an Object value.
3358         *
3359         * The updateXXX() methods are used to update column values in the
3360         * current row, or the insert row.  The updateXXX() methods do not
3361         * update the underlying database, instead the updateRow() or insertRow()
3362         * methods are called to update the database.
3363         *
3364         * @param columnName the name of the column
3365         * @param x the new column value
3366         * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
3367         *  this is the number of digits after the decimal.  For all other
3368         *  types this value will be ignored.
3369         * @exception SQLException if a database-access error occurs
3370         */
3371        public void updateObject(String columnName, Object x, int scale)
3372      throws SQLException {
3373                checkIfClosed("updateObject");
3374                updateObject(findColumnName(columnName), x, scale);
3375        }
3376 
3377        /**
3378         * JDBC 2.0
3379         *
3380         * Update a column with an Object value.
3381         *
3382         * The updateXXX() methods are used to update column values in the current
3383         * row, or the insert row. The updateXXX() methods do not update the
3384         * underlying database, instead the updateRow() or insertRow() methods are
3385         * called to update the database.
3386         *
3387         * @param columnName
3388         *            the name of the column
3389         * @param x
3390         *            the new column value
3391         * @exception SQLException
3392         *                if a database-access error occurs
3393         */
3394        public void updateObject(String columnName, Object x) throws SQLException {
3395                checkIfClosed("updateObject");
3396                updateObject(findColumnName(columnName), x);
3397        }
3398 
3399        /**
3400         * JDBC 2.0
3401         * 
3402         * Insert the contents of the insert row into the result set and the
3403         * database. Must be on the insert row when this method is called.
3404         * 
3405         * @exception SQLException
3406         *                if a database-access error occurs, if called when not on
3407         *                the insert row, or if all non-nullable columns in the
3408         *                insert row have not been given a value
3409         */
3410        public void insertRow() throws SQLException {
3411        synchronized (getConnectionSynchronization()) {
3412            checksBeforeInsert();
3413            setupContextStack();
3414            LanguageConnectionContext lcc = null;
3415            StatementContext statementContext = null;
3416            try {
3417                /*
3418                 * construct the insert statement
3419                 *
3420                 * If no values have been supplied for a column, it will be set 
3421                 * to the column's default value, if any. 
3422                 * If no default value had been defined, the default value of a 
3423                 * nullable column is set to NULL.
3424                 */
3425 
3426                boolean foundOneColumnAlready = false;
3427                StringBuffer insertSQL = new StringBuffer("INSERT INTO ");
3428                StringBuffer valuesSQL = new StringBuffer("VALUES (");
3429                CursorActivation activation = getEmbedConnection().
3430                        getLanguageConnection().lookupCursorActivation(getCursorName());
3431 
3432                ExecCursorTableReference targetTable = 
3433                        activation.getPreparedStatement().getTargetTable();
3434                // got the underlying (schema.)table name
3435                insertSQL.append(getFullBaseTableName(targetTable));
3436                ResultDescription rd = theResults.getResultDescription();
3437 
3438                insertSQL.append(" (");
3439                // in this for loop we are constructing list of column-names 
3440                // and values (?) ,... part of the insert sql
3441                for (int i=1; i<=rd.getColumnCount(); i++) { 
3442                    if (foundOneColumnAlready) {
3443                        insertSQL.append(",");
3444                        valuesSQL.append(",");
3445                    }
3446                    // using quotes around the column name 
3447                    // to preserve case sensitivity
3448                    insertSQL.append("\"" + 
3449                            rd.getColumnDescriptor(i).getName() + "\"");
3450                    if (columnGotUpdated[i-1]) { 
3451                        valuesSQL.append("?");
3452                    } else {
3453                        valuesSQL.append("DEFAULT");
3454                    }
3455                    foundOneColumnAlready = true;
3456                }
3457                insertSQL.append(") ");
3458                valuesSQL.append(") ");
3459                insertSQL.append(valuesSQL);
3460 
3461                lcc = getEmbedConnection().getLanguageConnection();
3462 
3463                // Context used for preparing, don't set any timeout (use 0)
3464                statementContext = lcc.pushStatementContext(
3465                        isAtomic, 
3466                        false, 
3467                        insertSQL.toString(), 
3468                        null, 
3469                        false, 
3470                        0L);
3471                org.apache.derby.iapi.sql.PreparedStatement ps = 
3472                        lcc.prepareInternalStatement(insertSQL.toString());
3473                Activation act = ps.getActivation(lcc, false);
3474 
3475                // in this for loop we are assigning values for parameters 
3476                //in sql constructed earlier VALUES (?, ..)
3477                for (int i=1, paramPosition=0; i<=rd.getColumnCount(); i++) { 
3478                    // if the column got updated, do following
3479                    if (columnGotUpdated[i-1]) {  
3480                        act.getParameterValueSet().
3481                                getParameterForSet(paramPosition++).
3482                                setValue(updateRow.getColumn(i));
3483                    }
3484                }
3485                // Don't see any timeout when inserting rows (use 0)
3486                //execute the insert
3487                org.apache.derby.iapi.sql.ResultSet rs = 
3488                        ps.execute(act, true, 0L); 
3489                rs.close();
3490                rs.finish();
3491 
3492                lcc.popStatementContext(statementContext, null);
3493            } catch (StandardException t) {
3494                throw closeOnTransactionError(t);
3495            } finally {
3496                restoreContextStack();
3497            }
3498        }
3499        }
3500 
3501    /**
3502     * JDBC 2.0
3503     *
3504     * Update the underlying database with the new contents of the
3505     * current row.  Cannot be called when on the insert row.
3506     *
3507     * @exception SQLException if a database-access error occurs, or
3508     * if called when on the insert row
3509     */
3510    public void updateRow() throws SQLException {
3511                        synchronized (getConnectionSynchronization()) {
3512        checksBeforeUpdateOrDelete("updateRow", -1);
3513        
3514        // Check that the cursor is not positioned on insertRow
3515        checkNotOnInsertRow();
3516        
3517        setupContextStack();
3518        LanguageConnectionContext lcc = null;
3519        StatementContext statementContext = null;
3520        try {
3521            if (currentRowHasBeenUpdated == false) //nothing got updated on this row 
3522                return; //nothing to do since no updates were made to this row
3523 
3524            //now construct the update where current of sql
3525            boolean foundOneColumnAlready = false;
3526            StringBuffer updateWhereCurrentOfSQL = new StringBuffer("UPDATE ");
3527            CursorActivation activation = getEmbedConnection().getLanguageConnection().lookupCursorActivation(getCursorName());
3528 
3529 
3530            ExecCursorTableReference targetTable = activation.getPreparedStatement().getTargetTable();
3531            updateWhereCurrentOfSQL.append(getFullBaseTableName(targetTable));//got the underlying (schema.)table name
3532            updateWhereCurrentOfSQL.append(" SET ");
3533            ResultDescription rd = theResults.getResultDescription();
3534 
3535            for (int i=1; i<=rd.getColumnCount(); i++) { //in this for loop we are constructing columnname=?,... part of the update sql
3536                if (columnGotUpdated[i-1]) { //if the column got updated, do following
3537                    if (foundOneColumnAlready)
3538                        updateWhereCurrentOfSQL.append(",");
3539                    //using quotes around the column name to preserve case sensitivity
3540                    updateWhereCurrentOfSQL.append("\"" + rd.getColumnDescriptor(i).getName() + "\"=?");
3541                    foundOneColumnAlready = true;
3542                }
3543            }
3544            //using quotes around the cursor name to preserve case sensitivity
3545            updateWhereCurrentOfSQL.append(" WHERE CURRENT OF \"" + getCursorName() + "\"");
3546            lcc = getEmbedConnection().getLanguageConnection();
3547 
3548            // Context used for preparing, don't set any timeout (use 0)
3549            statementContext = lcc.pushStatementContext(isAtomic, false, updateWhereCurrentOfSQL.toString(), null, false, 0L);
3550            org.apache.derby.iapi.sql.PreparedStatement ps = lcc.prepareInternalStatement(updateWhereCurrentOfSQL.toString());
3551            Activation act = ps.getActivation(lcc, false);
3552 
3553            //in this for loop we are assigning values for parameters in sql constructed earlier with columnname=?,... 
3554            for (int i=1, paramPosition=0; i<=rd.getColumnCount(); i++) { 
3555                if (columnGotUpdated[i-1])  //if the column got updated, do following
3556                    act.getParameterValueSet().getParameterForSet(paramPosition++).setValue(updateRow.getColumn(i));
3557            }
3558            // Don't set any timeout when updating rows (use 0)
3559            // Execute the update where current of sql.
3560            org.apache.derby.iapi.sql.ResultSet rs = ps.execute(act, true, 0L);
3561            SQLWarning w = act.getWarnings();
3562            if (w != null) {
3563                addWarning(w);
3564            }
3565            rs.close();
3566            rs.finish();
3567            //For forward only resultsets, after a update, the ResultSet will be positioned right before the next row.
3568            if (getType() == TYPE_FORWARD_ONLY) {
3569                currentRow.setRowArray(null);
3570            } else {
3571                movePosition(RELATIVE, 0, "relative");
3572            }
3573            lcc.popStatementContext(statementContext, null);
3574        } catch (StandardException t) {
3575            throw closeOnTransactionError(t);
3576        } finally {
3577            if (statementContext != null)
3578                lcc.popStatementContext(statementContext, null);
3579            restoreContextStack();
3580            initializeUpdateRowModifiers();
3581        }
3582                        }
3583    }
3584 
3585    /**
3586     * JDBC 2.0
3587     *
3588     * Delete the current row from the result set and the underlying
3589     * database.  Cannot be called when on the insert row.
3590     *
3591     * @exception SQLException if a database-access error occurs, or if
3592     * called when on the insert row.
3593     */
3594    public void deleteRow() throws SQLException {
3595        synchronized (getConnectionSynchronization()) {
3596            checksBeforeUpdateOrDelete("deleteRow", -1);
3597        
3598            // Check that the cursor is not positioned on insertRow
3599            checkNotOnInsertRow();
3600 
3601            setupContextStack();
3602            //now construct the delete where current of sql
3603            try {
3604                StringBuffer deleteWhereCurrentOfSQL = new StringBuffer("DELETE FROM ");
3605                CursorActivation activation = getEmbedConnection().getLanguageConnection().lookupCursorActivation(getCursorName());
3606                deleteWhereCurrentOfSQL.append(getFullBaseTableName(activation.getPreparedStatement().getTargetTable()));//get the underlying (schema.)table name
3607                //using quotes around the cursor name to preserve case sensitivity
3608                deleteWhereCurrentOfSQL.append(" WHERE CURRENT OF \"" + getCursorName() + "\"");
3609 
3610                LanguageConnectionContext lcc = getEmbedConnection().getLanguageConnection();
3611 
3612                // Context used for preparing, don't set any timeout (use 0)
3613                StatementContext statementContext = lcc.pushStatementContext(isAtomic, false, deleteWhereCurrentOfSQL.toString(), null, false, 0L);
3614                org.apache.derby.iapi.sql.PreparedStatement ps = lcc.prepareInternalStatement(deleteWhereCurrentOfSQL.toString());
3615                // Get activation, so that we can get the warning from it
3616                Activation act = ps.getActivation(lcc, false);
3617                // Don't set any timeout when deleting rows (use 0)
3618                //execute delete where current of sql
3619                org.apache.derby.iapi.sql.ResultSet rs = 
3620                        ps.execute(act, true, 0L);
3621                SQLWarning w = act.getWarnings();
3622                if (w != null) {
3623                    addWarning(w);
3624                }
3625                rs.close();
3626                rs.finish();
3627                //After a delete, the ResultSet will be positioned right before 
3628                //the next row.
3629                currentRow.setRowArray(null);
3630                lcc.popStatementContext(statementContext, null);
3631            } catch (StandardException t) {
3632                    throw closeOnTransactionError(t);
3633            } finally {
3634                restoreContextStack();
3635                initializeUpdateRowModifiers();
3636            }
3637        }
3638    }
3639 
3640        private String getFullBaseTableName(ExecCursorTableReference targetTable) {
3641                //using quotes to preserve case sensitivity
3642                if (targetTable.getSchemaName() != null)
3643                        return "\"" + targetTable.getSchemaName() + "\".\""
3644                                        + targetTable.getBaseName() + "\"";
3645                else
3646                        return "\"" + targetTable.getBaseName() + "\"";
3647        }
3648 
3649        /**
3650         * JDBC 2.0
3651         * 
3652         * Refresh the value of the current row with its current value in the
3653         * database. Cannot be called when on the insert row.
3654         * 
3655         * The refreshRow() method provides a way for an application to explicitly
3656         * tell the JDBC driver to refetch a row(s) from the database. An
3657         * application may want to call refreshRow() when caching or prefetching is
3658         * being done by the JDBC driver to fetch the latest value of a row from the
3659         * database. The JDBC driver may actually refresh multiple rows at once if
3660         * the fetch size is greater than one.
3661         * 
3662         * All values are refetched subject to the transaction isolation level and
3663         * cursor sensitivity. If refreshRow() is called after calling updateXXX(),
3664         * but before calling updateRow() then the updates made to the row are lost.
3665         * Calling refreshRow() frequently will likely slow performance.
3666         * 
3667         * @exception SQLException
3668         *                if a database-access error occurs, or if called when on
3669         *                the insert row.
3670         */
3671        public void refreshRow() throws SQLException {
3672                throw Util.notImplemented();
3673        }
3674 
3675    /**
3676     * JDBC 2.0
3677     *
3678     * The cancelRowUpdates() method may be called after calling an
3679     * updateXXX() method(s) and before calling updateRow() to rollback 
3680     * the updates made to a row.  If no updates have been made or 
3681     * updateRow() has already been called, then this method has no 
3682     * effect.
3683     *
3684     * @exception SQLException if a database-access error occurs, or if
3685     * called when on the insert row.
3686     *
3687     */
3688    public void cancelRowUpdates () throws SQLException {
3689        checksBeforeUpdateOrDelete("cancelRowUpdates", -1);
3690        
3691        checkNotOnInsertRow();
3692 
3693        initializeUpdateRowModifiers();        
3694    }
3695 
3696        /**
3697         * JDBC 2.0
3698         * 
3699         * Move to the insert row. The current cursor position is remembered while
3700         * the cursor is positioned on the insert row.
3701         * 
3702         * The insert row is a special row associated with an updatable result set.
3703         * It is essentially a buffer where a new row may be constructed by calling
3704         * the updateXXX() methods prior to inserting the row into the result set.
3705         * 
3706         * Only the updateXXX(), getXXX(), and insertRow() methods may be called
3707         * when the cursor is on the insert row. All of the columns in a result set
3708         * must be given a value each time this method is called before calling
3709         * insertRow(). UpdateXXX()must be called before getXXX() on a column.
3710         * 
3711         * @exception SQLException
3712         *                if a database-access error occurs, or the result set is
3713         *                not updatable
3714         */
3715        public void moveToInsertRow() throws SQLException {
3716                checkExecIfClosed("moveToInsertRow");
3717 
3718                // if not updatable resultset, then throw exception
3719                checkUpdatableCursor("moveToInsertRow");
3720 
3721                synchronized (getConnectionSynchronization()) {
3722                        try {
3723                                // initialize state corresponding to insertRow/updateRow impl.
3724                                initializeUpdateRowModifiers();
3725                                 isOnInsertRow = true;
3726                                
3727                                for (int i=1; i <= columnGotUpdated.length; i++) {
3728                                        updateRow.setColumn(i, 
3729                                                resultDescription.getColumnDescriptor(i).getType().getNull());
3730                                }
3731                        } catch (Throwable ex) {
3732                                handleException(ex);
3733                        }
3734                }
3735        }
3736 
3737        /**
3738         * JDBC 2.0
3739         * 
3740         * Move the cursor to the remembered cursor position, usually the current
3741         * row. Has no effect unless the cursor is on the insert row.
3742         * 
3743         * @exception SQLException
3744         *                if a database-access error occurs, or the result set is
3745         *                not updatable
3746         */
3747        public void moveToCurrentRow() throws SQLException {
3748                checkExecIfClosed("moveToCurrentRow");
3749 
3750                // if not updatable resultset, then throw exception
3751                checkUpdatableCursor("moveToCurrentRow");
3752 
3753                synchronized (getConnectionSynchronization()) {
3754                        try {
3755 
3756                                if (isOnInsertRow) {
3757                                        // initialize state corresponding to insertRow/updateRow impl.
3758                                        initializeUpdateRowModifiers();
3759 
3760                                        isOnInsertRow = false;
3761                                }
3762                        } catch (Throwable ex) {
3763                                handleException(ex);
3764                        }
3765                }
3766        }
3767 
3768    /**
3769         * JDBC 2.0
3770         * 
3771         * Get a BLOB column.
3772         * 
3773         * @param columnIndex the first column is 1, the second is 2, ...
3774         * @return an object representing a BLOB
3775         */
3776        public Blob getBlob(int columnIndex) throws SQLException {
3777 
3778                closeCurrentStream(); // closing currentStream does not depend on the
3779                // underlying connection. Do this outside of
3780                // the connection synchronization.
3781 
3782                checkIfClosed("getBlob"); // checking result set closure does not depend
3783                // on the underlying connection. Do this
3784                // outside of the connection synchronization.
3785 
3786                synchronized (getConnectionSynchronization()) {
3787                        int colType = getColumnType(columnIndex);
3788 
3789                        // DB2, only allow getBlob on a BLOB column.
3790                        if (colType != Types.BLOB)
3791                                throw dataTypeConversion("java.sql.Blob", columnIndex);
3792 
3793                        boolean pushStack = false;
3794                        try {
3795                                DataValueDescriptor dvd = getColumn(columnIndex);
3796 
3797                                if (wasNull = dvd.isNull())
3798                                        return null;
3799 
3800                                // should set up a context stack if we have a long column,
3801                                // since a blob may keep a pointer to a long column in the
3802                                // database
3803                                if (dvd.getStream() != null)
3804                                        pushStack = true;
3805 
3806                                if (pushStack)
3807                                        setupContextStack();
3808 
3809                                return new EmbedBlob(dvd, getEmbedConnection());
3810                        } catch (Throwable t) {
3811                                throw handleException(t);
3812                        } finally {
3813                                if (pushStack)
3814                                        restoreContextStack();
3815                        }
3816                }
3817        }
3818 
3819        /**
3820         * JDBC 2.0
3821         * 
3822         * Get a CLOB column.
3823         * 
3824         * @param columnIndex the first column is 1, the second is 2, ...
3825         * @return an object representing a CLOB
3826         */
3827        public final Clob getClob(int columnIndex) throws SQLException {
3828 
3829                closeCurrentStream(); // closing currentStream does not depend on the
3830                // underlying connection. Do this outside of
3831                // the connection synchronization.
3832 
3833                checkIfClosed("getClob"); // checking result set closure does not depend
3834                // on the underlying connection. Do this
3835                // outside of the connection synchronization.
3836 
3837                synchronized (getConnectionSynchronization()) {
3838                        int colType = getColumnType(columnIndex);
3839 
3840                        // DB2:, only allow getClob on a CLOB column.
3841                        if (colType != Types.CLOB)
3842                                throw dataTypeConversion("java.sql.Clob", columnIndex);
3843 
3844                        boolean pushStack = false;
3845                        try {
3846 
3847                                DataValueDescriptor dvd = getColumn(columnIndex);
3848 
3849                                if (wasNull = dvd.isNull())
3850                                        return null;
3851 
3852                                // should set up a context stack if we have a long column,
3853                                // since a blob may keep a pointer to a long column in the
3854                                // database
3855                                if (dvd.getStream() != null)
3856                                        pushStack = true;
3857 
3858                                if (pushStack)
3859                                        setupContextStack();
3860 
3861                                return new EmbedClob(dvd, getEmbedConnection());
3862                        } catch (Throwable t) {
3863                                throw handleException(t);
3864                        } finally {
3865                                if (pushStack)
3866                                        restoreContextStack();
3867                        }
3868                }
3869        }
3870        
3871    /**
3872         * JDBC 2.0
3873         * 
3874         * Get a BLOB column.
3875         * 
3876         * @param columnName the column name
3877         * @return an object representing a BLOB
3878         */
3879        public final Blob getBlob(String columnName) throws SQLException {
3880                checkIfClosed("getBlob");
3881                return (getBlob(findColumnName(columnName)));
3882        }
3883 
3884        /**
3885         * JDBC 2.0
3886         * 
3887         * Get a CLOB column.
3888         * 
3889         * @param columnName the column name
3890         * @return an object representing a CLOB
3891         * @exception SQLException
3892         *                Feature not implemented for now.
3893         */
3894        public final Clob getClob(String columnName) throws SQLException {
3895                checkIfClosed("getClob");
3896                return (getClob(findColumnName(columnName)));
3897        }        
3898 
3899        
3900    /**
3901         * JDBC 3.0
3902         * 
3903         * Updates the designated column with a java.sql.Blob value. The updater
3904         * methods are used to update column values in the current row or the insert
3905         * row. The updater methods do not update the underlying database; instead
3906         * the updateRow or insertRow methods are called to update the database.
3907         * 
3908         * @param columnIndex -
3909         *            the first column is 1, the second is 2
3910         * @param x -
3911         *            the new column value
3912         * @exception SQLException
3913         *                Feature not implemented for now.
3914         */
3915        public void updateBlob(int columnIndex, Blob x) throws SQLException {
3916        checksBeforeUpdateXXX("updateBlob", columnIndex);
3917        int colType = getColumnType(columnIndex);
3918        if (colType != Types.BLOB)
3919            throw dataTypeConversion(columnIndex, "java.sql.Blob");
3920 
3921        if (x == null)
3922            updateNull(columnIndex);
3923        else {
3924            long length = x.length();
3925            updateBinaryStreamInternal(columnIndex, x.getBinaryStream(), length, "updateBlob");
3926        }
3927        }
3928 
3929        /**
3930         * JDBC 3.0
3931         * 
3932         * Updates the designated column with a java.sql.Blob value. The updater
3933         * methods are used to update column values in the current row or the insert
3934         * row. The updater methods do not update the underlying database; instead
3935         * the updateRow or insertRow methods are called to update the database.
3936         * 
3937         * @param columnName -
3938         *            the SQL name of the column
3939         * @param x -
3940         *            the new column value
3941         * @exception SQLException
3942         *                Feature not implemented for now.
3943         */
3944        public void updateBlob(String columnName, Blob x) throws SQLException {
3945                checkIfClosed("updateBlob");
3946                updateBlob(findColumnName(columnName), x);
3947        }
3948 
3949        /**
3950         * JDBC 3.0
3951         * 
3952         * Updates the designated column with a java.sql.Clob value. The updater
3953         * methods are used to update column values in the current row or the insert
3954         * row. The updater methods do not update the underlying database; instead
3955         * the updateRow or insertRow methods are called to update the database.
3956         * 
3957         * @param columnIndex -
3958         *            the first column is 1, the second is 2
3959         * @param x -
3960         *            the new column value
3961         * @exception SQLException
3962         *                Feature not implemented for now.
3963         */
3964        public void updateClob(int columnIndex, Clob x) throws SQLException {
3965        checksBeforeUpdateXXX("updateClob", columnIndex);
3966        int colType = getColumnType(columnIndex);
3967        if (colType != Types.CLOB)
3968            throw dataTypeConversion(columnIndex, "java.sql.Clob");
3969 
3970        if (x == null)
3971        {
3972            updateNull(columnIndex);
3973        }
3974        else
3975        {
3976            
3977            long length = x.length();
3978 
3979            updateCharacterStreamInternal(
3980                columnIndex, x.getCharacterStream(),length, "updateClob");
3981        }
3982        }
3983 
3984        /**
3985         * JDBC 3.0
3986         * 
3987         * Updates the designated column with a java.sql.Clob value. The updater
3988         * methods are used to update column values in the current row or the insert
3989         * row. The updater methods do not update the underlying database; instead
3990         * the updateRow or insertRow methods are called to update the database.
3991         * 
3992         * @param columnName -
3993         *            the SQL name of the column
3994         * @param x -
3995         *            the new column value
3996         * @exception SQLException
3997         *                Feature not implemented for now.
3998         */
3999        public void updateClob(String columnName, Clob x) throws SQLException {
4000                checkIfClosed("updateClob");
4001                updateClob(findColumnName(columnName), x);
4002        }
4003        
4004        
4005        /*
4006         * * End of JDBC public methods.
4007         */
4008 
4009    /**
4010         * Map a Resultset column name to a ResultSet column index.
4011         * 
4012         * @param columnName
4013         *            the name of the column
4014         * @return the column index
4015         * @exception SQLException
4016         *                thrown on failure.
4017         */
4018    protected int findColumnName(String columnName)
4019                                                throws SQLException {
4020                // n.b. if we went through the JDBC interface,
4021                // there is a caching implementation in the JDBC doc
4022                // (appendix C). But we go through our own info, for now.
4023                // REVISIT: we might want to cache our own info...
4024                
4025 
4026                if (columnName == null)
4027                        throw newSQLException(SQLState.NULL_COLUMN_NAME);
4028 
4029                ResultDescription rd = resultDescription;
4030 
4031            // 1 or 0 based? assume 1 (probably wrong)
4032        // Changing the order in which columns are found from 1 till column count.
4033        // This is necessary in cases where the column names are the same but are in different cases.
4034        // This is because in updateXXX and getXXX methods column names are case insensitive
4035        // and in that case the first column should be returned.
4036        
4037        int columnCount = rd.getColumnCount();
4038 
4039        for(int i = 1 ; i<= columnCount;i++) {
4040                    String name = rd.getColumnDescriptor(i).getName();
4041                    if (StringUtil.SQLEqualsIgnoreCase(columnName, name)) {
4042                            return i;
4043                    }
4044            }
4045            throw newSQLException(SQLState.COLUMN_NOT_FOUND, columnName);
4046        }
4047 
4048 
4049 
4050        //
4051        // methods to be overridden in subimplementations
4052        // that want to stay within their subimplementation.
4053        //
4054        protected EmbedResultSetMetaData newEmbedResultSetMetaData(ResultDescription resultDesc) {
4055                return factory.newEmbedResultSetMetaData(resultDesc.getColumnInfo());
4056        }
4057 
4058        /**
4059         * Documented behaviour for streams is that they are implicitly closed on
4060         * the next get*() method call.
4061         */
4062        private final void closeCurrentStream() {
4063 
4064                if (currentStream != null) {
4065                        try {
4066                                // 99% of the time, the stream is already closed.
4067                                synchronized(this)
4068                                {
4069                                        if (currentStream != null) {
4070                                                if (currentStream instanceof java.io.Reader)
4071                                                        ((java.io.Reader) currentStream).close();
4072                                                else
4073                                                        ((java.io.InputStream) currentStream).close();
4074                                        }
4075                                }
4076                        } catch (IOException ioe) {
4077                                // just ignore, caller has already read the data they require
4078                        } finally {
4079                                currentStream = null;
4080                        }
4081                }
4082        }
4083 
4084        /**
4085         * Throw an exception if this ResultSet is closed.
4086         *
4087         * @param operation                The operation the caller is trying to perform
4088         *
4089         * @exception SQLException                Thrown if this ResultSet is closed.
4090         */
4091        final void checkIfClosed(String operation) throws SQLException {
4092                if (isClosed) {
4093                        throw newSQLException(SQLState.LANG_RESULT_SET_NOT_OPEN, operation);
4094                }
4095        }
4096 
4097    /**
4098     * Throw an exception if this ResultSet is closed or its
4099     * Connection has been closed. If the ResultSet has not
4100     * been explictly closed but the Connection is closed,
4101     * then this ResultSet will be marked as closed.
4102     */
4103        final void checkExecIfClosed(String operation) throws SQLException {
4104                
4105                checkIfClosed(operation);
4106 
4107                java.sql.Connection appConn = getEmbedConnection().getApplicationConnection();
4108 
4109        // Currently disconnected, i.e. a detached gobal transaction
4110        if (appConn == null)
4111            throw Util.noCurrentConnection();
4112            
4113                if (appConn.isClosed()) {
4114            closeCurrentStream();
4115            isClosed = true;
4116                        throw Util.noCurrentConnection();
4117        }
4118        }
4119    
4120        /**
4121         * Try to see if we can fish the SQL Statement out of the local statement.
4122         * @return null if we cannot figure out what SQL Statement is currently
4123         *  executing
4124         */
4125        protected String getSQLText()
4126        {
4127                if (stmt == null)
4128                        return null;
4129 
4130                return stmt.getSQLText();
4131        }
4132 
4133        /**
4134         * Try to see if we can fish the pvs out of the local statement.
4135         * @return null if we cannot figure out what parameter value set is currently
4136         *  using
4137         */
4138        protected ParameterValueSet getParameterValueSet()
4139        {
4140                if (stmt == null)
4141                        return null;
4142 
4143                return stmt.getParameterValueSet();
4144        }
4145 
4146    private static boolean isMaxFieldSizeType(int colType){
4147        return (colType == Types.BINARY || colType == Types.VARBINARY || 
4148            colType == Types.LONGVARBINARY || colType == Types.CHAR ||
4149            colType == Types.VARCHAR || colType == Types.LONGVARCHAR);
4150    }
4151        /*
4152         * close result set if we have a transaction level error 
4153         */
4154        final SQLException closeOnTransactionError(Throwable thrownException) throws SQLException
4155        {
4156                SQLException sqle = handleException(thrownException);
4157                if (thrownException instanceof StandardException)
4158                {
4159                        StandardException se = (StandardException) thrownException;
4160                        int severity = se.getSeverity();
4161                        if (severity == ExceptionSeverity.TRANSACTION_SEVERITY)
4162                        {
4163                                try {
4164                                        close();
4165                            } catch (Throwable t) {
4166                                SQLException top = handleException(t);
4167                                        top.setNextException(sqle);
4168                                        sqle = top;
4169                                }
4170                        }
4171                }
4172 
4173                return sqle;
4174        }
4175 
4176 
4177        /**
4178                Get the column value for a getXXX() call.
4179                This method:
4180                <UL>
4181                <LI> Closes the current stream (as per JDBC)
4182                <LI> Throws a SQLException if the result set is closed
4183                <LI> Throws a SQLException if the ResultSet is not on a row
4184                <LI> Throws a SQLException if the columnIndex is out of range
4185                <LI> Returns the DataValueDescriptor for the column.
4186                </UL>
4187        */
4188        protected final DataValueDescriptor getColumn(int columnIndex)
4189                throws SQLException, StandardException {
4190 
4191          closeCurrentStream();
4192 
4193          if (columnIndex < 1 || columnIndex > currentRow.nColumns()) {
4194                  throw newSQLException(SQLState.COLUMN_NOT_FOUND, 
4195                                                                new Integer(columnIndex));
4196          }
4197          if (isOnInsertRow || currentRowHasBeenUpdated && columnGotUpdated[columnIndex -1]) {
4198                  return updateRow.getColumn(columnIndex);
4199          } else {
4200                  checkOnRow(); // make sure there's a row
4201                  return currentRow.getColumn(columnIndex);
4202          }
4203        }
4204 
4205 
4206        /**
4207                An exception on many method calls to JDBC objects does not change the state
4208                of the transaction or statement, or even the underlying object. This method
4209                simply wraps the excecption in a SQLException. Examples are:
4210                <UL>
4211                <LI> getXXX() calls on ResultSet - ResultSet is not closed.
4212                <LI> setXXX() calls on PreparedStatement - ResultSet is not closed.
4213                </UL>
4214                In addition these exceptions must not call higher level objects to
4215                be closed (e.g. when executing a server side Java procedure). See bug 4397
4216 
4217        */
4218        static final SQLException noStateChangeException(Throwable thrownException) {
4219 
4220                // Any exception on a setXXX/getXXX method does not close
4221                // the ResultSet or the Statement. So we only need
4222                // to convert the exception to a SQLException.
4223 
4224                return TransactionResourceImpl.wrapInSQLException((SQLException) null, thrownException);
4225 
4226        }
4227 
4228        /**
4229                A dynamic result set was created in a procedure by a nested connection.
4230                Once the procedure returns, there is a good chance that connection is closed,
4231                so we re-attach the result set to the connection of the statement the called
4232                the procedure, which will be still open.
4233        */
4234        void setDynamicResultSet(EmbedStatement owningStmt) {
4235 
4236                this.owningStmt = owningStmt;
4237                this.localConn = owningStmt.getEmbedConnection();
4238        }
4239 
4240        /*
4241        ** Comparable (for ordering dynamic result sets from procedures) 
4242        */
4243 
4244        public final int compareTo(Object other) {
4245 
4246                EmbedResultSet olrs = (EmbedResultSet) other;
4247 
4248                return order - olrs.order;
4249 
4250        }
4251        
4252    /**
4253     * Checks if the result set has a scrollable cursor.
4254     *
4255     * @param methodName name of the method which requests the check
4256     * @exception SQLException if the result set is closed or its type
4257     * is <code>TYPE_FORWARD_ONLY</code>
4258     */
4259    private void checkScrollCursor(String methodName) throws SQLException {
4260                checkIfClosed(methodName);
4261                if (stmt.getResultSetType() == JDBC20Translation.TYPE_FORWARD_ONLY)
4262                        throw Util
4263                                        .newEmbedSQLException(
4264                                                        SQLState.NOT_ON_FORWARD_ONLY_CURSOR,
4265                                                        new Object[] { methodName },
4266                                                        StandardException
4267                                                                        .getSeverityFromIdentifier(SQLState.NOT_ON_FORWARD_ONLY_CURSOR));
4268        }
4269    
4270    private void checkUpdatableCursor(String operation) throws SQLException {
4271        if (getConcurrency() != JDBC20Translation.CONCUR_UPDATABLE) {
4272            throw Util.generateCsSQLException(
4273                    SQLState.UPDATABLE_RESULTSET_API_DISALLOWED, 
4274                    operation);
4275        }
4276    }
4277 
4278    
4279        private boolean checkRowPosition(int position, String positionText)
4280                        throws SQLException {
4281                // beforeFirst is only allowed on scroll cursors
4282                checkScrollCursor(positionText);
4283 
4284                synchronized (getConnectionSynchronization()) {
4285                        setupContextStack();
4286                        try {
4287                                try {
4288 
4289                                        /*
4290                                         * Push and pop a StatementContext around a next call so
4291                                         * that the ResultSet will get correctly closed down on an
4292                                         * error. (Cache the LanguageConnectionContext)
4293                                         */
4294                                        LanguageConnectionContext lcc = getEmbedConnection()
4295                                                        .getLanguageConnection();
4296                    // No timeout for this operation (use 0)
4297                                        StatementContext statementContext =
4298                        lcc.pushStatementContext(isAtomic, 
4299                                                 concurrencyOfThisResultSet==JDBC20Translation.CONCUR_READ_ONLY,
4300                                                 getSQLText(),
4301                                                 getParameterValueSet(),
4302                                                 false, 0L);
4303 
4304                                        boolean result = theResults.checkRowPosition(position);
4305 
4306                                        lcc.popStatementContext(statementContext, null);
4307 
4308                                        return result;
4309 
4310                                } catch (Throwable t) {
4311                                        /*
4312                                         * Need to close the result set here because the error might
4313                                         * cause us to lose the current connection if this is an XA
4314                                         * connection and we won't be able to do the close later
4315                                         */
4316                                        throw closeOnTransactionError(t);
4317                                }
4318 
4319                        } finally {
4320                                restoreContextStack();
4321                        }
4322                }
4323        }
4324        /**
4325         * * Is this result set from a select for update statement?
4326         */
4327        public final boolean isForUpdate()
4328        {
4329                if (theResults instanceof NoPutResultSet)
4330                        return ((NoPutResultSet) theResults).isForUpdate();
4331                return false;
4332        }
4333    
4334    final String getColumnSQLType(int column)
4335    {
4336        return resultDescription.getColumnDescriptor(column)
4337                       .getType().getTypeId().getSQLTypeName();
4338    }
4339 
4340        private final SQLException dataTypeConversion(String targetType, int column) {
4341                return newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH, targetType,
4342                getColumnSQLType(column));
4343        }
4344 
4345        private final SQLException dataTypeConversion(int column, String targetType) {
4346                return newSQLException(SQLState.LANG_DATA_TYPE_GET_MISMATCH,
4347                getColumnSQLType(column), targetType);
4348        }
4349    
4350    /**
4351     * Mark a column as already having a stream accessed from it.
4352     * If the stream was already accessed, then throw an exception.
4353     * @param columnIndex
4354     * @throws SQLException
4355     */
4356    final void useStream(int columnIndex) throws SQLException {
4357            
4358            if (streamUsedFlags == null)
4359                    streamUsedFlags = new boolean[getMetaData().getColumnCount()];
4360            
4361            else if (streamUsedFlags[columnIndex - 1])
4362                throw newSQLException(SQLState.LANG_STREAM_RETRIEVED_ALREADY);
4363            
4364            streamUsedFlags[columnIndex - 1] = true;
4365    }
4366 
4367    /**
4368     * JDBC 4.0
4369     *
4370     * <p>
4371     * Checks whether this <code>ResultSet</code> object has been
4372     * closed, either automatically or because <code>close()</code>
4373     * has been called.
4374     *
4375     * @return <code>true</code> if the <code>ResultSet</code> is
4376     * closed, <code>false</code> otherwise
4377     * @exception SQLException if a database error occurs
4378     */
4379    public final boolean isClosed() throws SQLException {
4380        if (isClosed) return true;
4381        try {
4382            // isClosed is not updated when EmbedConnection.close() is
4383            // called, so we need to check the status of the
4384            // connection
4385            checkExecIfClosed("");
4386            return false;
4387        } catch (SQLException sqle) {
4388            return isClosed;
4389        }
4390    }
4391     
4392     /**
4393      * Adds a warning to the end of the warning chain.
4394      *
4395      * @param w The warning to add to the warning chain.
4396      */
4397     private void addWarning(SQLWarning w) {
4398         if (topWarning == null) {
4399             topWarning = w;
4400         } else {
4401             topWarning.setNextWarning(w);
4402         }
4403     }
4404}
4405 

[all classes][org.apache.derby.impl.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov