EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.jdbc]

COVERAGE SUMMARY FOR SOURCE FILE [JdbcResultSet.java]

nameclass, %method, %block, %line, %
JdbcResultSet.java100% (1/1)97%  (204/210)80%  (3631/4552)72%  (817.3/1130)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class JdbcResultSet100% (1/1)97%  (204/210)80%  (3631/4552)72%  (817.3/1130)
getBigDecimal (String, int): BigDecimal 0%   (0/1)0%   (0/45)0%   (0/8)
getBigDecimal (int, int): BigDecimal 0%   (0/1)0%   (0/44)0%   (0/8)
getObject (String, Class): Object 0%   (0/1)0%   (0/2)0%   (0/1)
getObject (int, Class): Object 0%   (0/1)0%   (0/2)0%   (0/1)
updateObject (String, Object, int): void 0%   (0/1)0%   (0/33)0%   (0/7)
updateObject (int, Object, int): void 0%   (0/1)0%   (0/32)0%   (0/7)
rowDeleted (): boolean 100% (1/1)50%  (5/10)50%  (2/4)
rowInserted (): boolean 100% (1/1)50%  (5/10)50%  (2/4)
rowUpdated (): boolean 100% (1/1)50%  (5/10)50%  (2/4)
clearWarnings (): void 100% (1/1)58%  (7/12)67%  (4/6)
close (): void 100% (1/1)58%  (7/12)67%  (4/6)
getFetchDirection (): int 100% (1/1)58%  (7/12)60%  (3/5)
getWarnings (): SQLWarning 100% (1/1)58%  (7/12)60%  (3/5)
findColumn (String): int 100% (1/1)62%  (8/13)50%  (2/4)
wasNull (): boolean 100% (1/1)62%  (8/13)60%  (3/5)
closeInternal (): void 100% (1/1)62%  (35/56)74%  (8.8/12)
getType (): int 100% (1/1)63%  (12/19)57%  (2.8/5)
getBigDecimal (String): BigDecimal 100% (1/1)64%  (9/14)50%  (2/4)
getBinaryStream (String): InputStream 100% (1/1)64%  (9/14)50%  (2/4)
getByte (String): byte 100% (1/1)64%  (9/14)50%  (2/4)
getBytes (String): byte [] 100% (1/1)64%  (9/14)50%  (2/4)
getCharacterStream (String): Reader 100% (1/1)64%  (9/14)50%  (2/4)
getDate (String): Date 100% (1/1)64%  (9/14)50%  (2/4)
getDouble (String): double 100% (1/1)64%  (9/14)50%  (2/4)
getFetchSize (): int 100% (1/1)64%  (9/14)60%  (3/5)
getFloat (String): float 100% (1/1)64%  (9/14)50%  (2/4)
getHoldability (): int 100% (1/1)64%  (9/14)60%  (3/5)
getInt (String): int 100% (1/1)64%  (9/14)50%  (2/4)
getLong (String): long 100% (1/1)64%  (9/14)50%  (2/4)
getNCharacterStream (String): Reader 100% (1/1)64%  (9/14)50%  (2/4)
getNString (String): String 100% (1/1)64%  (9/14)50%  (2/4)
getShort (String): short 100% (1/1)64%  (9/14)50%  (2/4)
getString (String): String 100% (1/1)64%  (9/14)50%  (2/4)
getTime (String): Time 100% (1/1)64%  (9/14)50%  (2/4)
getTimestamp (String): Timestamp 100% (1/1)64%  (9/14)50%  (2/4)
previous (): boolean 100% (1/1)64%  (9/14)60%  (3/5)
checkColumnIndex (int): void 100% (1/1)67%  (10/15)75%  (3/4)
getBigDecimal (int): BigDecimal 100% (1/1)67%  (10/15)50%  (2/4)
getBinaryStream (int): InputStream 100% (1/1)67%  (10/15)50%  (2/4)
getByte (int): byte 100% (1/1)67%  (10/15)50%  (2/4)
getBytes (int): byte [] 100% (1/1)67%  (10/15)50%  (2/4)
getCharacterStream (int): Reader 100% (1/1)67%  (10/15)50%  (2/4)
getDate (int): Date 100% (1/1)67%  (10/15)50%  (2/4)
getDouble (int): double 100% (1/1)67%  (10/15)50%  (2/4)
getFloat (int): float 100% (1/1)67%  (10/15)50%  (2/4)
getInt (int): int 100% (1/1)67%  (10/15)50%  (2/4)
getLong (int): long 100% (1/1)67%  (10/15)50%  (2/4)
getNCharacterStream (int): Reader 100% (1/1)67%  (10/15)50%  (2/4)
getNString (int): String 100% (1/1)67%  (10/15)50%  (2/4)
getShort (int): short 100% (1/1)67%  (10/15)50%  (2/4)
getString (int): String 100% (1/1)67%  (10/15)50%  (2/4)
getTime (int): Time 100% (1/1)67%  (10/15)50%  (2/4)
getTimestamp (int): Timestamp 100% (1/1)67%  (10/15)50%  (2/4)
isClosed (): boolean 100% (1/1)67%  (10/15)50%  (2/4)
moveToCurrentRow (): void 100% (1/1)67%  (10/15)71%  (5/7)
updateNull (String): void 100% (1/1)67%  (10/15)67%  (4/6)
afterLast (): void 100% (1/1)69%  (11/16)71%  (5/7)
updateNull (int): void 100% (1/1)69%  (11/16)67%  (4/6)
getAsciiStream (String): InputStream 100% (1/1)71%  (12/17)60%  (3/5)
moveToInsertRow (): void 100% (1/1)71%  (12/17)71%  (5/7)
getObject (String): Object 100% (1/1)72%  (13/18)60%  (3/5)
getStatement (): Statement 100% (1/1)72%  (13/18)71%  (5/7)
deleteRow (): void 100% (1/1)72%  (21/29)73%  (8/11)
getObject (int): Object 100% (1/1)74%  (14/19)60%  (3/5)
refreshRow (): void 100% (1/1)74%  (23/31)73%  (8/11)
getBoolean (String): boolean 100% (1/1)76%  (16/21)60%  (3/5)
getAsciiStream (int): InputStream 100% (1/1)77%  (17/22)60%  (3/5)
getBoolean (int): boolean 100% (1/1)77%  (17/22)60%  (3/5)
updateBytes (int, byte []): void 100% (1/1)77%  (24/31)69%  (4.8/7)
updateDate (int, Date): void 100% (1/1)77%  (24/31)69%  (4.8/7)
updateTime (int, Time): void 100% (1/1)77%  (24/31)69%  (4.8/7)
updateTimestamp (int, Timestamp): void 100% (1/1)77%  (24/31)69%  (4.8/7)
updateBytes (String, byte []): void 100% (1/1)78%  (25/32)69%  (4.8/7)
updateDate (String, Date): void 100% (1/1)78%  (25/32)69%  (4.8/7)
updateTime (String, Time): void 100% (1/1)78%  (25/32)69%  (4.8/7)
updateTimestamp (String, Timestamp): void 100% (1/1)78%  (25/32)69%  (4.8/7)
checkOnValidRow (): void 100% (1/1)80%  (12/15)67%  (2/3)
getRow (): int 100% (1/1)80%  (20/25)75%  (6/8)
isFirst (): boolean 100% (1/1)80%  (20/25)67%  (4/6)
relative (int): boolean 100% (1/1)80%  (32/40)70%  (7/10)
updateBlob (int, Blob): void 100% (1/1)80%  (32/40)73%  (8/11)
updateClob (int, Clob): void 100% (1/1)80%  (32/40)73%  (8/11)
updateBlob (String, Blob): void 100% (1/1)80%  (33/41)73%  (8/11)
updateClob (String, Clob): void 100% (1/1)80%  (33/41)73%  (8/11)
updateBigDecimal (int, BigDecimal): void 100% (1/1)81%  (29/36)69%  (4.8/7)
updateNString (int, String): void 100% (1/1)81%  (29/36)69%  (4.8/7)
getDate (int, Calendar): Date 100% (1/1)81%  (21/26)60%  (3/5)
getTime (int, Calendar): Time 100% (1/1)81%  (21/26)60%  (3/5)
isBeforeFirst (): boolean 100% (1/1)81%  (21/26)71%  (5/7)
updateBigDecimal (String, BigDecimal): void 100% (1/1)81%  (30/37)69%  (4.8/7)
updateNString (String, String): void 100% (1/1)81%  (30/37)69%  (4.8/7)
updateString (String, String): void 100% (1/1)81%  (30/37)69%  (4.8/7)
getUpdatableRow (): UpdatableRow 100% (1/1)81%  (13/16)75%  (3/4)
getDate (String, Calendar): Date 100% (1/1)81%  (22/27)60%  (3/5)
getTime (String, Calendar): Time 100% (1/1)81%  (22/27)60%  (3/5)
isAfterLast (): boolean 100% (1/1)81%  (22/27)71%  (5/7)
isLast (): boolean 100% (1/1)81%  (22/27)67%  (4/6)
getTimestamp (int, Calendar): Timestamp 100% (1/1)82%  (23/28)67%  (4/6)
updateObject (int, Object): void 100% (1/1)82%  (23/28)71%  (5/7)
getArray (int): Array 100% (1/1)82%  (33/40)66%  (3.9/6)
getBlob (int): Blob 100% (1/1)82%  (33/40)66%  (3.9/6)
getClob (int): Clob 100% (1/1)82%  (33/40)66%  (3.9/6)
getNClob (String): NClob 100% (1/1)82%  (33/40)66%  (3.9/6)
getNClob (int): NClob 100% (1/1)82%  (33/40)66%  (3.9/6)
getTimestamp (String, Calendar): Timestamp 100% (1/1)83%  (24/29)67%  (4/6)
updateObject (String, Object): void 100% (1/1)83%  (24/29)71%  (5/7)
getArray (String): Array 100% (1/1)83%  (34/41)66%  (3.9/6)
getBlob (String): Blob 100% (1/1)83%  (34/41)66%  (3.9/6)
getClob (String): Clob 100% (1/1)83%  (34/41)66%  (3.9/6)
getConcurrency (): int 100% (1/1)83%  (25/30)75%  (6/8)
updateBoolean (int, boolean): void 100% (1/1)84%  (26/31)71%  (5/7)
updateByte (String, byte): void 100% (1/1)84%  (26/31)71%  (5/7)
updateByte (int, byte): void 100% (1/1)84%  (26/31)71%  (5/7)
updateDouble (int, double): void 100% (1/1)84%  (26/31)71%  (5/7)
updateFloat (int, float): void 100% (1/1)84%  (26/31)71%  (5/7)
updateInt (int, int): void 100% (1/1)84%  (26/31)71%  (5/7)
updateLong (int, long): void 100% (1/1)84%  (26/31)71%  (5/7)
updateShort (int, short): void 100% (1/1)84%  (26/31)71%  (5/7)
updateBoolean (String, boolean): void 100% (1/1)84%  (27/32)71%  (5/7)
updateDouble (String, double): void 100% (1/1)84%  (27/32)71%  (5/7)
updateFloat (String, float): void 100% (1/1)84%  (27/32)71%  (5/7)
updateInt (String, int): void 100% (1/1)84%  (27/32)71%  (5/7)
updateLong (String, long): void 100% (1/1)84%  (27/32)71%  (5/7)
updateShort (String, short): void 100% (1/1)84%  (27/32)71%  (5/7)
updateString (int, String): void 100% (1/1)86%  (31/36)71%  (5/7)
updateBinaryStream (int, InputStream, long): void 100% (1/1)87%  (33/38)78%  (7/9)
updateBlob (int, InputStream, long): void 100% (1/1)87%  (33/38)78%  (7/9)
updateCharacterStream (int, Reader, long): void 100% (1/1)87%  (33/38)78%  (7/9)
updateClob (int, Reader, long): void 100% (1/1)87%  (33/38)78%  (7/9)
updateNCharacterStream (int, Reader, long): void 100% (1/1)87%  (33/38)78%  (7/9)
getMetaData (): ResultSetMetaData 100% (1/1)87%  (34/39)78%  (7/9)
updateAsciiStream (int, InputStream, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateBinaryStream (String, InputStream, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateBlob (String, InputStream, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateCharacterStream (String, Reader, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateClob (String, Reader, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateNCharacterStream (String, Reader, long): void 100% (1/1)87%  (34/39)78%  (7/9)
updateAsciiStream (String, InputStream, long): void 100% (1/1)88%  (35/40)78%  (7/9)
insertRow (): void 100% (1/1)88%  (23/26)90%  (9/10)
updateRow (): void 100% (1/1)90%  (76/84)86%  (18/21)
getColumnIndex (String): int 100% (1/1)92%  (182/197)89%  (35.8/40)
JdbcResultSet (JdbcConnection, JdbcPreparedStatement, ResultInterface, int, b... 100% (1/1)100% (16/16)100% (4/4)
JdbcResultSet (JdbcConnection, JdbcStatement, ResultInterface, int, boolean, ... 100% (1/1)100% (32/32)100% (10/10)
absolute (int): boolean 100% (1/1)100% (69/69)100% (14/14)
beforeFirst (): void 100% (1/1)100% (18/18)100% (8/8)
cancelRowUpdates (): void 100% (1/1)100% (21/21)100% (9/9)
checkClosed (): void 100% (1/1)100% (20/20)100% (7/7)
checkUpdatable (): void 100% (1/1)100% (9/9)100% (4/4)
convertToUnknownValue (Object): Value 100% (1/1)100% (9/9)100% (2/2)
first (): boolean 100% (1/1)100% (22/22)100% (8/8)
get (String): Value 100% (1/1)100% (8/8)100% (2/2)
get (int): Value 100% (1/1)100% (44/44)100% (10/10)
getCursorName (): String 100% (1/1)100% (4/4)100% (1/1)
getObject (String, Map): Object 100% (1/1)100% (4/4)100% (1/1)
getObject (int, Map): Object 100% (1/1)100% (4/4)100% (1/1)
getRef (String): Ref 100% (1/1)100% (4/4)100% (1/1)
getRef (int): Ref 100% (1/1)100% (4/4)100% (1/1)
getRowId (String): RowId 100% (1/1)100% (4/4)100% (1/1)
getRowId (int): RowId 100% (1/1)100% (4/4)100% (1/1)
getSQLXML (String): SQLXML 100% (1/1)100% (4/4)100% (1/1)
getSQLXML (int): SQLXML 100% (1/1)100% (4/4)100% (1/1)
getURL (String): URL 100% (1/1)100% (4/4)100% (1/1)
getURL (int): URL 100% (1/1)100% (4/4)100% (1/1)
getUnicodeStream (String): InputStream 100% (1/1)100% (4/4)100% (1/1)
getUnicodeStream (int): InputStream 100% (1/1)100% (4/4)100% (1/1)
isWrapperFor (Class): boolean 100% (1/1)100% (11/11)100% (1/1)
last (): boolean 100% (1/1)100% (14/14)100% (5/5)
mapColumn (HashMap, String, int): void 100% (1/1)100% (15/15)100% (4/4)
next (): boolean 100% (1/1)100% (13/13)100% (5/5)
nextRow (): boolean 100% (1/1)100% (14/14)100% (4/4)
patchCurrentRow (Value []): void 100% (1/1)100% (56/56)100% (14/14)
resetResult (): void 100% (1/1)100% (10/10)100% (4/4)
setFetchDirection (int): void 100% (1/1)100% (4/4)100% (1/1)
setFetchSize (int): void 100% (1/1)100% (47/47)100% (16/16)
toString (): String 100% (1/1)100% (13/13)100% (1/1)
unwrap (Class): Object 100% (1/1)100% (10/10)100% (3/3)
update (String, Value): void 100% (1/1)100% (9/9)100% (3/3)
update (int, Value): void 100% (1/1)100% (32/32)100% (8/8)
updateArray (String, Array): void 100% (1/1)100% (4/4)100% (1/1)
updateArray (int, Array): void 100% (1/1)100% (4/4)100% (1/1)
updateAsciiStream (String, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateAsciiStream (String, InputStream, int): void 100% (1/1)100% (7/7)100% (2/2)
updateAsciiStream (int, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateAsciiStream (int, InputStream, int): void 100% (1/1)100% (7/7)100% (2/2)
updateBinaryStream (String, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateBinaryStream (String, InputStream, int): void 100% (1/1)100% (7/7)100% (2/2)
updateBinaryStream (int, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateBinaryStream (int, InputStream, int): void 100% (1/1)100% (7/7)100% (2/2)
updateBlob (String, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateBlob (int, InputStream): void 100% (1/1)100% (6/6)100% (2/2)
updateCharacterStream (String, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateCharacterStream (String, Reader, int): void 100% (1/1)100% (7/7)100% (2/2)
updateCharacterStream (int, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateCharacterStream (int, Reader, int): void 100% (1/1)100% (7/7)100% (2/2)
updateClob (String, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateClob (int, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateNCharacterStream (String, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateNCharacterStream (int, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateNClob (String, NClob): void 100% (1/1)100% (4/4)100% (1/1)
updateNClob (String, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateNClob (String, Reader, long): void 100% (1/1)100% (6/6)100% (2/2)
updateNClob (int, NClob): void 100% (1/1)100% (4/4)100% (1/1)
updateNClob (int, Reader): void 100% (1/1)100% (6/6)100% (2/2)
updateNClob (int, Reader, long): void 100% (1/1)100% (6/6)100% (2/2)
updateRef (String, Ref): void 100% (1/1)100% (4/4)100% (1/1)
updateRef (int, Ref): void 100% (1/1)100% (4/4)100% (1/1)
updateRowId (String, RowId): void 100% (1/1)100% (4/4)100% (1/1)
updateRowId (int, RowId): void 100% (1/1)100% (4/4)100% (1/1)
updateSQLXML (String, SQLXML): void 100% (1/1)100% (4/4)100% (1/1)
updateSQLXML (int, SQLXML): void 100% (1/1)100% (4/4)100% (1/1)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.jdbc;
7 
8import java.io.InputStream;
9import java.io.Reader;
10import java.math.BigDecimal;
11import java.net.URL;
12import java.sql.Array;
13import java.sql.Blob;
14import java.sql.Clob;
15import java.sql.Date;
16import java.sql.NClob;
17import java.sql.Ref;
18import java.sql.ResultSet;
19import java.sql.ResultSetMetaData;
20import java.sql.RowId;
21import java.sql.SQLException;
22import java.sql.SQLWarning;
23import java.sql.SQLXML;
24import java.sql.Statement;
25import java.sql.Time;
26import java.sql.Timestamp;
27import java.util.Calendar;
28import java.util.HashMap;
29import java.util.Map;
30import org.h2.api.ErrorCode;
31import org.h2.engine.SysProperties;
32import org.h2.message.DbException;
33import org.h2.message.TraceObject;
34import org.h2.result.ResultInterface;
35import org.h2.result.UpdatableRow;
36import org.h2.util.DateTimeUtils;
37import org.h2.util.IOUtils;
38import org.h2.util.New;
39import org.h2.util.StringUtils;
40import org.h2.value.CompareMode;
41import org.h2.value.DataType;
42import org.h2.value.Value;
43import org.h2.value.ValueBoolean;
44import org.h2.value.ValueByte;
45import org.h2.value.ValueBytes;
46import org.h2.value.ValueDate;
47import org.h2.value.ValueDecimal;
48import org.h2.value.ValueDouble;
49import org.h2.value.ValueFloat;
50import org.h2.value.ValueInt;
51import org.h2.value.ValueLong;
52import org.h2.value.ValueNull;
53import org.h2.value.ValueShort;
54import org.h2.value.ValueString;
55import org.h2.value.ValueTime;
56import org.h2.value.ValueTimestamp;
57 
58/**
59 * <p>
60 * Represents a result set.
61 * </p>
62 * <p>
63 * Column labels are case-insensitive, quotes are not supported. The first
64 * column has the column index 1.
65 * </p>
66 * <p>
67 * Updatable result sets: Result sets are updatable when the result only
68 * contains columns from one table, and if it contains all columns of a unique
69 * index (primary key or other) of this table. Key columns may not contain NULL
70 * (because multiple rows with NULL could exist). In updatable result sets, own
71 * changes are visible, but not own inserts and deletes.
72 * </p>
73 */
74public class JdbcResultSet extends TraceObject implements ResultSet {
75    private final boolean closeStatement;
76    private final boolean scrollable;
77    private final boolean updatable;
78    private ResultInterface result;
79    private JdbcConnection conn;
80    private JdbcStatement stat;
81    private int columnCount;
82    private boolean wasNull;
83    private Value[] insertRow;
84    private Value[] updateRow;
85    private HashMap<String, Integer> columnLabelMap;
86    private HashMap<Integer, Value[]> patchedRows;
87    private JdbcPreparedStatement preparedStatement;
88 
89    JdbcResultSet(JdbcConnection conn, JdbcStatement stat,
90            ResultInterface result, int id, boolean closeStatement,
91            boolean scrollable, boolean updatable) {
92        setTrace(conn.getSession().getTrace(), TraceObject.RESULT_SET, id);
93        this.conn = conn;
94        this.stat = stat;
95        this.result = result;
96        columnCount = result.getVisibleColumnCount();
97        this.closeStatement = closeStatement;
98        this.scrollable = scrollable;
99        this.updatable = updatable;
100    }
101 
102    JdbcResultSet(JdbcConnection conn, JdbcPreparedStatement preparedStatement,
103            ResultInterface result, int id, boolean closeStatement,
104            boolean scrollable, boolean updatable,
105            HashMap<String, Integer> columnLabelMap) {
106        this(conn, preparedStatement, result, id, closeStatement, scrollable,
107                updatable);
108        this.columnLabelMap = columnLabelMap;
109        this.preparedStatement = preparedStatement;
110    }
111 
112    /**
113     * Moves the cursor to the next row of the result set.
114     *
115     * @return true if successful, false if there are no more rows
116     */
117    @Override
118    public boolean next() throws SQLException {
119        try {
120            debugCodeCall("next");
121            checkClosed();
122            return nextRow();
123        } catch (Exception e) {
124            throw logAndConvert(e);
125        }
126    }
127 
128    /**
129     * Gets the meta data of this result set.
130     *
131     * @return the meta data
132     */
133    @Override
134    public ResultSetMetaData getMetaData() throws SQLException {
135        try {
136            int id = getNextId(TraceObject.RESULT_SET_META_DATA);
137            if (isDebugEnabled()) {
138                debugCodeAssign("ResultSetMetaData",
139                        TraceObject.RESULT_SET_META_DATA, id, "getMetaData()");
140            }
141            checkClosed();
142            String catalog = conn.getCatalog();
143            JdbcResultSetMetaData meta = new JdbcResultSetMetaData(
144                    this, null, result, catalog, conn.getSession().getTrace(), id);
145            return meta;
146        } catch (Exception e) {
147            throw logAndConvert(e);
148        }
149    }
150 
151    /**
152     * Returns whether the last column accessed was null.
153     *
154     * @return true if the last column accessed was null
155     */
156    @Override
157    public boolean wasNull() throws SQLException {
158        try {
159            debugCodeCall("wasNull");
160            checkClosed();
161            return wasNull;
162        } catch (Exception e) {
163            throw logAndConvert(e);
164        }
165    }
166 
167    /**
168     * Searches for a specific column in the result set. A case-insensitive
169     * search is made.
170     *
171     * @param columnLabel the column label
172     * @return the column index (1,2,...)
173     * @throws SQLException if the column is not found or if the result set is
174     *             closed
175     */
176    @Override
177    public int findColumn(String columnLabel) throws SQLException {
178        try {
179            debugCodeCall("findColumn", columnLabel);
180            return getColumnIndex(columnLabel);
181        } catch (Exception e) {
182            throw logAndConvert(e);
183        }
184    }
185 
186    /**
187     * Closes the result set.
188     */
189    @Override
190    public void close() throws SQLException {
191        try {
192            debugCodeCall("close");
193            closeInternal();
194        } catch (Exception e) {
195            throw logAndConvert(e);
196        }
197    }
198 
199    /**
200     * Close the result set. This method also closes the statement if required.
201     */
202    void closeInternal() throws SQLException {
203        if (result != null) {
204            try {
205                result.close();
206                if (closeStatement && stat != null) {
207                    stat.close();
208                }
209            } finally {
210                columnCount = 0;
211                result = null;
212                stat = null;
213                conn = null;
214                insertRow = null;
215                updateRow = null;
216            }
217        }
218    }
219 
220    /**
221     * Returns the statement that created this object.
222     *
223     * @return the statement or prepared statement, or null if created by a
224     *         DatabaseMetaData call.
225     */
226    @Override
227    public Statement getStatement() throws SQLException {
228        try {
229            debugCodeCall("getStatement");
230            checkClosed();
231            if (closeStatement) {
232                // if the result set was opened by a DatabaseMetaData call
233                return null;
234            }
235            return stat;
236        } catch (Exception e) {
237            throw logAndConvert(e);
238        }
239    }
240 
241    /**
242     * Gets the first warning reported by calls on this object.
243     *
244     * @return null
245     */
246    @Override
247    public SQLWarning getWarnings() throws SQLException {
248        try {
249            debugCodeCall("getWarnings");
250            checkClosed();
251            return null;
252        } catch (Exception e) {
253            throw logAndConvert(e);
254        }
255    }
256 
257    /**
258     * Clears all warnings.
259     */
260    @Override
261    public void clearWarnings() throws SQLException {
262        try {
263            debugCodeCall("clearWarnings");
264            checkClosed();
265        } catch (Exception e) {
266            throw logAndConvert(e);
267        }
268    }
269 
270    // =============================================================
271 
272    /**
273     * Returns the value of the specified column as a String.
274     *
275     * @param columnIndex (1,2,...)
276     * @return the value
277     * @throws SQLException if the column is not found or if the result set is
278     *             closed
279     */
280    @Override
281    public String getString(int columnIndex) throws SQLException {
282        try {
283            debugCodeCall("getString", columnIndex);
284            return get(columnIndex).getString();
285        } catch (Exception e) {
286            throw logAndConvert(e);
287        }
288    }
289 
290    /**
291     * Returns the value of the specified column as a String.
292     *
293     * @param columnLabel the column label
294     * @return the value
295     * @throws SQLException if the column is not found or if the result set is
296     *             closed
297     */
298    @Override
299    public String getString(String columnLabel) throws SQLException {
300        try {
301            debugCodeCall("getString", columnLabel);
302            return get(columnLabel).getString();
303        } catch (Exception e) {
304            throw logAndConvert(e);
305        }
306    }
307 
308    /**
309     * Returns the value of the specified column as an int.
310     *
311     * @param columnIndex (1,2,...)
312     * @return the value
313     * @throws SQLException if the column is not found or if the result set is
314     *             closed
315     */
316    @Override
317    public int getInt(int columnIndex) throws SQLException {
318        try {
319            debugCodeCall("getInt", columnIndex);
320            return get(columnIndex).getInt();
321        } catch (Exception e) {
322            throw logAndConvert(e);
323        }
324    }
325 
326    /**
327     * Returns the value of the specified column as an int.
328     *
329     * @param columnLabel the column label
330     * @return the value
331     * @throws SQLException if the column is not found or if the result set is
332     *             closed
333     */
334    @Override
335    public int getInt(String columnLabel) throws SQLException {
336        try {
337            debugCodeCall("getInt", columnLabel);
338            return get(columnLabel).getInt();
339        } catch (Exception e) {
340            throw logAndConvert(e);
341        }
342    }
343 
344    /**
345     * Returns the value of the specified column as a BigDecimal.
346     *
347     * @param columnIndex (1,2,...)
348     * @return the value
349     * @throws SQLException if the column is not found or if the result set is
350     *             closed
351     */
352    @Override
353    public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
354        try {
355            debugCodeCall("getBigDecimal", columnIndex);
356            return get(columnIndex).getBigDecimal();
357        } catch (Exception e) {
358            throw logAndConvert(e);
359        }
360    }
361 
362    /**
363     * Returns the value of the specified column as a java.sql.Date.
364     *
365     * @param columnIndex (1,2,...)
366     * @return the value
367     * @throws SQLException if the column is not found or if the result set is
368     *             closed
369     */
370    @Override
371    public Date getDate(int columnIndex) throws SQLException {
372        try {
373            debugCodeCall("getDate", columnIndex);
374            return get(columnIndex).getDate();
375        } catch (Exception e) {
376            throw logAndConvert(e);
377        }
378    }
379 
380    /**
381     * Returns the value of the specified column as a java.sql.Time.
382     *
383     * @param columnIndex (1,2,...)
384     * @return the value
385     * @throws SQLException if the column is not found or if the result set is
386     *             closed
387     */
388    @Override
389    public Time getTime(int columnIndex) throws SQLException {
390        try {
391            debugCodeCall("getTime", columnIndex);
392            return get(columnIndex).getTime();
393        } catch (Exception e) {
394            throw logAndConvert(e);
395        }
396    }
397 
398    /**
399     * Returns the value of the specified column as a java.sql.Timestamp.
400     *
401     * @param columnIndex (1,2,...)
402     * @return the value
403     * @throws SQLException if the column is not found or if the result set is
404     *             closed
405     */
406    @Override
407    public Timestamp getTimestamp(int columnIndex) throws SQLException {
408        try {
409            debugCodeCall("getTimestamp", columnIndex);
410            return get(columnIndex).getTimestamp();
411        } catch (Exception e) {
412            throw logAndConvert(e);
413        }
414    }
415 
416    /**
417     * Returns the value of the specified column as a BigDecimal.
418     *
419     * @param columnLabel the column label
420     * @return the value
421     * @throws SQLException if the column is not found or if the result set is
422     *             closed
423     */
424    @Override
425    public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
426        try {
427            debugCodeCall("getBigDecimal", columnLabel);
428            return get(columnLabel).getBigDecimal();
429        } catch (Exception e) {
430            throw logAndConvert(e);
431        }
432    }
433 
434    /**
435     * Returns the value of the specified column as a java.sql.Date.
436     *
437     * @param columnLabel the column label
438     * @return the value
439     * @throws SQLException if the column is not found or if the result set is
440     *             closed
441     */
442    @Override
443    public Date getDate(String columnLabel) throws SQLException {
444        try {
445            debugCodeCall("getDate", columnLabel);
446            return get(columnLabel).getDate();
447        } catch (Exception e) {
448            throw logAndConvert(e);
449        }
450    }
451 
452    /**
453     * Returns the value of the specified column as a java.sql.Time.
454     *
455     * @param columnLabel the column label
456     * @return the value
457     * @throws SQLException if the column is not found or if the result set is
458     *             closed
459     */
460    @Override
461    public Time getTime(String columnLabel) throws SQLException {
462        try {
463            debugCodeCall("getTime", columnLabel);
464            return get(columnLabel).getTime();
465        } catch (Exception e) {
466            throw logAndConvert(e);
467        }
468    }
469 
470    /**
471     * Returns the value of the specified column as a java.sql.Timestamp.
472     *
473     * @param columnLabel the column label
474     * @return the value
475     * @throws SQLException if the column is not found or if the result set is
476     *             closed
477     */
478    @Override
479    public Timestamp getTimestamp(String columnLabel) throws SQLException {
480        try {
481            debugCodeCall("getTimestamp", columnLabel);
482            return get(columnLabel).getTimestamp();
483        } catch (Exception e) {
484            throw logAndConvert(e);
485        }
486    }
487 
488    /**
489     * Returns a column value as a Java object. The data is
490     * de-serialized into a Java object (on the client side).
491     *
492     * @param columnIndex (1,2,...)
493     * @return the value or null
494     * @throws SQLException if the column is not found or if the result set is
495     *             closed
496     */
497    @Override
498    public Object getObject(int columnIndex) throws SQLException {
499        try {
500            debugCodeCall("getObject", columnIndex);
501            Value v = get(columnIndex);
502            return conn.convertToDefaultObject(v);
503        } catch (Exception e) {
504            throw logAndConvert(e);
505        }
506    }
507 
508    /**
509     * Returns a column value as a Java object. The data is
510     * de-serialized into a Java object (on the client side).
511     *
512     * @param columnLabel the column label
513     * @return the value or null
514     * @throws SQLException if the column is not found or if the result set is
515     *             closed
516     */
517    @Override
518    public Object getObject(String columnLabel) throws SQLException {
519        try {
520            debugCodeCall("getObject", columnLabel);
521            Value v = get(columnLabel);
522            return conn.convertToDefaultObject(v);
523        } catch (Exception e) {
524            throw logAndConvert(e);
525        }
526    }
527 
528    /**
529     * Returns the value of the specified column as a boolean.
530     *
531     * @param columnIndex (1,2,...)
532     * @return the value
533     * @throws SQLException if the column is not found or if the result set is
534     *             closed
535     */
536    @Override
537    public boolean getBoolean(int columnIndex) throws SQLException {
538        try {
539            debugCodeCall("getBoolean", columnIndex);
540            Boolean v = get(columnIndex).getBoolean();
541            return v == null ? false : v.booleanValue();
542        } catch (Exception e) {
543            throw logAndConvert(e);
544        }
545    }
546 
547    /**
548     * Returns the value of the specified column as a boolean.
549     *
550     * @param columnLabel the column label
551     * @return the value
552     * @throws SQLException if the column is not found or if the result set is
553     *             closed
554     */
555    @Override
556    public boolean getBoolean(String columnLabel) throws SQLException {
557        try {
558            debugCodeCall("getBoolean", columnLabel);
559            Boolean v = get(columnLabel).getBoolean();
560            return v == null ? false : v.booleanValue();
561        } catch (Exception e) {
562            throw logAndConvert(e);
563        }
564    }
565 
566    /**
567     * Returns the value of the specified column as a byte.
568     *
569     * @param columnIndex (1,2,...)
570     * @return the value
571     * @throws SQLException if the column is not found or if the result set is
572     *             closed
573     */
574    @Override
575    public byte getByte(int columnIndex) throws SQLException {
576        try {
577            debugCodeCall("getByte", columnIndex);
578            return get(columnIndex).getByte();
579        } catch (Exception e) {
580            throw logAndConvert(e);
581        }
582    }
583 
584    /**
585     * Returns the value of the specified column as a byte.
586     *
587     * @param columnLabel the column label
588     * @return the value
589     * @throws SQLException if the column is not found or if the result set is
590     *             closed
591     */
592    @Override
593    public byte getByte(String columnLabel) throws SQLException {
594        try {
595            debugCodeCall("getByte", columnLabel);
596            return get(columnLabel).getByte();
597        } catch (Exception e) {
598            throw logAndConvert(e);
599        }
600    }
601 
602    /**
603     * Returns the value of the specified column as a short.
604     *
605     * @param columnIndex (1,2,...)
606     * @return the value
607     * @throws SQLException if the column is not found or if the result set is
608     *             closed
609     */
610    @Override
611    public short getShort(int columnIndex) throws SQLException {
612        try {
613            debugCodeCall("getShort", columnIndex);
614            return get(columnIndex).getShort();
615        } catch (Exception e) {
616            throw logAndConvert(e);
617        }
618    }
619 
620    /**
621     * Returns the value of the specified column as a short.
622     *
623     * @param columnLabel the column label
624     * @return the value
625     * @throws SQLException if the column is not found or if the result set is
626     *             closed
627     */
628    @Override
629    public short getShort(String columnLabel) throws SQLException {
630        try {
631            debugCodeCall("getShort", columnLabel);
632            return get(columnLabel).getShort();
633        } catch (Exception e) {
634            throw logAndConvert(e);
635        }
636    }
637 
638    /**
639     * Returns the value of the specified column as a long.
640     *
641     * @param columnIndex (1,2,...)
642     * @return the value
643     * @throws SQLException if the column is not found or if the result set is
644     *             closed
645     */
646    @Override
647    public long getLong(int columnIndex) throws SQLException {
648        try {
649            debugCodeCall("getLong", columnIndex);
650            return get(columnIndex).getLong();
651        } catch (Exception e) {
652            throw logAndConvert(e);
653        }
654    }
655 
656    /**
657     * Returns the value of the specified column as a long.
658     *
659     * @param columnLabel the column label
660     * @return the value
661     * @throws SQLException if the column is not found or if the result set is
662     *             closed
663     */
664    @Override
665    public long getLong(String columnLabel) throws SQLException {
666        try {
667            debugCodeCall("getLong", columnLabel);
668            return get(columnLabel).getLong();
669        } catch (Exception e) {
670            throw logAndConvert(e);
671        }
672    }
673 
674    /**
675     * Returns the value of the specified column as a float.
676     *
677     * @param columnIndex (1,2,...)
678     * @return the value
679     * @throws SQLException if the column is not found or if the result set is
680     *             closed
681     */
682    @Override
683    public float getFloat(int columnIndex) throws SQLException {
684        try {
685            debugCodeCall("getFloat", columnIndex);
686            return get(columnIndex).getFloat();
687        } catch (Exception e) {
688            throw logAndConvert(e);
689        }
690    }
691 
692    /**
693     * Returns the value of the specified column as a float.
694     *
695     * @param columnLabel the column label
696     * @return the value
697     * @throws SQLException if the column is not found or if the result set is
698     *             closed
699     */
700    @Override
701    public float getFloat(String columnLabel) throws SQLException {
702        try {
703            debugCodeCall("getFloat", columnLabel);
704            return get(columnLabel).getFloat();
705        } catch (Exception e) {
706            throw logAndConvert(e);
707        }
708    }
709 
710    /**
711     * Returns the value of the specified column as a double.
712     *
713     * @param columnIndex (1,2,...)
714     * @return the value
715     * @throws SQLException if the column is not found or if the result set is
716     *             closed
717     */
718    @Override
719    public double getDouble(int columnIndex) throws SQLException {
720        try {
721            debugCodeCall("getDouble", columnIndex);
722            return get(columnIndex).getDouble();
723        } catch (Exception e) {
724            throw logAndConvert(e);
725        }
726    }
727 
728    /**
729     * Returns the value of the specified column as a double.
730     *
731     * @param columnLabel the column label
732     * @return the value
733     * @throws SQLException if the column is not found or if the result set is
734     *             closed
735     */
736    @Override
737    public double getDouble(String columnLabel) throws SQLException {
738        try {
739            debugCodeCall("getDouble", columnLabel);
740            return get(columnLabel).getDouble();
741        } catch (Exception e) {
742            throw logAndConvert(e);
743        }
744    }
745 
746    /**
747     * Returns the value of the specified column as a BigDecimal.
748     *
749     * @deprecated use {@link #getBigDecimal(String)}
750     *
751     * @param columnLabel the column label
752     * @param scale the scale of the returned value
753     * @return the value
754     * @throws SQLException if the column is not found or if the result set is
755     *             closed
756     */
757    @Override
758    public BigDecimal getBigDecimal(String columnLabel, int scale)
759            throws SQLException {
760        try {
761            if (isDebugEnabled()) {
762                debugCode("getBigDecimal(" +
763                        StringUtils.quoteJavaString(columnLabel)+", "+scale+");");
764            }
765            if (scale < 0) {
766                throw DbException.getInvalidValueException("scale", scale);
767            }
768            BigDecimal bd = get(columnLabel).getBigDecimal();
769            return bd == null ? null : ValueDecimal.setScale(bd, scale);
770        } catch (Exception e) {
771            throw logAndConvert(e);
772        }
773    }
774 
775    /**
776     * Returns the value of the specified column as a BigDecimal.
777     *
778     * @deprecated use {@link #getBigDecimal(int)}
779     *
780     * @param columnIndex (1,2,...)
781     * @param scale the scale of the returned value
782     * @return the value
783     * @throws SQLException if the column is not found or if the result set is
784     *             closed
785     */
786    @Override
787    public BigDecimal getBigDecimal(int columnIndex, int scale)
788            throws SQLException {
789        try {
790            if (isDebugEnabled()) {
791                debugCode("getBigDecimal(" + columnIndex + ", " + scale + ");");
792            }
793            if (scale < 0) {
794                throw DbException.getInvalidValueException("scale", scale);
795            }
796            BigDecimal bd = get(columnIndex).getBigDecimal();
797            return bd == null ? null : ValueDecimal.setScale(bd, scale);
798        } catch (Exception e) {
799            throw logAndConvert(e);
800        }
801    }
802 
803    /**
804     * [Not supported]
805     * @deprecated since JDBC 2.0, use getCharacterStream
806     */
807    @Override
808    public InputStream getUnicodeStream(int columnIndex) throws SQLException {
809        throw unsupported("unicodeStream");
810    }
811 
812    /**
813     * [Not supported]
814     * @deprecated since JDBC 2.0, use setCharacterStream
815     */
816    @Override
817    public InputStream getUnicodeStream(String columnLabel) throws SQLException {
818        throw unsupported("unicodeStream");
819    }
820 
821    /**
822     * [Not supported] Gets a column as a object using the specified type
823     * mapping.
824     */
825    @Override
826    public Object getObject(int columnIndex, Map<String, Class<?>> map)
827            throws SQLException {
828        throw unsupported("map");
829    }
830 
831    /**
832     * [Not supported] Gets a column as a object using the specified type
833     * mapping.
834     */
835    @Override
836    public Object getObject(String columnLabel, Map<String, Class<?>> map)
837            throws SQLException {
838        throw unsupported("map");
839    }
840 
841    /**
842     * [Not supported] Gets a column as a reference.
843     */
844    @Override
845    public Ref getRef(int columnIndex) throws SQLException {
846        throw unsupported("ref");
847    }
848 
849    /**
850     * [Not supported] Gets a column as a reference.
851     */
852    @Override
853    public Ref getRef(String columnLabel) throws SQLException {
854        throw unsupported("ref");
855    }
856 
857    /**
858     * Returns the value of the specified column as a java.sql.Date using a
859     * specified time zone.
860     *
861     * @param columnIndex (1,2,...)
862     * @param calendar the calendar
863     * @return the value
864     * @throws SQLException if the column is not found or if the result set is
865     *             closed
866     */
867    @Override
868    public Date getDate(int columnIndex, Calendar calendar) throws SQLException {
869        try {
870            if (isDebugEnabled()) {
871                debugCode("getDate(" + columnIndex + ", calendar)");
872            }
873            return DateTimeUtils.convertDate(get(columnIndex), calendar);
874        } catch (Exception e) {
875            throw logAndConvert(e);
876        }
877    }
878 
879    /**
880     * Returns the value of the specified column as a java.sql.Date using a
881     * specified time zone.
882     *
883     * @param columnLabel the column label
884     * @param calendar the calendar
885     * @return the value
886     * @throws SQLException if the column is not found or if the result set is
887     *             closed
888     */
889    @Override
890    public Date getDate(String columnLabel, Calendar calendar)
891            throws SQLException {
892        try {
893            if (isDebugEnabled()) {
894                debugCode("getDate(" +
895                        StringUtils.quoteJavaString(columnLabel) +
896                        ", calendar)");
897            }
898            return DateTimeUtils.convertDate(get(columnLabel), calendar);
899        } catch (Exception e) {
900            throw logAndConvert(e);
901        }
902    }
903 
904    /**
905     * Returns the value of the specified column as a java.sql.Time using a
906     * specified time zone.
907     *
908     * @param columnIndex (1,2,...)
909     * @param calendar the calendar
910     * @return the value
911     * @throws SQLException if the column is not found or if the result set is
912     *             closed
913     */
914    @Override
915    public Time getTime(int columnIndex, Calendar calendar) throws SQLException {
916        try {
917            if (isDebugEnabled()) {
918                debugCode("getTime(" + columnIndex + ", calendar)");
919            }
920            return DateTimeUtils.convertTime(get(columnIndex), calendar);
921        } catch (Exception e) {
922            throw logAndConvert(e);
923        }
924    }
925 
926    /**
927     * Returns the value of the specified column as a java.sql.Time using a
928     * specified time zone.
929     *
930     * @param columnLabel the column label
931     * @param calendar the calendar
932     * @return the value
933     * @throws SQLException if the column is not found or if the result set is
934     *             closed
935     */
936    @Override
937    public Time getTime(String columnLabel, Calendar calendar)
938            throws SQLException {
939        try {
940            if (isDebugEnabled()) {
941                debugCode("getTime(" +
942                        StringUtils.quoteJavaString(columnLabel) +
943                        ", calendar)");
944            }
945            return DateTimeUtils.convertTime(get(columnLabel), calendar);
946        } catch (Exception e) {
947            throw logAndConvert(e);
948        }
949    }
950 
951    /**
952     * Returns the value of the specified column as a java.sql.Timestamp using a
953     * specified time zone.
954     *
955     * @param columnIndex (1,2,...)
956     * @param calendar the calendar
957     * @return the value
958     * @throws SQLException if the column is not found or if the result set is
959     *             closed
960     */
961    @Override
962    public Timestamp getTimestamp(int columnIndex, Calendar calendar)
963            throws SQLException {
964        try {
965            if (isDebugEnabled()) {
966                debugCode("getTimestamp(" + columnIndex + ", calendar)");
967            }
968            Value value = get(columnIndex);
969            return DateTimeUtils.convertTimestamp(value, calendar);
970        } catch (Exception e) {
971            throw logAndConvert(e);
972        }
973    }
974 
975    /**
976     * Returns the value of the specified column as a java.sql.Timestamp.
977     *
978     * @param columnLabel the column label
979     * @param calendar the calendar
980     * @return the value
981     * @throws SQLException if the column is not found or if the result set is
982     *             closed
983     */
984    @Override
985    public Timestamp getTimestamp(String columnLabel, Calendar calendar)
986            throws SQLException {
987        try {
988            if (isDebugEnabled()) {
989                debugCode("getTimestamp(" +
990                        StringUtils.quoteJavaString(columnLabel) +
991                        ", calendar)");
992            }
993            Value value = get(columnLabel);
994            return DateTimeUtils.convertTimestamp(value, calendar);
995        } catch (Exception e) {
996            throw logAndConvert(e);
997        }
998    }
999 
1000    /**
1001     * Returns the value of the specified column as a Blob.
1002     *
1003     * @param columnIndex (1,2,...)
1004     * @return the value
1005     * @throws SQLException if the column is not found or if the result set is
1006     *             closed
1007     */
1008    @Override
1009    public Blob getBlob(int columnIndex) throws SQLException {
1010        try {
1011            int id = getNextId(TraceObject.BLOB);
1012            debugCodeAssign("Blob", TraceObject.BLOB,
1013                    id, "getBlob(" + columnIndex + ")");
1014            Value v = get(columnIndex);
1015            return v == ValueNull.INSTANCE ? null : new JdbcBlob(conn, v, id);
1016        } catch (Exception e) {
1017            throw logAndConvert(e);
1018        }
1019    }
1020 
1021    /**
1022     * Returns the value of the specified column as a Blob.
1023     *
1024     * @param columnLabel the column label
1025     * @return the value
1026     * @throws SQLException if the column is not found or if the result set is
1027     *             closed
1028     */
1029    @Override
1030    public Blob getBlob(String columnLabel) throws SQLException {
1031        try {
1032            int id = getNextId(TraceObject.BLOB);
1033            debugCodeAssign("Blob", TraceObject.BLOB,
1034                    id, "getBlob(" + quote(columnLabel) + ")");
1035            Value v = get(columnLabel);
1036            return v == ValueNull.INSTANCE ? null : new JdbcBlob(conn, v, id);
1037        } catch (Exception e) {
1038            throw logAndConvert(e);
1039        }
1040    }
1041 
1042    /**
1043     * Returns the value of the specified column as a byte array.
1044     *
1045     * @param columnIndex (1,2,...)
1046     * @return the value
1047     * @throws SQLException if the column is not found or if the result set is
1048     *             closed
1049     */
1050    @Override
1051    public byte[] getBytes(int columnIndex) throws SQLException {
1052        try {
1053            debugCodeCall("getBytes", columnIndex);
1054            return get(columnIndex).getBytes();
1055        } catch (Exception e) {
1056            throw logAndConvert(e);
1057        }
1058    }
1059 
1060    /**
1061     * Returns the value of the specified column as a byte array.
1062     *
1063     * @param columnLabel the column label
1064     * @return the value
1065     * @throws SQLException if the column is not found or if the result set is
1066     *             closed
1067     */
1068    @Override
1069    public byte[] getBytes(String columnLabel) throws SQLException {
1070        try {
1071            debugCodeCall("getBytes", columnLabel);
1072            return get(columnLabel).getBytes();
1073        } catch (Exception e) {
1074            throw logAndConvert(e);
1075        }
1076    }
1077 
1078    /**
1079     * Returns the value of the specified column as an input stream.
1080     *
1081     * @param columnIndex (1,2,...)
1082     * @return the value
1083     * @throws SQLException if the column is not found or if the result set is
1084     *             closed
1085     */
1086    @Override
1087    public InputStream getBinaryStream(int columnIndex) throws SQLException {
1088        try {
1089            debugCodeCall("getBinaryStream", columnIndex);
1090            return get(columnIndex).getInputStream();
1091        } catch (Exception e) {
1092            throw logAndConvert(e);
1093        }
1094    }
1095 
1096    /**
1097     * Returns the value of the specified column as an input stream.
1098     *
1099     * @param columnLabel the column label
1100     * @return the value
1101     * @throws SQLException if the column is not found or if the result set is
1102     *             closed
1103     */
1104    @Override
1105    public InputStream getBinaryStream(String columnLabel) throws SQLException {
1106        try {
1107            debugCodeCall("getBinaryStream", columnLabel);
1108            return get(columnLabel).getInputStream();
1109        } catch (Exception e) {
1110            throw logAndConvert(e);
1111        }
1112    }
1113 
1114 
1115    /**
1116     * Returns the value of the specified column as a Clob.
1117     *
1118     * @param columnIndex (1,2,...)
1119     * @return the value
1120     * @throws SQLException if the column is not found or if the result set is
1121     *             closed
1122     */
1123    @Override
1124    public Clob getClob(int columnIndex) throws SQLException {
1125        try {
1126            int id = getNextId(TraceObject.CLOB);
1127            debugCodeAssign("Clob", TraceObject.CLOB, id, "getClob(" + columnIndex + ")");
1128            Value v = get(columnIndex);
1129            return v == ValueNull.INSTANCE ? null : new JdbcClob(conn, v, id);
1130        } catch (Exception e) {
1131            throw logAndConvert(e);
1132        }
1133    }
1134 
1135    /**
1136     * Returns the value of the specified column as a Clob.
1137     *
1138     * @param columnLabel the column label
1139     * @return the value
1140     * @throws SQLException if the column is not found or if the result set is
1141     *             closed
1142     */
1143    @Override
1144    public Clob getClob(String columnLabel) throws SQLException {
1145        try {
1146            int id = getNextId(TraceObject.CLOB);
1147            debugCodeAssign("Clob", TraceObject.CLOB, id, "getClob(" +
1148                    quote(columnLabel) + ")");
1149            Value v = get(columnLabel);
1150            return v == ValueNull.INSTANCE ? null : new JdbcClob(conn, v, id);
1151        } catch (Exception e) {
1152            throw logAndConvert(e);
1153        }
1154    }
1155 
1156    /**
1157     * Returns the value of the specified column as an Array.
1158     *
1159     * @param columnIndex (1,2,...)
1160     * @return the value
1161     * @throws SQLException if the column is not found or if the result set is
1162     *             closed
1163     */
1164    @Override
1165    public Array getArray(int columnIndex) throws SQLException {
1166        try {
1167            int id = getNextId(TraceObject.ARRAY);
1168            debugCodeAssign("Clob", TraceObject.ARRAY, id, "getArray(" + columnIndex + ")");
1169            Value v = get(columnIndex);
1170            return v == ValueNull.INSTANCE ? null : new JdbcArray(conn, v, id);
1171        } catch (Exception e) {
1172            throw logAndConvert(e);
1173        }
1174    }
1175 
1176    /**
1177     * Returns the value of the specified column as an Array.
1178     *
1179     * @param columnLabel the column label
1180     * @return the value
1181     * @throws SQLException if the column is not found or if the result set is
1182     *             closed
1183     */
1184    @Override
1185    public Array getArray(String columnLabel) throws SQLException {
1186        try {
1187            int id = getNextId(TraceObject.ARRAY);
1188            debugCodeAssign("Clob", TraceObject.ARRAY, id, "getArray(" +
1189                    quote(columnLabel) + ")");
1190            Value v = get(columnLabel);
1191            return v == ValueNull.INSTANCE ? null : new JdbcArray(conn, v, id);
1192        } catch (Exception e) {
1193            throw logAndConvert(e);
1194        }
1195    }
1196 
1197    /**
1198     * Returns the value of the specified column as an input stream.
1199     *
1200     * @param columnIndex (1,2,...)
1201     * @return the value
1202     * @throws SQLException if the column is not found or if the result set is
1203     *             closed
1204     */
1205    @Override
1206    public InputStream getAsciiStream(int columnIndex) throws SQLException {
1207        try {
1208            debugCodeCall("getAsciiStream", columnIndex);
1209            String s = get(columnIndex).getString();
1210            return s == null ? null : IOUtils.getInputStreamFromString(s);
1211        } catch (Exception e) {
1212            throw logAndConvert(e);
1213        }
1214    }
1215 
1216    /**
1217     * Returns the value of the specified column as an input stream.
1218     *
1219     * @param columnLabel the column label
1220     * @return the value
1221     * @throws SQLException if the column is not found or if the result set is
1222     *             closed
1223     */
1224    @Override
1225    public InputStream getAsciiStream(String columnLabel) throws SQLException {
1226        try {
1227            debugCodeCall("getAsciiStream", columnLabel);
1228            String s = get(columnLabel).getString();
1229            return IOUtils.getInputStreamFromString(s);
1230        } catch (Exception e) {
1231            throw logAndConvert(e);
1232        }
1233    }
1234 
1235    /**
1236     * Returns the value of the specified column as a reader.
1237     *
1238     * @param columnIndex (1,2,...)
1239     * @return the value
1240     * @throws SQLException if the column is not found or if the result set is
1241     *             closed
1242     */
1243    @Override
1244    public Reader getCharacterStream(int columnIndex) throws SQLException {
1245        try {
1246            debugCodeCall("getCharacterStream", columnIndex);
1247            return get(columnIndex).getReader();
1248        } catch (Exception e) {
1249            throw logAndConvert(e);
1250        }
1251    }
1252 
1253    /**
1254     * Returns the value of the specified column as a reader.
1255     *
1256     * @param columnLabel the column label
1257     * @return the value
1258     * @throws SQLException if the column is not found or if the result set is
1259     *             closed
1260     */
1261    @Override
1262    public Reader getCharacterStream(String columnLabel) throws SQLException {
1263        try {
1264            debugCodeCall("getCharacterStream", columnLabel);
1265            return get(columnLabel).getReader();
1266        } catch (Exception e) {
1267            throw logAndConvert(e);
1268        }
1269    }
1270 
1271    /**
1272     * [Not supported]
1273     */
1274    @Override
1275    public URL getURL(int columnIndex) throws SQLException {
1276        throw unsupported("url");
1277    }
1278 
1279    /**
1280     * [Not supported]
1281     */
1282    @Override
1283    public URL getURL(String columnLabel) throws SQLException {
1284        throw unsupported("url");
1285    }
1286 
1287    // =============================================================
1288 
1289    /**
1290     * Updates a column in the current or insert row.
1291     *
1292     * @param columnIndex (1,2,...)
1293     * @throws SQLException if the result set is closed or not updatable
1294     */
1295    @Override
1296    public void updateNull(int columnIndex) throws SQLException {
1297        try {
1298            debugCodeCall("updateNull", columnIndex);
1299            update(columnIndex, ValueNull.INSTANCE);
1300        } catch (Exception e) {
1301            throw logAndConvert(e);
1302        }
1303    }
1304 
1305    /**
1306     * Updates a column in the current or insert row.
1307     *
1308     * @param columnLabel the column label
1309     * @throws SQLException if the result set is closed or not updatable
1310     */
1311    @Override
1312    public void updateNull(String columnLabel) throws SQLException {
1313        try {
1314            debugCodeCall("updateNull", columnLabel);
1315            update(columnLabel, ValueNull.INSTANCE);
1316        } catch (Exception e) {
1317            throw logAndConvert(e);
1318        }
1319    }
1320 
1321    /**
1322     * Updates a column in the current or insert row.
1323     *
1324     * @param columnIndex (1,2,...)
1325     * @param x the value
1326     * @throws SQLException if the result set is closed or not updatable
1327     */
1328    @Override
1329    public void updateBoolean(int columnIndex, boolean x) throws SQLException {
1330        try {
1331            if (isDebugEnabled()) {
1332                debugCode("updateBoolean("+columnIndex+", "+x+");");
1333            }
1334            update(columnIndex, ValueBoolean.get(x));
1335        } catch (Exception e) {
1336            throw logAndConvert(e);
1337        }
1338    }
1339 
1340    /**
1341     * Updates a column in the current or insert row.
1342     *
1343     * @param columnLabel the column label
1344     * @param x the value
1345     * @throws SQLException if result set is closed or not updatable
1346     */
1347    @Override
1348    public void updateBoolean(String columnLabel, boolean x)
1349            throws SQLException {
1350        try {
1351            if (isDebugEnabled()) {
1352                debugCode("updateBoolean("+quote(columnLabel)+", "+x+");");
1353            }
1354            update(columnLabel, ValueBoolean.get(x));
1355        } catch (Exception e) {
1356            throw logAndConvert(e);
1357        }
1358    }
1359 
1360    /**
1361     * Updates a column in the current or insert row.
1362     *
1363     * @param columnIndex (1,2,...)
1364     * @param x the value
1365     * @throws SQLException if the result set is closed or not updatable
1366     */
1367    @Override
1368    public void updateByte(int columnIndex, byte x) throws SQLException {
1369        try {
1370            if (isDebugEnabled()) {
1371                debugCode("updateByte("+columnIndex+", "+x+");");
1372            }
1373            update(columnIndex, ValueByte.get(x));
1374        } catch (Exception e) {
1375            throw logAndConvert(e);
1376        }
1377    }
1378 
1379    /**
1380     * Updates a column in the current or insert row.
1381     *
1382     * @param columnLabel the column label
1383     * @param x the value
1384     * @throws SQLException if the result set is closed or not updatable
1385     */
1386    @Override
1387    public void updateByte(String columnLabel, byte x) throws SQLException {
1388        try {
1389            if (isDebugEnabled()) {
1390                debugCode("updateByte("+columnLabel+", "+x+");");
1391            }
1392            update(columnLabel, ValueByte.get(x));
1393        } catch (Exception e) {
1394            throw logAndConvert(e);
1395        }
1396    }
1397 
1398    /**
1399     * Updates a column in the current or insert row.
1400     *
1401     * @param columnIndex (1,2,...)
1402     * @param x the value
1403     * @throws SQLException if the result set is closed or not updatable
1404     */
1405    @Override
1406    public void updateBytes(int columnIndex, byte[] x) throws SQLException {
1407        try {
1408            if (isDebugEnabled()) {
1409                debugCode("updateBytes("+columnIndex+", x);");
1410            }
1411            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE : ValueBytes.get(x));
1412        } catch (Exception e) {
1413            throw logAndConvert(e);
1414        }
1415    }
1416 
1417    /**
1418     * Updates a column in the current or insert row.
1419     *
1420     * @param columnLabel the column label
1421     * @param x the value
1422     * @throws SQLException if the result set is closed or not updatable
1423     */
1424    @Override
1425    public void updateBytes(String columnLabel, byte[] x) throws SQLException {
1426        try {
1427            if (isDebugEnabled()) {
1428                debugCode("updateBytes("+quote(columnLabel)+", x);");
1429            }
1430            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE : ValueBytes.get(x));
1431        } catch (Exception e) {
1432            throw logAndConvert(e);
1433        }
1434    }
1435 
1436    /**
1437     * Updates a column in the current or insert row.
1438     *
1439     * @param columnIndex (1,2,...)
1440     * @param x the value
1441     * @throws SQLException if the result set is closed or not updatable
1442     */
1443    @Override
1444    public void updateShort(int columnIndex, short x) throws SQLException {
1445        try {
1446            if (isDebugEnabled()) {
1447                debugCode("updateShort("+columnIndex+", (short) "+x+");");
1448            }
1449            update(columnIndex, ValueShort.get(x));
1450        } catch (Exception e) {
1451            throw logAndConvert(e);
1452        }
1453    }
1454 
1455    /**
1456     * Updates a column in the current or insert row.
1457     *
1458     * @param columnLabel the column label
1459     * @param x the value
1460     * @throws SQLException if the result set is closed or not updatable
1461     */
1462    @Override
1463    public void updateShort(String columnLabel, short x) throws SQLException {
1464        try {
1465            if (isDebugEnabled()) {
1466                debugCode("updateShort("+quote(columnLabel)+", (short) "+x+");");
1467            }
1468            update(columnLabel, ValueShort.get(x));
1469        } catch (Exception e) {
1470            throw logAndConvert(e);
1471        }
1472    }
1473 
1474    /**
1475     * Updates a column in the current or insert row.
1476     *
1477     * @param columnIndex (1,2,...)
1478     * @param x the value
1479     * @throws SQLException if the result set is closed or not updatable
1480     */
1481    @Override
1482    public void updateInt(int columnIndex, int x) throws SQLException {
1483        try {
1484            if (isDebugEnabled()) {
1485                debugCode("updateInt("+columnIndex+", "+x+");");
1486            }
1487            update(columnIndex, ValueInt.get(x));
1488        } catch (Exception e) {
1489            throw logAndConvert(e);
1490        }
1491    }
1492 
1493    /**
1494     * Updates a column in the current or insert row.
1495     *
1496     * @param columnLabel the column label
1497     * @param x the value
1498     * @throws SQLException if the result set is closed or not updatable
1499     */
1500    @Override
1501    public void updateInt(String columnLabel, int x) throws SQLException {
1502        try {
1503            if (isDebugEnabled()) {
1504                debugCode("updateInt("+quote(columnLabel)+", "+x+");");
1505            }
1506            update(columnLabel, ValueInt.get(x));
1507        } catch (Exception e) {
1508            throw logAndConvert(e);
1509        }
1510    }
1511 
1512    /**
1513     * Updates a column in the current or insert row.
1514     *
1515     * @param columnIndex (1,2,...)
1516     * @param x the value
1517     * @throws SQLException if the result set is closed or not updatable
1518     */
1519    @Override
1520    public void updateLong(int columnIndex, long x) throws SQLException {
1521        try {
1522            if (isDebugEnabled()) {
1523                debugCode("updateLong("+columnIndex+", "+x+"L);");
1524            }
1525            update(columnIndex, ValueLong.get(x));
1526        } catch (Exception e) {
1527            throw logAndConvert(e);
1528        }
1529    }
1530 
1531    /**
1532     * Updates a column in the current or insert row.
1533     *
1534     * @param columnLabel the column label
1535     * @param x the value
1536     * @throws SQLException if the result set is closed or not updatable
1537     */
1538    @Override
1539    public void updateLong(String columnLabel, long x) throws SQLException {
1540        try {
1541            if (isDebugEnabled()) {
1542                debugCode("updateLong("+quote(columnLabel)+", "+x+"L);");
1543            }
1544            update(columnLabel, ValueLong.get(x));
1545        } catch (Exception e) {
1546            throw logAndConvert(e);
1547        }
1548    }
1549 
1550    /**
1551     * Updates a column in the current or insert row.
1552     *
1553     * @param columnIndex (1,2,...)
1554     * @param x the value
1555     * @throws SQLException if the result set is closed or not updatable
1556     */
1557    @Override
1558    public void updateFloat(int columnIndex, float x) throws SQLException {
1559        try {
1560            if (isDebugEnabled()) {
1561                debugCode("updateFloat("+columnIndex+", "+x+"f);");
1562            }
1563            update(columnIndex, ValueFloat.get(x));
1564        } catch (Exception e) {
1565            throw logAndConvert(e);
1566        }
1567    }
1568 
1569    /**
1570     * Updates a column in the current or insert row.
1571     *
1572     * @param columnLabel the column label
1573     * @param x the value
1574     * @throws SQLException if the result set is closed or not updatable
1575     */
1576    @Override
1577    public void updateFloat(String columnLabel, float x) throws SQLException {
1578        try {
1579            if (isDebugEnabled()) {
1580                debugCode("updateFloat("+quote(columnLabel)+", "+x+"f);");
1581            }
1582            update(columnLabel, ValueFloat.get(x));
1583        } catch (Exception e) {
1584            throw logAndConvert(e);
1585        }
1586    }
1587 
1588    /**
1589     * Updates a column in the current or insert row.
1590     *
1591     * @param columnIndex (1,2,...)
1592     * @param x the value
1593     * @throws SQLException if the result set is closed or not updatable
1594     */
1595    @Override
1596    public void updateDouble(int columnIndex, double x) throws SQLException {
1597        try {
1598            if (isDebugEnabled()) {
1599                debugCode("updateDouble("+columnIndex+", "+x+"d);");
1600            }
1601            update(columnIndex, ValueDouble.get(x));
1602        } catch (Exception e) {
1603            throw logAndConvert(e);
1604        }
1605    }
1606 
1607    /**
1608     * Updates a column in the current or insert row.
1609     *
1610     * @param columnLabel the column label
1611     * @param x the value
1612     * @throws SQLException if the result set is closed or not updatable
1613     */
1614    @Override
1615    public void updateDouble(String columnLabel, double x) throws SQLException {
1616        try {
1617            if (isDebugEnabled()) {
1618                debugCode("updateDouble("+quote(columnLabel)+", "+x+"d);");
1619            }
1620            update(columnLabel, ValueDouble.get(x));
1621        } catch (Exception e) {
1622            throw logAndConvert(e);
1623        }
1624    }
1625 
1626    /**
1627     * Updates a column in the current or insert row.
1628     *
1629     * @param columnIndex (1,2,...)
1630     * @param x the value
1631     * @throws SQLException if the result set is closed or not updatable
1632     */
1633    @Override
1634    public void updateBigDecimal(int columnIndex, BigDecimal x)
1635            throws SQLException {
1636        try {
1637            if (isDebugEnabled()) {
1638                debugCode("updateBigDecimal("+columnIndex+", " + quoteBigDecimal(x) + ");");
1639            }
1640            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE
1641                    : ValueDecimal.get(x));
1642        } catch (Exception e) {
1643            throw logAndConvert(e);
1644        }
1645    }
1646 
1647    /**
1648     * Updates a column in the current or insert row.
1649     *
1650     * @param columnLabel the column label
1651     * @param x the value
1652     * @throws SQLException if the result set is closed or not updatable
1653     */
1654    @Override
1655    public void updateBigDecimal(String columnLabel, BigDecimal x)
1656            throws SQLException {
1657        try {
1658            if (isDebugEnabled()) {
1659                debugCode("updateBigDecimal(" + quote(columnLabel) + ", " +
1660                        quoteBigDecimal(x) + ");");
1661            }
1662            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE
1663                    : ValueDecimal.get(x));
1664        } catch (Exception e) {
1665            throw logAndConvert(e);
1666        }
1667    }
1668 
1669    /**
1670     * Updates a column in the current or insert row.
1671     *
1672     * @param columnIndex (1,2,...)
1673     * @param x the value
1674     * @throws SQLException if the result set is closed or not updatable
1675     */
1676    @Override
1677    public void updateString(int columnIndex, String x) throws SQLException {
1678        try {
1679            if (isDebugEnabled()) {
1680                debugCode("updateString("+columnIndex+", "+quote(x)+");");
1681            }
1682            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE
1683                    : ValueString.get(x));
1684        } catch (Exception e) {
1685            throw logAndConvert(e);
1686        }
1687    }
1688 
1689    /**
1690     * Updates a column in the current or insert row.
1691     *
1692     * @param columnLabel the column label
1693     * @param x the value
1694     * @throws SQLException if the result set is closed or not updatable
1695     */
1696    @Override
1697    public void updateString(String columnLabel, String x) throws SQLException {
1698        try {
1699            if (isDebugEnabled()) {
1700                debugCode("updateString("+quote(columnLabel)+", "+quote(x)+");");
1701            }
1702            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE
1703                    : ValueString.get(x));
1704        } catch (Exception e) {
1705            throw logAndConvert(e);
1706        }
1707    }
1708 
1709    /**
1710     * Updates a column in the current or insert row.
1711     *
1712     * @param columnIndex (1,2,...)
1713     * @param x the value
1714     * @throws SQLException if the result set is closed or not updatable
1715     */
1716    @Override
1717    public void updateDate(int columnIndex, Date x) throws SQLException {
1718        try {
1719            if (isDebugEnabled()) {
1720                debugCode("updateDate("+columnIndex+", x);");
1721            }
1722            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE : ValueDate.get(x));
1723        } catch (Exception e) {
1724            throw logAndConvert(e);
1725        }
1726    }
1727 
1728    /**
1729     * Updates a column in the current or insert row.
1730     *
1731     * @param columnLabel the column label
1732     * @param x the value
1733     * @throws SQLException if the result set is closed or not updatable
1734     */
1735    @Override
1736    public void updateDate(String columnLabel, Date x) throws SQLException {
1737        try {
1738            if (isDebugEnabled()) {
1739                debugCode("updateDate("+quote(columnLabel)+", x);");
1740            }
1741            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE : ValueDate.get(x));
1742        } catch (Exception e) {
1743            throw logAndConvert(e);
1744        }
1745    }
1746 
1747    /**
1748     * Updates a column in the current or insert row.
1749     *
1750     * @param columnIndex (1,2,...)
1751     * @param x the value
1752     * @throws SQLException if the result set is closed or not updatable
1753     */
1754    @Override
1755    public void updateTime(int columnIndex, Time x) throws SQLException {
1756        try {
1757            if (isDebugEnabled()) {
1758                debugCode("updateTime("+columnIndex+", x);");
1759            }
1760            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE : ValueTime.get(x));
1761        } catch (Exception e) {
1762            throw logAndConvert(e);
1763        }
1764    }
1765 
1766    /**
1767     * Updates a column in the current or insert row.
1768     *
1769     * @param columnLabel the column label
1770     * @param x the value
1771     * @throws SQLException if the result set is closed or not updatable
1772     */
1773    @Override
1774    public void updateTime(String columnLabel, Time x) throws SQLException {
1775        try {
1776            if (isDebugEnabled()) {
1777                debugCode("updateTime("+quote(columnLabel)+", x);");
1778            }
1779            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE : ValueTime.get(x));
1780        } catch (Exception e) {
1781            throw logAndConvert(e);
1782        }
1783    }
1784 
1785    /**
1786     * Updates a column in the current or insert row.
1787     *
1788     * @param columnIndex (1,2,...)
1789     * @param x the value
1790     * @throws SQLException if the result set is closed or not updatable
1791     */
1792    @Override
1793    public void updateTimestamp(int columnIndex, Timestamp x)
1794            throws SQLException {
1795        try {
1796            if (isDebugEnabled()) {
1797                debugCode("updateTimestamp("+columnIndex+", x);");
1798            }
1799            update(columnIndex, x == null ? (Value) ValueNull.INSTANCE
1800                    : ValueTimestamp.get(x));
1801        } catch (Exception e) {
1802            throw logAndConvert(e);
1803        }
1804    }
1805 
1806    /**
1807     * Updates a column in the current or insert row.
1808     *
1809     * @param columnLabel the column label
1810     * @param x the value
1811     * @throws SQLException if the result set is closed or not updatable
1812     */
1813    @Override
1814    public void updateTimestamp(String columnLabel, Timestamp x)
1815            throws SQLException {
1816        try {
1817            if (isDebugEnabled()) {
1818                debugCode("updateTimestamp("+quote(columnLabel)+", x);");
1819            }
1820            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE
1821                    : ValueTimestamp.get(x));
1822        } catch (Exception e) {
1823            throw logAndConvert(e);
1824        }
1825    }
1826 
1827    /**
1828     * Updates a column in the current or insert row.
1829     *
1830     * @param columnIndex (1,2,...)
1831     * @param x the value
1832     * @param length the number of characters
1833     * @throws SQLException if the result set is closed or not updatable
1834     */
1835    @Override
1836    public void updateAsciiStream(int columnIndex, InputStream x, int length)
1837            throws SQLException {
1838        updateAsciiStream(columnIndex, x, (long) length);
1839    }
1840 
1841    /**
1842     * Updates a column in the current or insert row.
1843     *
1844     * @param columnIndex (1,2,...)
1845     * @param x the value
1846     * @throws SQLException if the result set is closed or not updatable
1847     */
1848    @Override
1849    public void updateAsciiStream(int columnIndex, InputStream x)
1850            throws SQLException {
1851        updateAsciiStream(columnIndex, x, -1);
1852    }
1853 
1854    /**
1855     * Updates a column in the current or insert row.
1856     *
1857     * @param columnIndex (1,2,...)
1858     * @param x the value
1859     * @param length the number of characters
1860     * @throws SQLException if the result set is closed or not updatable
1861     */
1862    @Override
1863    public void updateAsciiStream(int columnIndex, InputStream x, long length)
1864            throws SQLException {
1865        try {
1866            if (isDebugEnabled()) {
1867                debugCode("updateAsciiStream("+columnIndex+", x, "+length+"L);");
1868            }
1869            checkClosed();
1870            Value v = conn.createClob(IOUtils.getAsciiReader(x), length);
1871            update(columnIndex, v);
1872        } catch (Exception e) {
1873            throw logAndConvert(e);
1874        }
1875    }
1876 
1877    /**
1878     * Updates a column in the current or insert row.
1879     *
1880     * @param columnLabel the column label
1881     * @param x the value
1882     * @param length the number of characters
1883     * @throws SQLException if the result set is closed or not updatable
1884     */
1885    @Override
1886    public void updateAsciiStream(String columnLabel, InputStream x, int length)
1887            throws SQLException {
1888        updateAsciiStream(columnLabel, x, (long) length);
1889    }
1890 
1891    /**
1892     * Updates a column in the current or insert row.
1893     *
1894     * @param columnLabel the column label
1895     * @param x the value
1896     * @throws SQLException if the result set is closed
1897     */
1898    @Override
1899    public void updateAsciiStream(String columnLabel, InputStream x)
1900            throws SQLException {
1901        updateAsciiStream(columnLabel, x, -1);
1902    }
1903 
1904    /**
1905     * Updates a column in the current or insert row.
1906     *
1907     * @param columnLabel the column label
1908     * @param x the value
1909     * @param length the number of characters
1910     * @throws SQLException if the result set is closed or not updatable
1911     */
1912    @Override
1913    public void updateAsciiStream(String columnLabel, InputStream x, long length)
1914            throws SQLException {
1915        try {
1916            if (isDebugEnabled()) {
1917                debugCode("updateAsciiStream("+quote(columnLabel)+", x, "+length+"L);");
1918            }
1919            checkClosed();
1920            Value v = conn.createClob(IOUtils.getAsciiReader(x), length);
1921            update(columnLabel, v);
1922        } catch (Exception e) {
1923            throw logAndConvert(e);
1924        }
1925    }
1926 
1927    /**
1928     * Updates a column in the current or insert row.
1929     *
1930     * @param columnIndex (1,2,...)
1931     * @param x the value
1932     * @param length the number of characters
1933     * @throws SQLException if the result set is closed or not updatable
1934     */
1935    @Override
1936    public void updateBinaryStream(int columnIndex, InputStream x, int length)
1937            throws SQLException {
1938        updateBinaryStream(columnIndex, x, (long) length);
1939    }
1940 
1941    /**
1942     * Updates a column in the current or insert row.
1943     *
1944     * @param columnIndex (1,2,...)
1945     * @param x the value
1946     * @throws SQLException if the result set is closed or not updatable
1947     */
1948    @Override
1949    public void updateBinaryStream(int columnIndex, InputStream x)
1950            throws SQLException {
1951        updateBinaryStream(columnIndex, x, -1);
1952    }
1953 
1954    /**
1955     * Updates a column in the current or insert row.
1956     *
1957     * @param columnIndex (1,2,...)
1958     * @param x the value
1959     * @param length the number of characters
1960     * @throws SQLException if the result set is closed or not updatable
1961     */
1962    @Override
1963    public void updateBinaryStream(int columnIndex, InputStream x, long length)
1964            throws SQLException {
1965        try {
1966            if (isDebugEnabled()) {
1967                debugCode("updateBinaryStream("+columnIndex+", x, "+length+"L);");
1968            }
1969            checkClosed();
1970            Value v = conn.createBlob(x, length);
1971            update(columnIndex, v);
1972        } catch (Exception e) {
1973            throw logAndConvert(e);
1974        }
1975    }
1976 
1977    /**
1978     * Updates a column in the current or insert row.
1979     *
1980     * @param columnLabel the column label
1981     * @param x the value
1982     * @throws SQLException if the result set is closed or not updatable
1983     */
1984    @Override
1985    public void updateBinaryStream(String columnLabel, InputStream x)
1986            throws SQLException {
1987        updateBinaryStream(columnLabel, x, -1);
1988    }
1989 
1990    /**
1991     * Updates a column in the current or insert row.
1992     *
1993     * @param columnLabel the column label
1994     * @param x the value
1995     * @param length the number of characters
1996     * @throws SQLException if the result set is closed or not updatable
1997     */
1998    @Override
1999    public void updateBinaryStream(String columnLabel, InputStream x, int length)
2000            throws SQLException {
2001        updateBinaryStream(columnLabel, x, (long) length);
2002    }
2003 
2004    /**
2005     * Updates a column in the current or insert row.
2006     *
2007     * @param columnLabel the column label
2008     * @param x the value
2009     * @param length the number of characters
2010     * @throws SQLException if the result set is closed or not updatable
2011     */
2012    @Override
2013    public void updateBinaryStream(String columnLabel, InputStream x,
2014            long length) throws SQLException {
2015        try {
2016            if (isDebugEnabled()) {
2017                debugCode("updateBinaryStream("+quote(columnLabel)+", x, "+length+"L);");
2018            }
2019            checkClosed();
2020            Value v = conn.createBlob(x, length);
2021            update(columnLabel, v);
2022        } catch (Exception e) {
2023            throw logAndConvert(e);
2024        }
2025    }
2026 
2027    /**
2028     * Updates a column in the current or insert row.
2029     *
2030     * @param columnIndex (1,2,...)
2031     * @param x the value
2032     * @param length the number of characters
2033     * @throws SQLException if the result set is closed or not updatable
2034     */
2035    @Override
2036    public void updateCharacterStream(int columnIndex, Reader x, long length)
2037            throws SQLException {
2038        try {
2039            if (isDebugEnabled()) {
2040                debugCode("updateCharacterStream("+columnIndex+", x, "+length+"L);");
2041            }
2042            checkClosed();
2043            Value v = conn.createClob(x, length);
2044            update(columnIndex, v);
2045        } catch (Exception e) {
2046            throw logAndConvert(e);
2047        }
2048    }
2049 
2050    /**
2051     * Updates a column in the current or insert row.
2052     *
2053     * @param columnIndex (1,2,...)
2054     * @param x the value
2055     * @param length the number of characters
2056     * @throws SQLException if the result set is closed or not updatable
2057     */
2058    @Override
2059    public void updateCharacterStream(int columnIndex, Reader x, int length)
2060            throws SQLException {
2061        updateCharacterStream(columnIndex, x, (long) length);
2062    }
2063 
2064    /**
2065     * Updates a column in the current or insert row.
2066     *
2067     * @param columnIndex (1,2,...)
2068     * @param x the value
2069     * @throws SQLException if the result set is closed or not updatable
2070     */
2071    @Override
2072    public void updateCharacterStream(int columnIndex, Reader x)
2073            throws SQLException {
2074        updateCharacterStream(columnIndex, x, -1);
2075    }
2076 
2077    /**
2078     * Updates a column in the current or insert row.
2079     *
2080     * @param columnLabel the column label
2081     * @param x the value
2082     * @param length the number of characters
2083     * @throws SQLException if the result set is closed or not updatable
2084     */
2085    @Override
2086    public void updateCharacterStream(String columnLabel, Reader x, int length)
2087            throws SQLException {
2088        updateCharacterStream(columnLabel, x, (long) length);
2089    }
2090 
2091    /**
2092     * Updates a column in the current or insert row.
2093     *
2094     * @param columnLabel the column label
2095     * @param x the value
2096     * @throws SQLException if the result set is closed or not updatable
2097     */
2098    @Override
2099    public void updateCharacterStream(String columnLabel, Reader x)
2100            throws SQLException {
2101        updateCharacterStream(columnLabel, x, -1);
2102    }
2103 
2104    /**
2105     * Updates a column in the current or insert row.
2106     *
2107     * @param columnLabel the column label
2108     * @param x the value
2109     * @param length the number of characters
2110     * @throws SQLException if the result set is closed or not updatable
2111     */
2112    @Override
2113    public void updateCharacterStream(String columnLabel, Reader x, long length)
2114            throws SQLException {
2115        try {
2116            if (isDebugEnabled()) {
2117                debugCode("updateCharacterStream("+quote(columnLabel)+", x, "+length+"L);");
2118            }
2119            checkClosed();
2120            Value v = conn.createClob(x, length);
2121            update(columnLabel, v);
2122        } catch (Exception e) {
2123            throw logAndConvert(e);
2124        }
2125    }
2126 
2127    /**
2128     * Updates a column in the current or insert row.
2129     *
2130     * @param columnIndex (1,2,...)
2131     * @param x the value
2132     * @param scale is ignored
2133     * @throws SQLException if the result set is closed or not updatable
2134     */
2135    @Override
2136    public void updateObject(int columnIndex, Object x, int scale)
2137            throws SQLException {
2138        try {
2139            if (isDebugEnabled()) {
2140                debugCode("updateObject("+columnIndex+", x, "+scale+");");
2141            }
2142            update(columnIndex, convertToUnknownValue(x));
2143        } catch (Exception e) {
2144            throw logAndConvert(e);
2145        }
2146    }
2147 
2148 
2149 
2150    /**
2151     * Updates a column in the current or insert row.
2152     *
2153     * @param columnLabel the column label
2154     * @param x the value
2155     * @param scale is ignored
2156     * @throws SQLException if the result set is closed or not updatable
2157     */
2158    @Override
2159    public void updateObject(String columnLabel, Object x, int scale)
2160            throws SQLException {
2161        try {
2162            if (isDebugEnabled()) {
2163                debugCode("updateObject("+quote(columnLabel)+", x, "+scale+");");
2164            }
2165            update(columnLabel, convertToUnknownValue(x));
2166        } catch (Exception e) {
2167            throw logAndConvert(e);
2168        }
2169    }
2170 
2171    /**
2172     * Updates a column in the current or insert row.
2173     *
2174     * @param columnIndex (1,2,...)
2175     * @param x the value
2176     * @throws SQLException if the result set is closed or not updatable
2177     */
2178    @Override
2179    public void updateObject(int columnIndex, Object x) throws SQLException {
2180        try {
2181            if (isDebugEnabled()) {
2182                debugCode("updateObject("+columnIndex+", x);");
2183            }
2184            update(columnIndex, convertToUnknownValue(x));
2185        } catch (Exception e) {
2186            throw logAndConvert(e);
2187        }
2188    }
2189 
2190    /**
2191     * Updates a column in the current or insert row.
2192     *
2193     * @param columnLabel the column label
2194     * @param x the value
2195     * @throws SQLException if the result set is closed or not updatable
2196     */
2197    @Override
2198    public void updateObject(String columnLabel, Object x) throws SQLException {
2199        try {
2200            if (isDebugEnabled()) {
2201                debugCode("updateObject("+quote(columnLabel)+", x);");
2202            }
2203            update(columnLabel, convertToUnknownValue(x));
2204        } catch (Exception e) {
2205            throw logAndConvert(e);
2206        }
2207    }
2208 
2209    /**
2210     * [Not supported]
2211     */
2212    @Override
2213    public void updateRef(int columnIndex, Ref x) throws SQLException {
2214        throw unsupported("ref");
2215    }
2216 
2217    /**
2218     * [Not supported]
2219     */
2220    @Override
2221    public void updateRef(String columnLabel, Ref x) throws SQLException {
2222        throw unsupported("ref");
2223    }
2224 
2225    /**
2226     * Updates a column in the current or insert row.
2227     *
2228     * @param columnIndex (1,2,...)
2229     * @param x the value
2230     * @throws SQLException if the result set is closed or not updatable
2231     */
2232    @Override
2233    public void updateBlob(int columnIndex, InputStream x) throws SQLException {
2234        updateBlob(columnIndex, x, -1);
2235    }
2236 
2237    /**
2238     * Updates a column in the current or insert row.
2239     *
2240     * @param columnIndex (1,2,...)
2241     * @param x the value
2242     * @param length the length
2243     * @throws SQLException if the result set is closed or not updatable
2244     */
2245    @Override
2246    public void updateBlob(int columnIndex, InputStream x, long length)
2247            throws SQLException {
2248        try {
2249            if (isDebugEnabled()) {
2250                debugCode("updateBlob("+columnIndex+", x, " + length + "L);");
2251            }
2252            checkClosed();
2253            Value v = conn.createBlob(x, length);
2254            update(columnIndex, v);
2255        } catch (Exception e) {
2256            throw logAndConvert(e);
2257        }
2258    }
2259 
2260    /**
2261     * Updates a column in the current or insert row.
2262     *
2263     * @param columnIndex (1,2,...)
2264     * @param x the value
2265     * @throws SQLException if the result set is closed or not updatable
2266     */
2267    @Override
2268    public void updateBlob(int columnIndex, Blob x) throws SQLException {
2269        try {
2270            if (isDebugEnabled()) {
2271                debugCode("updateBlob("+columnIndex+", x);");
2272            }
2273            checkClosed();
2274            Value v;
2275            if (x == null) {
2276                v = ValueNull.INSTANCE;
2277            } else {
2278                v = conn.createBlob(x.getBinaryStream(), -1);
2279            }
2280            update(columnIndex, v);
2281        } catch (Exception e) {
2282            throw logAndConvert(e);
2283        }
2284    }
2285 
2286    /**
2287     * Updates a column in the current or insert row.
2288     *
2289     * @param columnLabel the column label
2290     * @param x the value
2291     * @throws SQLException if the result set is closed or not updatable
2292     */
2293    @Override
2294    public void updateBlob(String columnLabel, Blob x) throws SQLException {
2295        try {
2296            if (isDebugEnabled()) {
2297                debugCode("updateBlob("+quote(columnLabel)+", x);");
2298            }
2299            checkClosed();
2300            Value v;
2301            if (x == null) {
2302                v = ValueNull.INSTANCE;
2303            } else {
2304                v = conn.createBlob(x.getBinaryStream(), -1);
2305            }
2306            update(columnLabel, v);
2307        } catch (Exception e) {
2308            throw logAndConvert(e);
2309        }
2310    }
2311 
2312    /**
2313     * Updates a column in the current or insert row.
2314     *
2315     * @param columnLabel the column label
2316     * @param x the value
2317     * @throws SQLException if the result set is closed or not updatable
2318     */
2319    @Override
2320    public void updateBlob(String columnLabel, InputStream x) throws SQLException {
2321        updateBlob(columnLabel, x, -1);
2322    }
2323 
2324    /**
2325     * Updates a column in the current or insert row.
2326     *
2327     * @param columnLabel the column label
2328     * @param x the value
2329     * @param length the length
2330     * @throws SQLException if the result set is closed or not updatable
2331     */
2332    @Override
2333    public void updateBlob(String columnLabel, InputStream x, long length)
2334            throws SQLException {
2335        try {
2336            if (isDebugEnabled()) {
2337                debugCode("updateBlob("+quote(columnLabel)+", x, " + length + "L);");
2338            }
2339            checkClosed();
2340            Value v = conn.createBlob(x, -1);
2341            update(columnLabel, v);
2342        } catch (Exception e) {
2343            throw logAndConvert(e);
2344        }
2345    }
2346 
2347    /**
2348     * Updates a column in the current or insert row.
2349     *
2350     * @param columnIndex (1,2,...)
2351     * @param x the value
2352     * @throws SQLException if the result set is closed or not updatable
2353     */
2354    @Override
2355    public void updateClob(int columnIndex, Clob x) throws SQLException {
2356        try {
2357            if (isDebugEnabled()) {
2358                debugCode("updateClob("+columnIndex+", x);");
2359            }
2360            checkClosed();
2361            Value v;
2362            if (x == null) {
2363                v = ValueNull.INSTANCE;
2364            } else {
2365                v = conn.createClob(x.getCharacterStream(), -1);
2366            }
2367            update(columnIndex, v);
2368        } catch (Exception e) {
2369            throw logAndConvert(e);
2370        }
2371    }
2372 
2373    /**
2374     * Updates a column in the current or insert row.
2375     *
2376     * @param columnIndex (1,2,...)
2377     * @param x the value
2378     * @throws SQLException if the result set is closed or not updatable
2379     */
2380    @Override
2381    public void updateClob(int columnIndex, Reader x) throws SQLException {
2382        updateClob(columnIndex, x, -1);
2383    }
2384 
2385    /**
2386     * Updates a column in the current or insert row.
2387     *
2388     * @param columnIndex (1,2,...)
2389     * @param x the value
2390     * @param length the length
2391     * @throws SQLException if the result set is closed or not updatable
2392     */
2393    @Override
2394    public void updateClob(int columnIndex, Reader x, long length)
2395            throws SQLException {
2396        try {
2397            if (isDebugEnabled()) {
2398                debugCode("updateClob("+columnIndex+", x, " + length + "L);");
2399            }
2400            checkClosed();
2401            Value v = conn.createClob(x, length);
2402            update(columnIndex, v);
2403        } catch (Exception e) {
2404            throw logAndConvert(e);
2405        }
2406    }
2407 
2408    /**
2409     * Updates a column in the current or insert row.
2410     *
2411     * @param columnLabel the column label
2412     * @param x the value
2413     * @throws SQLException if the result set is closed or not updatable
2414     */
2415    @Override
2416    public void updateClob(String columnLabel, Clob x) throws SQLException {
2417        try {
2418            if (isDebugEnabled()) {
2419                debugCode("updateClob("+quote(columnLabel)+", x);");
2420            }
2421            checkClosed();
2422            Value v;
2423            if (x == null) {
2424                v = ValueNull.INSTANCE;
2425            } else {
2426                v = conn.createClob(x.getCharacterStream(), -1);
2427            }
2428            update(columnLabel, v);
2429        } catch (Exception e) {
2430            throw logAndConvert(e);
2431        }
2432    }
2433 
2434    /**
2435     * Updates a column in the current or insert row.
2436     *
2437     * @param columnLabel the column label
2438     * @param x the value
2439     * @throws SQLException if the result set is closed or not updatable
2440     */
2441    @Override
2442    public void updateClob(String columnLabel, Reader x) throws SQLException {
2443        updateClob(columnLabel, x, -1);
2444    }
2445 
2446    /**
2447     * Updates a column in the current or insert row.
2448     *
2449     * @param columnLabel the column label
2450     * @param x the value
2451     * @param length the length
2452     * @throws SQLException if the result set is closed or not updatable
2453     */
2454    @Override
2455    public void updateClob(String columnLabel, Reader x, long length)
2456            throws SQLException {
2457        try {
2458            if (isDebugEnabled()) {
2459                debugCode("updateClob("+quote(columnLabel)+", x, " + length + "L);");
2460            }
2461            checkClosed();
2462            Value v = conn.createClob(x, length);
2463            update(columnLabel, v);
2464        } catch (Exception e) {
2465            throw logAndConvert(e);
2466        }
2467    }
2468 
2469    /**
2470     * [Not supported]
2471     */
2472    @Override
2473    public void updateArray(int columnIndex, Array x) throws SQLException {
2474        throw unsupported("setArray");
2475    }
2476 
2477    /**
2478     * [Not supported]
2479     */
2480    @Override
2481    public void updateArray(String columnLabel, Array x) throws SQLException {
2482        throw unsupported("setArray");
2483    }
2484 
2485    /**
2486     * [Not supported] Gets the cursor name if it was defined. This feature is
2487     * superseded by updateX methods. This method throws a SQLException because
2488     * cursor names are not supported.
2489     */
2490    @Override
2491    public String getCursorName() throws SQLException {
2492        throw unsupported("cursorName");
2493    }
2494 
2495    /**
2496     * Gets the current row number. The first row is row 1, the second 2 and so
2497     * on. This method returns 0 before the first and after the last row.
2498     *
2499     * @return the row number
2500     */
2501    @Override
2502    public int getRow() throws SQLException {
2503        try {
2504            debugCodeCall("getRow");
2505            checkClosed();
2506            int rowId = result.getRowId();
2507            if (rowId >= result.getRowCount()) {
2508                return 0;
2509            }
2510            return rowId + 1;
2511        } catch (Exception e) {
2512            throw logAndConvert(e);
2513        }
2514    }
2515 
2516    /**
2517     * Gets the result set concurrency. Result sets are only updatable if the
2518     * statement was created with updatable concurrency, and if the result set
2519     * contains all columns of the primary key or of a unique index of a table.
2520     *
2521     * @return ResultSet.CONCUR_UPDATABLE if the result set is updatable, or
2522     *         ResultSet.CONCUR_READ_ONLY otherwise
2523     */
2524    @Override
2525    public int getConcurrency() throws SQLException {
2526        try {
2527            debugCodeCall("getConcurrency");
2528            checkClosed();
2529            if (!updatable) {
2530                return ResultSet.CONCUR_READ_ONLY;
2531            }
2532            UpdatableRow row = new UpdatableRow(conn, result);
2533            return row.isUpdatable() ? ResultSet.CONCUR_UPDATABLE
2534                    : ResultSet.CONCUR_READ_ONLY;
2535        } catch (Exception e) {
2536            throw logAndConvert(e);
2537        }
2538    }
2539 
2540    /**
2541     * Gets the fetch direction.
2542     *
2543     * @return the direction: FETCH_FORWARD
2544     */
2545    @Override
2546    public int getFetchDirection() throws SQLException {
2547        try {
2548            debugCodeCall("getFetchDirection");
2549            checkClosed();
2550            return ResultSet.FETCH_FORWARD;
2551        } catch (Exception e) {
2552            throw logAndConvert(e);
2553        }
2554    }
2555 
2556    /**
2557     * Gets the number of rows suggested to read in one step.
2558     *
2559     * @return the current fetch size
2560     */
2561    @Override
2562    public int getFetchSize() throws SQLException {
2563        try {
2564            debugCodeCall("getFetchSize");
2565            checkClosed();
2566            return result.getFetchSize();
2567        } catch (Exception e) {
2568            throw logAndConvert(e);
2569        }
2570    }
2571 
2572    /**
2573     * Sets the number of rows suggested to read in one step. This value cannot
2574     * be higher than the maximum rows (setMaxRows) set by the statement or
2575     * prepared statement, otherwise an exception is throws. Setting the value
2576     * to 0 will set the default value. The default value can be changed using
2577     * the system property h2.serverResultSetFetchSize.
2578     *
2579     * @param rows the number of rows
2580     */
2581    @Override
2582    public void setFetchSize(int rows) throws SQLException {
2583        try {
2584            debugCodeCall("setFetchSize", rows);
2585            checkClosed();
2586            if (rows < 0) {
2587                throw DbException.getInvalidValueException("rows", rows);
2588            } else if (rows > 0) {
2589                if (stat != null) {
2590                    int maxRows = stat.getMaxRows();
2591                    if (maxRows > 0 && rows > maxRows) {
2592                        throw DbException.getInvalidValueException("rows", rows);
2593                    }
2594                }
2595            } else {
2596                rows = SysProperties.SERVER_RESULT_SET_FETCH_SIZE;
2597            }
2598            result.setFetchSize(rows);
2599        } catch (Exception e) {
2600            throw logAndConvert(e);
2601        }
2602    }
2603 
2604    /**
2605     * [Not supported]
2606     * Sets (changes) the fetch direction for this result set. This method
2607     * should only be called for scrollable result sets, otherwise it will throw
2608     * an exception (no matter what direction is used).
2609     *
2610     * @param direction the new fetch direction
2611     * @throws SQLException Unsupported Feature if the method is called for a
2612     *             forward-only result set
2613     */
2614    @Override
2615    public void setFetchDirection(int direction) throws SQLException {
2616        throw unsupported("setFetchDirection");
2617    }
2618 
2619    /**
2620     * Get the result set type.
2621     *
2622     * @return the result set type (TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE
2623     *         or TYPE_SCROLL_SENSITIVE)
2624     * @throws SQLException if the column is not found or if the result set is
2625     *             closed
2626     */
2627    @Override
2628    public int getType() throws SQLException {
2629        try {
2630            debugCodeCall("getType");
2631            checkClosed();
2632            return stat == null ? ResultSet.TYPE_FORWARD_ONLY : stat.resultSetType;
2633        } catch (Exception e) {
2634            throw logAndConvert(e);
2635        }
2636    }
2637 
2638    /**
2639     * Checks if the current position is before the first row, that means next()
2640     * was not called yet, and there is at least one row.
2641     *
2642     * @return if there are results and the current position is before the first
2643     *         row
2644     * @throws SQLException if the result set is closed
2645     */
2646    @Override
2647    public boolean isBeforeFirst() throws SQLException {
2648        try {
2649            debugCodeCall("isBeforeFirst");
2650            checkClosed();
2651            int row = result.getRowId();
2652            int count = result.getRowCount();
2653            return count > 0 && row < 0;
2654        } catch (Exception e) {
2655            throw logAndConvert(e);
2656        }
2657    }
2658 
2659    /**
2660     * Checks if the current position is after the last row, that means next()
2661     * was called and returned false, and there was at least one row.
2662     *
2663     * @return if there are results and the current position is after the last
2664     *         row
2665     * @throws SQLException if the result set is closed
2666     */
2667    @Override
2668    public boolean isAfterLast() throws SQLException {
2669        try {
2670            debugCodeCall("isAfterLast");
2671            checkClosed();
2672            int row = result.getRowId();
2673            int count = result.getRowCount();
2674            return count > 0 && row >= count;
2675        } catch (Exception e) {
2676            throw logAndConvert(e);
2677        }
2678    }
2679 
2680    /**
2681     * Checks if the current position is row 1, that means next() was called
2682     * once and returned true.
2683     *
2684     * @return if the current position is the first row
2685     * @throws SQLException if the result set is closed
2686     */
2687    @Override
2688    public boolean isFirst() throws SQLException {
2689        try {
2690            debugCodeCall("isFirst");
2691            checkClosed();
2692            int row = result.getRowId();
2693            return row == 0 && row < result.getRowCount();
2694        } catch (Exception e) {
2695            throw logAndConvert(e);
2696        }
2697    }
2698 
2699    /**
2700     * Checks if the current position is the last row, that means next() was
2701     * called and did not yet returned false, but will in the next call.
2702     *
2703     * @return if the current position is the last row
2704     * @throws SQLException if the result set is closed
2705     */
2706    @Override
2707    public boolean isLast() throws SQLException {
2708        try {
2709            debugCodeCall("isLast");
2710            checkClosed();
2711            int row = result.getRowId();
2712            return row >= 0 && row == result.getRowCount() - 1;
2713        } catch (Exception e) {
2714            throw logAndConvert(e);
2715        }
2716    }
2717 
2718    /**
2719     * Moves the current position to before the first row, that means resets the
2720     * result set.
2721     *
2722     * @throws SQLException if the result set is closed
2723     */
2724    @Override
2725    public void beforeFirst() throws SQLException {
2726        try {
2727            debugCodeCall("beforeFirst");
2728            checkClosed();
2729            if (result.getRowId() >= 0) {
2730                resetResult();
2731            }
2732        } catch (Exception e) {
2733            throw logAndConvert(e);
2734        }
2735    }
2736 
2737    /**
2738     * Moves the current position to after the last row, that means after the
2739     * end.
2740     *
2741     * @throws SQLException if the result set is closed
2742     */
2743    @Override
2744    public void afterLast() throws SQLException {
2745        try {
2746            debugCodeCall("afterLast");
2747            checkClosed();
2748            while (nextRow()) {
2749                // nothing
2750            }
2751        } catch (Exception e) {
2752            throw logAndConvert(e);
2753        }
2754}
2755 
2756    /**
2757     * Moves the current position to the first row. This is the same as calling
2758     * beforeFirst() followed by next().
2759     *
2760     * @return true if there is a row available, false if not
2761     * @throws SQLException if the result set is closed
2762     */
2763    @Override
2764    public boolean first() throws SQLException {
2765        try {
2766            debugCodeCall("first");
2767            checkClosed();
2768            if (result.getRowId() < 0) {
2769                return nextRow();
2770            }
2771            resetResult();
2772            return nextRow();
2773        } catch (Exception e) {
2774            throw logAndConvert(e);
2775        }
2776    }
2777 
2778    /**
2779     * Moves the current position to the last row.
2780     *
2781     * @return true if there is a row available, false if not
2782     * @throws SQLException if the result set is closed
2783     */
2784    @Override
2785    public boolean last() throws SQLException {
2786        try {
2787            debugCodeCall("last");
2788            checkClosed();
2789            return absolute(-1);
2790        } catch (Exception e) {
2791            throw logAndConvert(e);
2792        }
2793    }
2794 
2795    /**
2796     * Moves the current position to a specific row.
2797     *
2798     * @param rowNumber the row number. 0 is not allowed, 1 means the first row,
2799     *            2 the second. -1 means the last row, -2 the row before the
2800     *            last row. If the value is too large, the position is moved
2801     *            after the last row, if if the value is too small it is moved
2802     *            before the first row.
2803     * @return true if there is a row available, false if not
2804     * @throws SQLException if the result set is closed
2805     */
2806    @Override
2807    public boolean absolute(int rowNumber) throws SQLException {
2808        try {
2809            debugCodeCall("absolute", rowNumber);
2810            checkClosed();
2811            if (rowNumber < 0) {
2812                rowNumber = result.getRowCount() + rowNumber + 1;
2813            } else if (rowNumber > result.getRowCount() + 1) {
2814                rowNumber = result.getRowCount() + 1;
2815            }
2816            if (rowNumber <= result.getRowId()) {
2817                resetResult();
2818            }
2819            while (result.getRowId() + 1 < rowNumber) {
2820                nextRow();
2821            }
2822            int row = result.getRowId();
2823            return row >= 0 && row < result.getRowCount();
2824        } catch (Exception e) {
2825            throw logAndConvert(e);
2826        }
2827    }
2828 
2829    /**
2830     * Moves the current position to a specific row relative to the current row.
2831     *
2832     * @param rowCount 0 means don't do anything, 1 is the next row, -1 the
2833     *            previous. If the value is too large, the position is moved
2834     *            after the last row, if if the value is too small it is moved
2835     *            before the first row.
2836     * @return true if there is a row available, false if not
2837     * @throws SQLException if the result set is closed
2838     */
2839    @Override
2840    public boolean relative(int rowCount) throws SQLException {
2841        try {
2842            debugCodeCall("relative", rowCount);
2843            checkClosed();
2844            int row = result.getRowId() + 1 + rowCount;
2845            if (row < 0) {
2846                row = 0;
2847            } else if (row > result.getRowCount()) {
2848                row = result.getRowCount() + 1;
2849            }
2850            return absolute(row);
2851        } catch (Exception e) {
2852            throw logAndConvert(e);
2853        }
2854    }
2855 
2856    /**
2857     * Moves the cursor to the last row, or row before first row if the current
2858     * position is the first row.
2859     *
2860     * @return true if there is a row available, false if not
2861     * @throws SQLException if the result set is closed
2862     */
2863    @Override
2864    public boolean previous() throws SQLException {
2865        try {
2866            debugCodeCall("previous");
2867            checkClosed();
2868            return relative(-1);
2869        } catch (Exception e) {
2870            throw logAndConvert(e);
2871        }
2872    }
2873 
2874    /**
2875     * Moves the current position to the insert row. The current row is
2876     * remembered.
2877     *
2878     * @throws SQLException if the result set is closed or is not updatable
2879     */
2880    @Override
2881    public void moveToInsertRow() throws SQLException {
2882        try {
2883            debugCodeCall("moveToInsertRow");
2884            checkUpdatable();
2885            insertRow = new Value[columnCount];
2886        } catch (Exception e) {
2887            throw logAndConvert(e);
2888        }
2889    }
2890 
2891    /**
2892     * Moves the current position to the current row.
2893     *
2894     * @throws SQLException if the result set is closed or is not updatable
2895     */
2896    @Override
2897    public void moveToCurrentRow() throws SQLException {
2898        try {
2899            debugCodeCall("moveToCurrentRow");
2900            checkUpdatable();
2901            insertRow = null;
2902        } catch (Exception e) {
2903            throw logAndConvert(e);
2904        }
2905    }
2906 
2907    /**
2908     * Detects if the row was updated (by somebody else or the caller).
2909     *
2910     * @return false because this driver does not detect this
2911     */
2912    @Override
2913    public boolean rowUpdated() throws SQLException {
2914        try {
2915            debugCodeCall("rowUpdated");
2916            return false;
2917        } catch (Exception e) {
2918            throw logAndConvert(e);
2919        }
2920    }
2921 
2922    /**
2923     * Detects if the row was inserted.
2924     *
2925     * @return false because this driver does not detect this
2926     */
2927    @Override
2928    public boolean rowInserted() throws SQLException {
2929        try {
2930            debugCodeCall("rowInserted");
2931            return false;
2932        } catch (Exception e) {
2933            throw logAndConvert(e);
2934        }
2935    }
2936 
2937    /**
2938     * Detects if the row was deleted (by somebody else or the caller).
2939     *
2940     * @return false because this driver does not detect this
2941     */
2942    @Override
2943    public boolean rowDeleted() throws SQLException {
2944        try {
2945            debugCodeCall("rowDeleted");
2946            return false;
2947        } catch (Exception e) {
2948            throw logAndConvert(e);
2949        }
2950    }
2951 
2952    /**
2953     * Inserts the current row. The current position must be the insert row.
2954     *
2955     * @throws SQLException if the result set is closed or if not on the insert
2956     *             row, or if the result set it not updatable
2957     */
2958    @Override
2959    public void insertRow() throws SQLException {
2960        try {
2961            debugCodeCall("insertRow");
2962            checkUpdatable();
2963            if (insertRow == null) {
2964                throw DbException.get(ErrorCode.NOT_ON_UPDATABLE_ROW);
2965            }
2966            getUpdatableRow().insertRow(insertRow);
2967            insertRow = null;
2968        } catch (Exception e) {
2969            throw logAndConvert(e);
2970        }
2971    }
2972 
2973    /**
2974     * Updates the current row.
2975     *
2976     * @throws SQLException if the result set is closed, if the current row is
2977     *             the insert row or if not on a valid row, or if the result set
2978     *             it not updatable
2979     */
2980    @Override
2981    public void updateRow() throws SQLException {
2982        try {
2983            debugCodeCall("updateRow");
2984            checkUpdatable();
2985            if (insertRow != null) {
2986                throw DbException.get(ErrorCode.NOT_ON_UPDATABLE_ROW);
2987            }
2988            checkOnValidRow();
2989            if (updateRow != null) {
2990                UpdatableRow row = getUpdatableRow();
2991                Value[] current = new Value[columnCount];
2992                for (int i = 0; i < updateRow.length; i++) {
2993                    current[i] = get(i + 1);
2994                }
2995                row.updateRow(current, updateRow);
2996                for (int i = 0; i < updateRow.length; i++) {
2997                    if (updateRow[i] == null) {
2998                        updateRow[i] = current[i];
2999                    }
3000                }
3001                Value[] patch = row.readRow(updateRow);
3002                patchCurrentRow(patch);
3003                updateRow = null;
3004            }
3005        } catch (Exception e) {
3006            throw logAndConvert(e);
3007        }
3008    }
3009 
3010    /**
3011     * Deletes the current row.
3012     *
3013     * @throws SQLException if the result set is closed, if the current row is
3014     *             the insert row or if not on a valid row, or if the result set
3015     *             it not updatable
3016     */
3017    @Override
3018    public void deleteRow() throws SQLException {
3019        try {
3020            debugCodeCall("deleteRow");
3021            checkUpdatable();
3022            if (insertRow != null) {
3023                throw DbException.get(ErrorCode.NOT_ON_UPDATABLE_ROW);
3024            }
3025            checkOnValidRow();
3026            getUpdatableRow().deleteRow(result.currentRow());
3027            updateRow = null;
3028        } catch (Exception e) {
3029            throw logAndConvert(e);
3030        }
3031    }
3032 
3033    /**
3034     * Re-reads the current row from the database.
3035     *
3036     * @throws SQLException if the result set is closed or if the current row is
3037     *             the insert row or if the row has been deleted or if not on a
3038     *             valid row
3039     */
3040    @Override
3041    public void refreshRow() throws SQLException {
3042        try {
3043            debugCodeCall("refreshRow");
3044            checkClosed();
3045            if (insertRow != null) {
3046                throw DbException.get(ErrorCode.NO_DATA_AVAILABLE);
3047            }
3048            checkOnValidRow();
3049            patchCurrentRow(getUpdatableRow().readRow(result.currentRow()));
3050            updateRow = null;
3051        } catch (Exception e) {
3052            throw logAndConvert(e);
3053        }
3054    }
3055 
3056    /**
3057     * Cancels updating a row.
3058     *
3059     * @throws SQLException if the result set is closed or if the current row is
3060     *             the insert row
3061     */
3062    @Override
3063    public void cancelRowUpdates() throws SQLException {
3064        try {
3065            debugCodeCall("cancelRowUpdates");
3066            checkClosed();
3067            if (insertRow != null) {
3068                throw DbException.get(ErrorCode.NO_DATA_AVAILABLE);
3069            }
3070            updateRow = null;
3071        } catch (Exception e) {
3072            throw logAndConvert(e);
3073        }
3074    }
3075 
3076    // =============================================================
3077 
3078    private UpdatableRow getUpdatableRow() throws SQLException {
3079        UpdatableRow row = new UpdatableRow(conn, result);
3080        if (!row.isUpdatable()) {
3081            throw DbException.get(ErrorCode.RESULT_SET_NOT_UPDATABLE);
3082        }
3083        return row;
3084    }
3085 
3086    private int getColumnIndex(String columnLabel) {
3087        checkClosed();
3088        if (columnLabel == null) {
3089            throw DbException.getInvalidValueException("columnLabel", null);
3090        }
3091        if (columnCount >= 3) {
3092            // use a hash table if more than 2 columns
3093            if (columnLabelMap == null) {
3094                HashMap<String, Integer> map = New.hashMap(columnCount);
3095                // column labels have higher priority
3096                for (int i = 0; i < columnCount; i++) {
3097                    String c = StringUtils.toUpperEnglish(result.getAlias(i));
3098                    mapColumn(map, c, i);
3099                }
3100                for (int i = 0; i < columnCount; i++) {
3101                    String colName = result.getColumnName(i);
3102                    if (colName != null) {
3103                        colName = StringUtils.toUpperEnglish(colName);
3104                        mapColumn(map, colName, i);
3105                        String tabName = result.getTableName(i);
3106                        if (tabName != null) {
3107                            colName = StringUtils.toUpperEnglish(tabName) + "." + colName;
3108                            mapColumn(map, colName, i);
3109                        }
3110                    }
3111                }
3112                // assign at the end so concurrent access is supported
3113                columnLabelMap = map;
3114                if (preparedStatement != null) {
3115                    preparedStatement.setCachedColumnLabelMap(columnLabelMap);
3116                }
3117            }
3118            Integer index = columnLabelMap.get(StringUtils.toUpperEnglish(columnLabel));
3119            if (index == null) {
3120                throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1, columnLabel);
3121            }
3122            return index.intValue() + 1;
3123        }
3124        for (int i = 0; i < columnCount; i++) {
3125            if (columnLabel.equalsIgnoreCase(result.getAlias(i))) {
3126                return i + 1;
3127            }
3128        }
3129        int idx = columnLabel.indexOf('.');
3130        if (idx > 0) {
3131            String table = columnLabel.substring(0, idx);
3132            String col = columnLabel.substring(idx+1);
3133            for (int i = 0; i < columnCount; i++) {
3134                if (table.equalsIgnoreCase(result.getTableName(i)) &&
3135                        col.equalsIgnoreCase(result.getColumnName(i))) {
3136                    return i + 1;
3137                }
3138            }
3139        } else {
3140            for (int i = 0; i < columnCount; i++) {
3141                if (columnLabel.equalsIgnoreCase(result.getColumnName(i))) {
3142                    return i + 1;
3143                }
3144            }
3145        }
3146        throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1, columnLabel);
3147    }
3148 
3149    private static void mapColumn(HashMap<String, Integer> map, String label,
3150            int index) {
3151        // put the index (usually that's the only operation)
3152        Integer old = map.put(label, index);
3153        if (old != null) {
3154            // if there was a clash (which is seldom),
3155            // put the old one back
3156            map.put(label, old);
3157        }
3158    }
3159 
3160    private void checkColumnIndex(int columnIndex) {
3161        checkClosed();
3162        if (columnIndex < 1 || columnIndex > columnCount) {
3163            throw DbException.getInvalidValueException("columnIndex", columnIndex);
3164        }
3165    }
3166 
3167    /**
3168     * Check if this result set is closed.
3169     *
3170     * @throws DbException if it is closed
3171     */
3172    void checkClosed() {
3173        if (result == null) {
3174            throw DbException.get(ErrorCode.OBJECT_CLOSED);
3175        }
3176        if (stat != null) {
3177            stat.checkClosed();
3178        }
3179        if (conn != null) {
3180            conn.checkClosed();
3181        }
3182    }
3183 
3184    private void checkOnValidRow() {
3185        if (result.getRowId() < 0 || result.getRowId() >= result.getRowCount()) {
3186            throw DbException.get(ErrorCode.NO_DATA_AVAILABLE);
3187        }
3188    }
3189 
3190    private Value get(int columnIndex) {
3191        checkColumnIndex(columnIndex);
3192        checkOnValidRow();
3193        Value[] list;
3194        if (patchedRows == null) {
3195            list = result.currentRow();
3196        } else {
3197            list = patchedRows.get(result.getRowId());
3198            if (list == null) {
3199                list = result.currentRow();
3200            }
3201        }
3202        Value value = list[columnIndex - 1];
3203        wasNull = value == ValueNull.INSTANCE;
3204        return value;
3205    }
3206 
3207    private Value get(String columnLabel) {
3208        int columnIndex = getColumnIndex(columnLabel);
3209        return get(columnIndex);
3210    }
3211 
3212    private void update(String columnLabel, Value v) {
3213        int columnIndex = getColumnIndex(columnLabel);
3214        update(columnIndex, v);
3215    }
3216 
3217    private void update(int columnIndex, Value v) {
3218        checkUpdatable();
3219        checkColumnIndex(columnIndex);
3220        if (insertRow != null) {
3221            insertRow[columnIndex - 1] = v;
3222        } else {
3223            if (updateRow == null) {
3224                updateRow = new Value[columnCount];
3225            }
3226            updateRow[columnIndex - 1] = v;
3227        }
3228    }
3229 
3230    private boolean nextRow() {
3231        boolean next = result.next();
3232        if (!next && !scrollable) {
3233            result.close();
3234        }
3235        return next;
3236    }
3237 
3238    private void resetResult() {
3239        if (!scrollable) {
3240            throw DbException.get(ErrorCode.RESULT_SET_NOT_SCROLLABLE);
3241        }
3242        result.reset();
3243    }
3244 
3245    /**
3246     * [Not supported] Returns the value of the specified column as a row id.
3247     *
3248     * @param columnIndex (1,2,...)
3249     */
3250    @Override
3251    public RowId getRowId(int columnIndex) throws SQLException {
3252        throw unsupported("rowId");
3253    }
3254 
3255    /**
3256     * [Not supported] Returns the value of the specified column as a row id.
3257     *
3258     * @param columnLabel the column label
3259     */
3260    @Override
3261    public RowId getRowId(String columnLabel) throws SQLException {
3262        throw unsupported("rowId");
3263    }
3264 
3265    /**
3266     * [Not supported] Updates a column in the current or insert row.
3267     *
3268     * @param columnIndex (1,2,...)
3269     * @param x the value
3270     */
3271    @Override
3272    public void updateRowId(int columnIndex, RowId x) throws SQLException {
3273        throw unsupported("rowId");
3274    }
3275 
3276    /**
3277     * [Not supported] Updates a column in the current or insert row.
3278     *
3279     * @param columnLabel the column label
3280     * @param x the value
3281     */
3282    @Override
3283    public void updateRowId(String columnLabel, RowId x) throws SQLException {
3284        throw unsupported("rowId");
3285    }
3286 
3287    /**
3288     * Returns the current result set holdability.
3289     *
3290     * @return the holdability
3291     * @throws SQLException if the connection is closed
3292     */
3293    @Override
3294    public int getHoldability() throws SQLException {
3295        try {
3296            debugCodeCall("getHoldability");
3297            checkClosed();
3298            return conn.getHoldability();
3299        } catch (Exception e) {
3300            throw logAndConvert(e);
3301        }
3302    }
3303 
3304    /**
3305     * Returns whether this result set is closed.
3306     *
3307     * @return true if the result set is closed
3308     */
3309    @Override
3310    public boolean isClosed() throws SQLException {
3311        try {
3312            debugCodeCall("isClosed");
3313            return result == null;
3314        } catch (Exception e) {
3315            throw logAndConvert(e);
3316        }
3317    }
3318 
3319    /**
3320     * Updates a column in the current or insert row.
3321     *
3322     * @param columnIndex (1,2,...)
3323     * @param x the value
3324     * @throws SQLException if the result set is closed or not updatable
3325     */
3326    @Override
3327    public void updateNString(int columnIndex, String x) throws SQLException {
3328        try {
3329            if (isDebugEnabled()) {
3330                debugCode("updateNString("+columnIndex+", "+quote(x)+");");
3331            }
3332            update(columnIndex, x == null ? (Value)
3333                    ValueNull.INSTANCE : ValueString.get(x));
3334        } catch (Exception e) {
3335            throw logAndConvert(e);
3336        }
3337    }
3338 
3339    /**
3340     * Updates a column in the current or insert row.
3341     *
3342     * @param columnLabel the column label
3343     * @param x the value
3344     * @throws SQLException if the result set is closed or not updatable
3345     */
3346    @Override
3347    public void updateNString(String columnLabel, String x) throws SQLException {
3348        try {
3349            if (isDebugEnabled()) {
3350                debugCode("updateNString("+quote(columnLabel)+", "+quote(x)+");");
3351            }
3352            update(columnLabel, x == null ? (Value) ValueNull.INSTANCE :
3353                    ValueString.get(x));
3354        } catch (Exception e) {
3355            throw logAndConvert(e);
3356        }
3357    }
3358 
3359    /**
3360     * [Not supported]
3361     */
3362    @Override
3363    public void updateNClob(int columnIndex, NClob x) throws SQLException {
3364        throw unsupported("NClob");
3365    }
3366 
3367    /**
3368     * Updates a column in the current or insert row.
3369     *
3370     * @param columnIndex (1,2,...)
3371     * @param x the value
3372     * @throws SQLException if the result set is closed or not updatable
3373     */
3374    @Override
3375    public void updateNClob(int columnIndex, Reader x) throws SQLException {
3376        updateClob(columnIndex, x, -1);
3377    }
3378 
3379    /**
3380     * Updates a column in the current or insert row.
3381     *
3382     * @param columnIndex (1,2,...)
3383     * @param x the value
3384     * @param length the length
3385     * @throws SQLException if the result set is closed or not updatable
3386     */
3387    @Override
3388    public void updateNClob(int columnIndex, Reader x, long length)
3389            throws SQLException {
3390        updateClob(columnIndex, x, length);
3391    }
3392 
3393    /**
3394     * Updates a column in the current or insert row.
3395     *
3396     * @param columnLabel the column label
3397     * @param x the value
3398     * @throws SQLException if the result set is closed or not updatable
3399     */
3400    @Override
3401    public void updateNClob(String columnLabel, Reader x) throws SQLException {
3402        updateClob(columnLabel, x, -1);
3403    }
3404 
3405    /**
3406     * Updates a column in the current or insert row.
3407     *
3408     * @param columnLabel the column label
3409     * @param x the value
3410     * @param length the length
3411     * @throws SQLException if the result set is closed or not updatable
3412     */
3413    @Override
3414    public void updateNClob(String columnLabel, Reader x, long length)
3415            throws SQLException {
3416        updateClob(columnLabel, x, length);
3417    }
3418 
3419    /**
3420     * [Not supported]
3421     */
3422    @Override
3423    public void updateNClob(String columnLabel, NClob x) throws SQLException {
3424        throw unsupported("NClob");
3425    }
3426 
3427    /**
3428     * Returns the value of the specified column as a Clob.
3429     *
3430     * @param columnIndex (1,2,...)
3431     * @return the value
3432     * @throws SQLException if the column is not found or if the result set is
3433     *             closed
3434     */
3435    @Override
3436    public NClob getNClob(int columnIndex) throws SQLException {
3437        try {
3438            int id = getNextId(TraceObject.CLOB);
3439            debugCodeAssign("NClob", TraceObject.CLOB, id, "getNClob(" + columnIndex + ")");
3440            Value v = get(columnIndex);
3441            return v == ValueNull.INSTANCE ? null : new JdbcClob(conn, v, id);
3442        } catch (Exception e) {
3443            throw logAndConvert(e);
3444        }
3445    }
3446 
3447    /**
3448     * Returns the value of the specified column as a Clob.
3449     *
3450     * @param columnLabel the column label
3451     * @return the value
3452     * @throws SQLException if the column is not found or if the result set is
3453     *             closed
3454     */
3455    @Override
3456    public NClob getNClob(String columnLabel) throws SQLException {
3457        try {
3458            int id = getNextId(TraceObject.CLOB);
3459            debugCodeAssign("NClob", TraceObject.CLOB, id, "getNClob(" + columnLabel + ")");
3460            Value v = get(columnLabel);
3461            return v == ValueNull.INSTANCE ? null : new JdbcClob(conn, v, id);
3462        } catch (Exception e) {
3463            throw logAndConvert(e);
3464        }
3465    }
3466 
3467    /**
3468     * [Not supported] Returns the value of the specified column as a SQLXML
3469     * object.
3470     */
3471    @Override
3472    public SQLXML getSQLXML(int columnIndex) throws SQLException {
3473        throw unsupported("SQLXML");
3474    }
3475 
3476    /**
3477     * [Not supported] Returns the value of the specified column as a SQLXML
3478     * object.
3479     */
3480    @Override
3481    public SQLXML getSQLXML(String columnLabel) throws SQLException {
3482        throw unsupported("SQLXML");
3483    }
3484 
3485    /**
3486     * [Not supported] Updates a column in the current or insert row.
3487     */
3488    @Override
3489    public void updateSQLXML(int columnIndex, SQLXML xmlObject)
3490            throws SQLException {
3491        throw unsupported("SQLXML");
3492    }
3493 
3494    /**
3495     * [Not supported] Updates a column in the current or insert row.
3496     */
3497    @Override
3498    public void updateSQLXML(String columnLabel, SQLXML xmlObject)
3499            throws SQLException {
3500        throw unsupported("SQLXML");
3501    }
3502 
3503    /**
3504     * Returns the value of the specified column as a String.
3505     *
3506     * @param columnIndex (1,2,...)
3507     * @return the value
3508     * @throws SQLException if the column is not found or if the result set is
3509     *             closed
3510     */
3511    @Override
3512    public String getNString(int columnIndex) throws SQLException {
3513        try {
3514            debugCodeCall("getNString", columnIndex);
3515            return get(columnIndex).getString();
3516        } catch (Exception e) {
3517            throw logAndConvert(e);
3518        }
3519    }
3520 
3521    /**
3522     * Returns the value of the specified column as a String.
3523     *
3524     * @param columnLabel the column label
3525     * @return the value
3526     * @throws SQLException if the column is not found or if the result set is
3527     *             closed
3528     */
3529    @Override
3530    public String getNString(String columnLabel) throws SQLException {
3531        try {
3532            debugCodeCall("getNString", columnLabel);
3533            return get(columnLabel).getString();
3534        } catch (Exception e) {
3535            throw logAndConvert(e);
3536        }
3537    }
3538 
3539    /**
3540     * Returns the value of the specified column as a reader.
3541     *
3542     * @param columnIndex (1,2,...)
3543     * @return the value
3544     * @throws SQLException if the column is not found or if the result set is
3545     *             closed
3546     */
3547    @Override
3548    public Reader getNCharacterStream(int columnIndex) throws SQLException {
3549        try {
3550            debugCodeCall("getNCharacterStream", columnIndex);
3551            return get(columnIndex).getReader();
3552        } catch (Exception e) {
3553            throw logAndConvert(e);
3554        }
3555    }
3556 
3557    /**
3558     * Returns the value of the specified column as a reader.
3559     *
3560     * @param columnLabel the column label
3561     * @return the value
3562     * @throws SQLException if the column is not found or if the result set is
3563     *             closed
3564     */
3565    @Override
3566    public Reader getNCharacterStream(String columnLabel) throws SQLException {
3567        try {
3568            debugCodeCall("getNCharacterStream", columnLabel);
3569            return get(columnLabel).getReader();
3570        } catch (Exception e) {
3571            throw logAndConvert(e);
3572        }
3573    }
3574 
3575    /**
3576     * Updates a column in the current or insert row.
3577     *
3578     * @param columnIndex (1,2,...)
3579     * @param x the value
3580     * @throws SQLException if the result set is closed or not updatable
3581     */
3582    @Override
3583    public void updateNCharacterStream(int columnIndex, Reader x)
3584            throws SQLException {
3585        updateNCharacterStream(columnIndex, x, -1);
3586    }
3587 
3588    /**
3589     * Updates a column in the current or insert row.
3590     *
3591     * @param columnIndex (1,2,...)
3592     * @param x the value
3593     * @param length the number of characters
3594     * @throws SQLException if the result set is closed or not updatable
3595     */
3596    @Override
3597    public void updateNCharacterStream(int columnIndex, Reader x, long length)
3598            throws SQLException {
3599        try {
3600            if (isDebugEnabled()) {
3601                debugCode("updateNCharacterStream("+columnIndex+", x, "+length+"L);");
3602            }
3603            checkClosed();
3604            Value v = conn.createClob(x, length);
3605            update(columnIndex, v);
3606        } catch (Exception e) {
3607            throw logAndConvert(e);
3608        }
3609    }
3610 
3611    /**
3612     * Updates a column in the current or insert row.
3613     *
3614     * @param columnLabel the column label
3615     * @param x the value
3616     * @throws SQLException if the result set is closed or not updatable
3617     */
3618    @Override
3619    public void updateNCharacterStream(String columnLabel, Reader x)
3620            throws SQLException {
3621        updateNCharacterStream(columnLabel, x, -1);
3622    }
3623 
3624    /**
3625     * Updates a column in the current or insert row.
3626     *
3627     * @param columnLabel the column label
3628     * @param x the value
3629     * @param length the number of characters
3630     * @throws SQLException if the result set is closed or not updatable
3631     */
3632    @Override
3633    public void updateNCharacterStream(String columnLabel, Reader x, long length)
3634            throws SQLException {
3635        try {
3636            if (isDebugEnabled()) {
3637                debugCode("updateNCharacterStream("+quote(columnLabel)+", x, "+length+"L);");
3638            }
3639            checkClosed();
3640            Value v = conn.createClob(x, length);
3641            update(columnLabel, v);
3642        } catch (Exception e) {
3643            throw logAndConvert(e);
3644        }
3645    }
3646 
3647    /**
3648     * Return an object of this class if possible.
3649     *
3650     * @param iface the class
3651     * @return this
3652     */
3653    @Override
3654    @SuppressWarnings("unchecked")
3655    public <T> T unwrap(Class<T> iface) throws SQLException {
3656        if (isWrapperFor(iface)) {
3657            return (T) this;
3658        }
3659        throw DbException.getInvalidValueException("iface", iface);
3660    }
3661 
3662    /**
3663     * Checks if unwrap can return an object of this class.
3664     *
3665     * @param iface the class
3666     * @return whether or not the interface is assignable from this class
3667     */
3668    @Override
3669    public boolean isWrapperFor(Class<?> iface) throws SQLException {
3670        return iface != null && iface.isAssignableFrom(getClass());
3671    }
3672 
3673    /**
3674     * [Not supported]
3675     *
3676     * @param columnIndex the column index (1, 2, ...)
3677     * @param type the class of the returned value
3678     */
3679//## Java 1.7 ##
3680    @Override
3681    public <T> T getObject(int columnIndex, Class<T> type) {
3682        return null;
3683    }
3684//*/
3685 
3686    /**
3687     * [Not supported]
3688     *
3689     * @param columnName the column name
3690     * @param type the class of the returned value
3691     */
3692//## Java 1.7 ##
3693    @Override
3694    public <T> T getObject(String columnName, Class<T> type) {
3695        return null;
3696    }
3697//*/
3698 
3699    /**
3700     * INTERNAL
3701     */
3702    @Override
3703    public String toString() {
3704        return getTraceObjectName() + ": " + result;
3705    }
3706 
3707    private void patchCurrentRow(Value[] row) {
3708        boolean changed = false;
3709        Value[] current = result.currentRow();
3710        CompareMode mode = conn.getCompareMode();
3711        for (int i = 0; i < row.length; i++) {
3712            if (row[i].compareTo(current[i], mode) != 0) {
3713                changed = true;
3714                break;
3715            }
3716        }
3717        if (patchedRows == null) {
3718            patchedRows = New.hashMap();
3719        }
3720        Integer rowId = result.getRowId();
3721        if (!changed) {
3722            patchedRows.remove(rowId);
3723        } else {
3724            patchedRows.put(rowId, row);
3725        }
3726    }
3727 
3728    private Value convertToUnknownValue(Object x) {
3729        checkClosed();
3730        return DataType.convertToValue(conn.getSession(), x, Value.UNKNOWN);
3731    }
3732 
3733    private void checkUpdatable() {
3734        checkClosed();
3735        if (!updatable) {
3736            throw DbException.get(ErrorCode.RESULT_SET_READONLY);
3737        }
3738    }
3739 
3740}

[all classes][org.h2.jdbc]
EMMA 2.0.5312 (C) Vladimir Roubtsov