0001: /*
0002: Copyright (C) 2002-2007 MySQL AB
0003:
0004: This program is free software; you can redistribute it and/or modify
0005: it under the terms of version 2 of the GNU General Public License as
0006: published by the Free Software Foundation.
0007:
0008: There are special exceptions to the terms and conditions of the GPL
0009: as it is applied to this software. View the full text of the
0010: exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
0011: software distribution.
0012:
0013: This program is distributed in the hope that it will be useful,
0014: but WITHOUT ANY WARRANTY; without even the implied warranty of
0015: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0016: GNU General Public License for more details.
0017:
0018: You should have received a copy of the GNU General Public License
0019: along with this program; if not, write to the Free Software
0020: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0021:
0022:
0023:
0024: */
0025: package com.mysql.jdbc;
0026:
0027: import com.mysql.jdbc.PreparedStatement.ParseInfo;
0028: import com.mysql.jdbc.exceptions.NotYetImplementedException;
0029: import com.mysql.jdbc.profiler.ProfileEventSink;
0030: import com.mysql.jdbc.profiler.ProfilerEvent;
0031:
0032: import java.io.ByteArrayInputStream;
0033: import java.io.IOException;
0034: import java.io.InputStream;
0035: import java.io.ObjectInputStream;
0036: import java.io.Reader;
0037: import java.io.StringReader;
0038: import java.io.UnsupportedEncodingException;
0039:
0040: import java.lang.reflect.Constructor;
0041: import java.math.BigDecimal;
0042: import java.math.BigInteger;
0043:
0044: import java.net.MalformedURLException;
0045: import java.net.URL;
0046:
0047: import java.sql.Array;
0048: import java.sql.DataTruncation;
0049: import java.sql.Date;
0050: import java.sql.Ref;
0051: import java.sql.SQLException;
0052: import java.sql.SQLWarning;
0053: import java.sql.Time;
0054: import java.sql.Timestamp;
0055: import java.sql.Types;
0056:
0057: import java.util.Calendar;
0058: import java.util.GregorianCalendar;
0059: import java.util.HashMap;
0060: import java.util.Locale;
0061: import java.util.Map;
0062: import java.util.StringTokenizer;
0063: import java.util.TimeZone;
0064: import java.util.TreeMap;
0065:
0066: /**
0067: * A ResultSet provides access to a table of data generated by executing a
0068: * Statement. The table rows are retrieved in sequence. Within a row its column
0069: * values can be accessed in any order.
0070: *
0071: * <P>
0072: * A ResultSet maintains a cursor pointing to its current row of data. Initially
0073: * the cursor is positioned before the first row. The 'next' method moves the
0074: * cursor to the next row.
0075: * </p>
0076: *
0077: * <P>
0078: * The getXXX methods retrieve column values for the current row. You can
0079: * retrieve values either using the index number of the column, or by using the
0080: * name of the column. In general using the column index will be more efficient.
0081: * Columns are numbered from 1.
0082: * </p>
0083: *
0084: * <P>
0085: * For maximum portability, ResultSet columns within each row should be read in
0086: * left-to-right order and each column should be read only once.
0087: * </p>
0088: *
0089: * <P>
0090: * For the getXXX methods, the JDBC driver attempts to convert the underlying
0091: * data to the specified Java type and returns a suitable Java value. See the
0092: * JDBC specification for allowable mappings from SQL types to Java types with
0093: * the ResultSet getXXX methods.
0094: * </p>
0095: *
0096: * <P>
0097: * Column names used as input to getXXX methods are case insenstive. When
0098: * performing a getXXX using a column name, if several columns have the same
0099: * name, then the value of the first matching column will be returned. The
0100: * column name option is designed to be used when column names are used in the
0101: * SQL Query. For columns that are NOT explicitly named in the query, it is best
0102: * to use column numbers. If column names were used there is no way for the
0103: * programmer to guarentee that they actually refer to the intended columns.
0104: * </p>
0105: *
0106: * <P>
0107: * A ResultSet is automatically closed by the Statement that generated it when
0108: * that Statement is closed, re-executed, or is used to retrieve the next result
0109: * from a sequence of multiple results.
0110: * </p>
0111: *
0112: * <P>
0113: * The number, types and properties of a ResultSet's columns are provided by the
0114: * ResultSetMetaData object returned by the getMetaData method.
0115: * </p>
0116: *
0117: * @author Mark Matthews
0118: * @version $Id: ResultSetImpl.java 6576 2007-09-07 16:11:05Z mmatthews $
0119: *
0120: * @see ResultSetMetaData
0121: * @see java.sql.ResultSet
0122: */
0123: public class ResultSetImpl implements ResultSetInternalMethods {
0124:
0125: private static final Constructor JDBC_4_RS_4_ARG_CTOR;
0126: private static final Constructor JDBC_4_RS_6_ARG_CTOR;;
0127: private static final Constructor JDBC_4_UPD_RS_6_ARG_CTOR;
0128:
0129: static {
0130: if (Util.isJdbc4()) {
0131: try {
0132: JDBC_4_RS_4_ARG_CTOR = Class
0133: .forName("com.mysql.jdbc.JDBC4ResultSet")
0134: .getConstructor(
0135: new Class[] {
0136: Long.TYPE,
0137: Long.TYPE,
0138: ConnectionImpl.class,
0139: com.mysql.jdbc.StatementImpl.class });
0140: JDBC_4_RS_6_ARG_CTOR = Class
0141: .forName("com.mysql.jdbc.JDBC4ResultSet")
0142: .getConstructor(
0143: new Class[] {
0144: String.class,
0145: Field[].class,
0146: RowData.class,
0147: ConnectionImpl.class,
0148: com.mysql.jdbc.StatementImpl.class });
0149: JDBC_4_UPD_RS_6_ARG_CTOR = Class
0150: .forName(
0151: "com.mysql.jdbc.JDBC4UpdatableResultSet")
0152: .getConstructor(
0153: new Class[] {
0154: String.class,
0155: Field[].class,
0156: RowData.class,
0157: ConnectionImpl.class,
0158: com.mysql.jdbc.StatementImpl.class });
0159: } catch (SecurityException e) {
0160: throw new RuntimeException(e);
0161: } catch (NoSuchMethodException e) {
0162: throw new RuntimeException(e);
0163: } catch (ClassNotFoundException e) {
0164: throw new RuntimeException(e);
0165: }
0166: } else {
0167: JDBC_4_RS_4_ARG_CTOR = null;
0168: JDBC_4_RS_6_ARG_CTOR = null;
0169: JDBC_4_UPD_RS_6_ARG_CTOR = null;
0170: }
0171: }
0172:
0173: /**
0174: * Epsillon between Float.MIN_VALUE and the double representation of said value.
0175: */
0176: protected static final double MIN_DIFF_PREC = Float
0177: .parseFloat(Float.toString(Float.MIN_VALUE))
0178: - Double.parseDouble(Float.toString(Float.MIN_VALUE));
0179:
0180: /**
0181: * Epsillon between Float.MAX_VALUE and the double representation of said value.
0182: */
0183: protected static final double MAX_DIFF_PREC = Float
0184: .parseFloat(Float.toString(Float.MAX_VALUE))
0185: - Double.parseDouble(Float.toString(Float.MAX_VALUE));
0186:
0187: /** Counter used to generate IDs for profiling. */
0188: protected static int resultCounter = 1;
0189:
0190: /**
0191: * Converts the given value as a java long, to an 'unsigned' long, using the
0192: * java.math.BigInteger class.
0193: */
0194: protected static BigInteger convertLongToUlong(long longVal) {
0195: byte[] asBytes = new byte[8];
0196: asBytes[7] = (byte) (longVal & 0xff);
0197: asBytes[6] = (byte) (longVal >>> 8);
0198: asBytes[5] = (byte) (longVal >>> 16);
0199: asBytes[4] = (byte) (longVal >>> 24);
0200: asBytes[3] = (byte) (longVal >>> 32);
0201: asBytes[2] = (byte) (longVal >>> 40);
0202: asBytes[1] = (byte) (longVal >>> 48);
0203: asBytes[0] = (byte) (longVal >>> 56);
0204:
0205: return new BigInteger(1, asBytes);
0206: }
0207:
0208: /** The catalog that was in use when we were created */
0209: protected String catalog = null;
0210:
0211: /** Map column names (and all of their permutations) to column indices */
0212: protected Map columnNameToIndex = null;
0213:
0214: /** Keep track of columns accessed */
0215: protected boolean[] columnUsed = null;
0216:
0217: /** The Connection instance that created us */
0218: protected ConnectionImpl connection; // The connection that
0219: // created us
0220:
0221: protected long connectionId = 0;
0222:
0223: /** The current row #, -1 == before start of result set */
0224: protected int currentRow = -1; // Cursor to current row;
0225:
0226: TimeZone defaultTimeZone;
0227:
0228: /** Are we in the middle of doing updates to the current row? */
0229: protected boolean doingUpdates = false;
0230:
0231: protected ProfileEventSink eventSink = null;
0232:
0233: Calendar fastDateCal = null;
0234:
0235: /** The direction to fetch rows (always FETCH_FORWARD) */
0236: protected int fetchDirection = FETCH_FORWARD;
0237:
0238: /** The number of rows to fetch in one go... */
0239: protected int fetchSize = 0;
0240:
0241: /** The fields for this result set */
0242: protected Field[] fields; // The fields
0243:
0244: /**
0245: * First character of the query that created this result set...Used to
0246: * determine whether or not to parse server info messages in certain
0247: * circumstances.
0248: */
0249: protected char firstCharOfQuery;
0250:
0251: /** Map of fully-specified column names to column indices */
0252: protected Map fullColumnNameToIndex = null;
0253:
0254: protected boolean hasBuiltIndexMapping = false;
0255:
0256: /**
0257: * Is the data stored as strings (default) or natively (which is the case
0258: * with results from PrepStmts)
0259: */
0260: protected boolean isBinaryEncoded = false;
0261:
0262: /** Has this result set been closed? */
0263: protected boolean isClosed = false;
0264:
0265: protected ResultSetInternalMethods nextResultSet = null;
0266:
0267: /** Are we on the insert row? */
0268: protected boolean onInsertRow = false;
0269:
0270: /** The statement that created us */
0271: protected com.mysql.jdbc.StatementImpl owningStatement;
0272:
0273: /**
0274: * StackTrace generated where ResultSet was created... used when profiling
0275: */
0276: protected Throwable pointOfOrigin;
0277:
0278: /** Are we tracking items for profileSql? */
0279: protected boolean profileSql = false;
0280:
0281: /**
0282: * Do we actually contain rows, or just information about
0283: * UPDATE/INSERT/DELETE?
0284: */
0285: protected boolean reallyResult = false;
0286:
0287: /** The id (used when profiling) to identify us */
0288: protected int resultId;
0289:
0290: /** Are we read-only or updatable? */
0291: protected int resultSetConcurrency = 0;
0292:
0293: /** Are we scroll-sensitive/insensitive? */
0294: protected int resultSetType = 0;
0295:
0296: /** The actual rows */
0297: protected RowData rowData; // The results
0298:
0299: /**
0300: * Any info message from the server that was created while generating this
0301: * result set (if 'info parsing' is enabled for the connection).
0302: */
0303: protected String serverInfo = null;
0304:
0305: PreparedStatement statementUsedForFetchingRows;
0306:
0307: /** Pointer to current row data */
0308: protected ResultSetRow this Row = null; // Values for current row
0309:
0310: // These are longs for
0311: // recent versions of the MySQL server.
0312: //
0313: // They get reduced to ints via the JDBC API,
0314: // but can be retrieved through a MySQLStatement
0315: // in their entirety.
0316: //
0317:
0318: /** How many rows were affected by UPDATE/INSERT/DELETE? */
0319: protected long updateCount;
0320:
0321: /** Value generated for AUTO_INCREMENT columns */
0322: protected long updateId = -1;
0323:
0324: private boolean useStrictFloatingPoint = false;
0325:
0326: protected boolean useUsageAdvisor = false;
0327:
0328: /** The warning chain */
0329: protected java.sql.SQLWarning warningChain = null;
0330:
0331: /** Did the previous value retrieval find a NULL? */
0332: protected boolean wasNullFlag = false;
0333:
0334: protected java.sql.Statement wrapperStatement;
0335:
0336: protected boolean retainOwningStatement;
0337:
0338: protected Calendar gmtCalendar = null;
0339:
0340: protected boolean useFastDateParsing = false;
0341:
0342: private boolean padCharsWithSpace = false;
0343:
0344: protected final static char[] EMPTY_SPACE = new char[255];
0345:
0346: static {
0347: for (int i = 0; i < EMPTY_SPACE.length; i++) {
0348: EMPTY_SPACE[i] = ' ';
0349: }
0350: }
0351:
0352: protected static ResultSetImpl getInstance(long updateCount,
0353: long updateID, ConnectionImpl conn,
0354: StatementImpl creatorStmt) throws SQLException {
0355: if (!Util.isJdbc4()) {
0356: return new ResultSetImpl(updateCount, updateID, conn,
0357: creatorStmt);
0358: }
0359:
0360: return (ResultSetImpl) Util.handleNewInstance(
0361: JDBC_4_RS_4_ARG_CTOR, new Object[] {
0362: Constants.longValueOf(updateCount),
0363: Constants.longValueOf(updateID), conn,
0364: creatorStmt });
0365: }
0366:
0367: /**
0368: * Creates a result set instance that represents a query result -- We need
0369: * to provide factory-style methods so we can support both JDBC3 (and older)
0370: * and JDBC4 runtimes, otherwise the class verifier complains when it tries
0371: * to load JDBC4-only interface classes that are present in JDBC4 method
0372: * signatures.
0373: */
0374:
0375: protected static ResultSetImpl getInstance(String catalog,
0376: Field[] fields, RowData tuples, ConnectionImpl conn,
0377: StatementImpl creatorStmt, boolean isUpdatable)
0378: throws SQLException {
0379: if (!Util.isJdbc4()) {
0380: if (!isUpdatable) {
0381: return new ResultSetImpl(catalog, fields, tuples, conn,
0382: creatorStmt);
0383: }
0384:
0385: return new UpdatableResultSet(catalog, fields, tuples,
0386: conn, creatorStmt);
0387: }
0388:
0389: if (!isUpdatable) {
0390: return (ResultSetImpl) Util.handleNewInstance(
0391: JDBC_4_RS_6_ARG_CTOR, new Object[] { catalog,
0392: fields, tuples, conn, creatorStmt });
0393: }
0394:
0395: return (ResultSetImpl) Util.handleNewInstance(
0396: JDBC_4_UPD_RS_6_ARG_CTOR, new Object[] { catalog,
0397: fields, tuples, conn, creatorStmt });
0398: }
0399:
0400: /**
0401: * Create a result set for an executeUpdate statement.
0402: *
0403: * @param updateCount
0404: * the number of rows affected by the update
0405: * @param updateID
0406: * the autoincrement value (if any)
0407: * @param conn
0408: * DOCUMENT ME!
0409: * @param creatorStmt
0410: * DOCUMENT ME!
0411: */
0412: public ResultSetImpl(long updateCount, long updateID,
0413: ConnectionImpl conn, StatementImpl creatorStmt) {
0414: this .updateCount = updateCount;
0415: this .updateId = updateID;
0416: this .reallyResult = false;
0417: this .fields = new Field[0];
0418:
0419: this .connection = conn;
0420: this .owningStatement = creatorStmt;
0421:
0422: this .retainOwningStatement = false;
0423:
0424: if (this .connection != null) {
0425: this .retainOwningStatement = this .connection
0426: .getRetainStatementAfterResultSetClose();
0427:
0428: this .connectionId = this .connection.getId();
0429: }
0430: }
0431:
0432: /**
0433: * Creates a new ResultSet object.
0434: *
0435: * @param catalog
0436: * the database in use when we were created
0437: * @param fields
0438: * an array of Field objects (basically, the ResultSet MetaData)
0439: * @param tuples
0440: * actual row data
0441: * @param conn
0442: * the Connection that created us.
0443: * @param creatorStmt
0444: * DOCUMENT ME!
0445: *
0446: * @throws SQLException
0447: * if an error occurs
0448: */
0449: public ResultSetImpl(String catalog, Field[] fields,
0450: RowData tuples, ConnectionImpl conn,
0451: StatementImpl creatorStmt) throws SQLException {
0452: this .connection = conn;
0453:
0454: this .retainOwningStatement = false;
0455:
0456: if (this .connection != null) {
0457: this .useStrictFloatingPoint = this .connection
0458: .getStrictFloatingPoint();
0459: this .setDefaultTimeZone(this .connection
0460: .getDefaultTimeZone());
0461: this .connectionId = this .connection.getId();
0462: this .useFastDateParsing = this .connection
0463: .getUseFastDateParsing();
0464: this .profileSql = this .connection.getProfileSql();
0465: this .retainOwningStatement = this .connection
0466: .getRetainStatementAfterResultSetClose();
0467: }
0468:
0469: this .owningStatement = creatorStmt;
0470:
0471: this .catalog = catalog;
0472:
0473: this .fields = fields;
0474: this .rowData = tuples;
0475: this .updateCount = this .rowData.size();
0476:
0477: if (Driver.DEBUG) {
0478: System.out.println(Messages
0479: .getString("ResultSet.Retrieved__1")
0480: + this .updateCount + " rows"); //$NON-NLS-1$
0481: }
0482:
0483: this .reallyResult = true;
0484:
0485: // Check for no results
0486: if (this .rowData.size() > 0) {
0487: if (this .updateCount == 1) {
0488: if (this .this Row == null) {
0489: this .rowData.close(); // empty result set
0490: this .updateCount = -1;
0491: }
0492: }
0493: } else {
0494: this .this Row = null;
0495: }
0496:
0497: this .rowData.setOwner(this );
0498:
0499: if (this .fields != null) {
0500: initializeWithMetadata();
0501: } // else called by Connection.initializeResultsMetadataFromCache() when cached
0502: }
0503:
0504: public void initializeWithMetadata() throws SQLException {
0505: this .rowData.setMetadata(this .fields);
0506:
0507: if (this .profileSql || this .connection.getUseUsageAdvisor()) {
0508: this .columnUsed = new boolean[this .fields.length];
0509: this .pointOfOrigin = new Throwable();
0510: this .resultId = resultCounter++;
0511: this .useUsageAdvisor = this .connection.getUseUsageAdvisor();
0512: this .eventSink = ProfileEventSink
0513: .getInstance(this .connection);
0514: }
0515:
0516: if (this .connection.getGatherPerformanceMetrics()) {
0517: this .connection.incrementNumberOfResultSetsCreated();
0518:
0519: Map tableNamesMap = new HashMap();
0520:
0521: for (int i = 0; i < this .fields.length; i++) {
0522: Field f = this .fields[i];
0523:
0524: String tableName = f.getOriginalTableName();
0525:
0526: if (tableName == null) {
0527: tableName = f.getTableName();
0528: }
0529:
0530: if (tableName != null) {
0531: if (this .connection.lowerCaseTableNames()) {
0532: tableName = tableName.toLowerCase(); // on windows, table
0533: // names are not case-sens.
0534: }
0535:
0536: tableNamesMap.put(tableName, null);
0537: }
0538: }
0539:
0540: this .connection.reportNumberOfTablesAccessed(tableNamesMap
0541: .size());
0542: }
0543: }
0544:
0545: private synchronized void createCalendarIfNeeded() {
0546: if (this .fastDateCal == null) {
0547: this .fastDateCal = new GregorianCalendar(Locale.US);
0548: this .fastDateCal.setTimeZone(this .getDefaultTimeZone());
0549: }
0550: }
0551:
0552: /**
0553: * JDBC 2.0
0554: *
0555: * <p>
0556: * Move to an absolute row number in the result set.
0557: * </p>
0558: *
0559: * <p>
0560: * If row is positive, moves to an absolute row with respect to the
0561: * beginning of the result set. The first row is row 1, the second is row 2,
0562: * etc.
0563: * </p>
0564: *
0565: * <p>
0566: * If row is negative, moves to an absolute row position with respect to the
0567: * end of result set. For example, calling absolute(-1) positions the cursor
0568: * on the last row, absolute(-2) indicates the next-to-last row, etc.
0569: * </p>
0570: *
0571: * <p>
0572: * An attempt to position the cursor beyond the first/last row in the result
0573: * set, leaves the cursor before/after the first/last row, respectively.
0574: * </p>
0575: *
0576: * <p>
0577: * Note: Calling absolute(1) is the same as calling first(). Calling
0578: * absolute(-1) is the same as calling last().
0579: * </p>
0580: *
0581: * @param row
0582: * the row number to move to
0583: *
0584: * @return true if on the result set, false if off.
0585: *
0586: * @exception SQLException
0587: * if a database-access error occurs, or row is 0, or result
0588: * set type is TYPE_FORWARD_ONLY.
0589: */
0590: public boolean absolute(int row) throws SQLException {
0591: checkClosed();
0592:
0593: boolean b;
0594:
0595: if (this .rowData.size() == 0) {
0596: b = false;
0597: } else {
0598: if (row == 0) {
0599: throw SQLError
0600: .createSQLException(
0601: Messages
0602: .getString("ResultSet.Cannot_absolute_position_to_row_0_110"), //$NON-NLS-1$
0603: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
0604: }
0605:
0606: if (this .onInsertRow) {
0607: this .onInsertRow = false;
0608: }
0609:
0610: if (this .doingUpdates) {
0611: this .doingUpdates = false;
0612: }
0613:
0614: if (this .this Row != null) {
0615: this .this Row.closeOpenStreams();
0616: }
0617:
0618: if (row == 1) {
0619: b = first();
0620: } else if (row == -1) {
0621: b = last();
0622: } else if (row > this .rowData.size()) {
0623: afterLast();
0624: b = false;
0625: } else {
0626: if (row < 0) {
0627: // adjust to reflect after end of result set
0628: int newRowPosition = this .rowData.size() + row + 1;
0629:
0630: if (newRowPosition <= 0) {
0631: beforeFirst();
0632: b = false;
0633: } else {
0634: b = absolute(newRowPosition);
0635: }
0636: } else {
0637: row--; // adjust for index difference
0638: this .rowData.setCurrentRow(row);
0639: this .this Row = this .rowData.getAt(row);
0640: b = true;
0641: }
0642: }
0643: }
0644:
0645: return b;
0646: }
0647:
0648: /**
0649: * JDBC 2.0
0650: *
0651: * <p>
0652: * Moves to the end of the result set, just after the last row. Has no
0653: * effect if the result set contains no rows.
0654: * </p>
0655: *
0656: * @exception SQLException
0657: * if a database-access error occurs, or result set type is
0658: * TYPE_FORWARD_ONLY.
0659: */
0660: public void afterLast() throws SQLException {
0661: checkClosed();
0662:
0663: if (this .onInsertRow) {
0664: this .onInsertRow = false;
0665: }
0666:
0667: if (this .doingUpdates) {
0668: this .doingUpdates = false;
0669: }
0670:
0671: if (this .this Row != null) {
0672: this .this Row.closeOpenStreams();
0673: }
0674:
0675: if (this .rowData.size() != 0) {
0676: this .rowData.afterLast();
0677: this .this Row = null;
0678: }
0679: }
0680:
0681: /**
0682: * JDBC 2.0
0683: *
0684: * <p>
0685: * Moves to the front of the result set, just before the first row. Has no
0686: * effect if the result set contains no rows.
0687: * </p>
0688: *
0689: * @exception SQLException
0690: * if a database-access error occurs, or result set type is
0691: * TYPE_FORWARD_ONLY
0692: */
0693: public void beforeFirst() throws SQLException {
0694: checkClosed();
0695:
0696: if (this .onInsertRow) {
0697: this .onInsertRow = false;
0698: }
0699:
0700: if (this .doingUpdates) {
0701: this .doingUpdates = false;
0702: }
0703:
0704: if (this .rowData.size() == 0) {
0705: return;
0706: }
0707:
0708: if (this .this Row != null) {
0709: this .this Row.closeOpenStreams();
0710: }
0711:
0712: this .rowData.beforeFirst();
0713: this .this Row = null;
0714: }
0715:
0716: // ---------------------------------------------------------------------
0717: // Traversal/Positioning
0718: // ---------------------------------------------------------------------
0719:
0720: /**
0721: * Builds a hash between column names and their indices for fast retrieval.
0722: */
0723: public void buildIndexMapping() throws SQLException {
0724: int numFields = this .fields.length;
0725: this .columnNameToIndex = new TreeMap(
0726: String.CASE_INSENSITIVE_ORDER);
0727: this .fullColumnNameToIndex = new TreeMap(
0728: String.CASE_INSENSITIVE_ORDER);
0729:
0730: // We do this in reverse order, so that the 'first' column
0731: // with a given name ends up as the final mapping in the
0732: // hashtable...
0733: //
0734: // Quoting the JDBC Spec:
0735: //
0736: // "Column names used as input to getter
0737: // methods are case insensitive. When a getter method is called with a
0738: // column
0739: // name and several columns have the same name, the value of the first
0740: // matching column will be returned. "
0741: //
0742: for (int i = numFields - 1; i >= 0; i--) {
0743: Integer index = Constants.integerValueOf(i);
0744: String columnName = this .fields[i].getName();
0745: String fullColumnName = this .fields[i].getFullName();
0746:
0747: if (columnName != null) {
0748: this .columnNameToIndex.put(columnName, index);
0749: }
0750:
0751: if (fullColumnName != null) {
0752: this .fullColumnNameToIndex.put(fullColumnName, index);
0753: }
0754: }
0755:
0756: // set the flag to prevent rebuilding...
0757: this .hasBuiltIndexMapping = true;
0758: }
0759:
0760: /**
0761: * JDBC 2.0 The cancelRowUpdates() method may be called after calling an
0762: * updateXXX() method(s) and before calling updateRow() to rollback the
0763: * updates made to a row. If no updates have been made or updateRow() has
0764: * already been called, then this method has no effect.
0765: *
0766: * @exception SQLException
0767: * if a database-access error occurs, or if called when on
0768: * the insert row.
0769: * @throws NotUpdatable
0770: * DOCUMENT ME!
0771: */
0772: public void cancelRowUpdates() throws SQLException {
0773: throw new NotUpdatable();
0774: }
0775:
0776: /**
0777: * Ensures that the result set is not closed
0778: *
0779: * @throws SQLException
0780: * if the result set is closed
0781: */
0782: protected final void checkClosed() throws SQLException {
0783: if (this .isClosed) {
0784: throw SQLError
0785: .createSQLException(
0786: Messages
0787: .getString("ResultSet.Operation_not_allowed_after_ResultSet_closed_144"), //$NON-NLS-1$
0788: SQLError.SQL_STATE_GENERAL_ERROR);
0789: }
0790: }
0791:
0792: /**
0793: * Checks if columnIndex is within the number of columns in this result set.
0794: *
0795: * @param columnIndex
0796: * the index to check
0797: *
0798: * @throws SQLException
0799: * if the index is out of bounds
0800: */
0801: protected final void checkColumnBounds(int columnIndex)
0802: throws SQLException {
0803: if ((columnIndex < 1)) {
0804: throw SQLError
0805: .createSQLException(
0806: Messages
0807: .getString(
0808: "ResultSet.Column_Index_out_of_range_low",
0809: new Object[] {
0810: Constants
0811: .integerValueOf(columnIndex),
0812: Constants
0813: .integerValueOf(this .fields.length) }),
0814: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0815: } else if ((columnIndex > this .fields.length)) {
0816: throw SQLError
0817: .createSQLException(
0818: Messages
0819: .getString(
0820: "ResultSet.Column_Index_out_of_range_high",
0821: new Object[] {
0822: Constants
0823: .integerValueOf(columnIndex),
0824: Constants
0825: .integerValueOf(this .fields.length) }),
0826: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
0827: }
0828:
0829: if (this .profileSql || this .useUsageAdvisor) {
0830: this .columnUsed[columnIndex - 1] = true;
0831: }
0832: }
0833:
0834: /**
0835: * Ensures that the cursor is positioned on a valid row and that the result
0836: * set is not closed
0837: *
0838: * @throws SQLException
0839: * if the result set is not in a valid state for traversal
0840: */
0841: protected void checkRowPos() throws SQLException {
0842: checkClosed();
0843:
0844: if (!this .rowData.isDynamic() && (this .rowData.size() == 0)) {
0845: throw SQLError
0846: .createSQLException(
0847: Messages
0848: .getString("ResultSet.Illegal_operation_on_empty_result_set"),
0849: SQLError.SQL_STATE_GENERAL_ERROR);
0850: }
0851:
0852: if (this .rowData.isBeforeFirst()) {
0853: throw SQLError
0854: .createSQLException(
0855: Messages
0856: .getString("ResultSet.Before_start_of_result_set_146"),
0857: SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
0858: }
0859:
0860: if (this .rowData.isAfterLast()) {
0861: throw SQLError
0862: .createSQLException(
0863: Messages
0864: .getString("ResultSet.After_end_of_result_set_148"),
0865: SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
0866: }
0867: }
0868:
0869: /**
0870: * We can't do this ourselves, otherwise the contract for
0871: * Statement.getMoreResults() won't work correctly.
0872: */
0873: public void clearNextResult() {
0874: this .nextResultSet = null;
0875: }
0876:
0877: /**
0878: * After this call, getWarnings returns null until a new warning is reported
0879: * for this ResultSet
0880: *
0881: * @exception SQLException
0882: * if a database access error occurs
0883: */
0884: public void clearWarnings() throws SQLException {
0885: this .warningChain = null;
0886: }
0887:
0888: /**
0889: * In some cases, it is desirable to immediately release a ResultSet
0890: * database and JDBC resources instead of waiting for this to happen when it
0891: * is automatically closed. The close method provides this immediate
0892: * release.
0893: *
0894: * <p>
0895: * <B>Note:</B> A ResultSet is automatically closed by the Statement the
0896: * Statement that generated it when that Statement is closed, re-executed,
0897: * or is used to retrieve the next result from a sequence of multiple
0898: * results. A ResultSet is also automatically closed when it is garbage
0899: * collected.
0900: * </p>
0901: *
0902: * @exception SQLException
0903: * if a database access error occurs
0904: */
0905: public void close() throws SQLException {
0906: realClose(true);
0907: }
0908:
0909: /**
0910: * @return
0911: */
0912: private int convertToZeroWithEmptyCheck() throws SQLException {
0913: if (this .connection.getEmptyStringsConvertToZero()) {
0914: return 0;
0915: }
0916:
0917: throw SQLError.createSQLException(
0918: "Can't convert empty string ('') to numeric",
0919: SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
0920: }
0921:
0922: private String convertToZeroLiteralStringWithEmptyCheck()
0923: throws SQLException {
0924:
0925: if (this .connection.getEmptyStringsConvertToZero()) {
0926: return "0";
0927: }
0928:
0929: throw SQLError.createSQLException(
0930: "Can't convert empty string ('') to numeric",
0931: SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
0932: }
0933:
0934: //
0935: // Note, row data is linked between these two result sets
0936: //
0937: public ResultSetInternalMethods copy() throws SQLException {
0938: ResultSetInternalMethods rs = ResultSetImpl.getInstance(
0939: this .catalog, this .fields, this .rowData,
0940: this .connection, this .owningStatement, false); // note, doesn't work for updatable result sets
0941:
0942: return rs;
0943: }
0944:
0945: public void redefineFieldsForDBMD(Field[] f) {
0946: this .fields = f;
0947:
0948: for (int i = 0; i < this .fields.length; i++) {
0949: this .fields[i].setUseOldNameMetadata(true);
0950: this .fields[i].setConnection(this .connection);
0951: }
0952: }
0953:
0954: public void populateCachedMetaData(
0955: CachedResultSetMetaData cachedMetaData) throws SQLException {
0956: cachedMetaData.fields = this .fields;
0957: cachedMetaData.columnNameToIndex = this .columnNameToIndex;
0958: cachedMetaData.fullColumnNameToIndex = this .fullColumnNameToIndex;
0959: cachedMetaData.metadata = getMetaData();
0960: }
0961:
0962: public void initializeFromCachedMetaData(
0963: CachedResultSetMetaData cachedMetaData) {
0964: this .fields = cachedMetaData.fields;
0965: this .columnNameToIndex = cachedMetaData.columnNameToIndex;
0966: this .fullColumnNameToIndex = cachedMetaData.fullColumnNameToIndex;
0967: this .hasBuiltIndexMapping = true;
0968: }
0969:
0970: /**
0971: * JDBC 2.0 Delete the current row from the result set and the underlying
0972: * database. Cannot be called when on the insert row.
0973: *
0974: * @exception SQLException
0975: * if a database-access error occurs, or if called when on
0976: * the insert row.
0977: * @throws NotUpdatable
0978: * DOCUMENT ME!
0979: */
0980: public void deleteRow() throws SQLException {
0981: throw new NotUpdatable();
0982: }
0983:
0984: /**
0985: * @param columnIndex
0986: * @param stringVal
0987: * @param mysqlType
0988: * @return
0989: * @throws SQLException
0990: */
0991: private String extractStringFromNativeColumn(int columnIndex,
0992: int mysqlType) throws SQLException {
0993: int columnIndexMinusOne = columnIndex - 1;
0994:
0995: this .wasNullFlag = false;
0996:
0997: if (this .this Row.isNull(columnIndexMinusOne)) {
0998: this .wasNullFlag = true;
0999:
1000: return null;
1001: }
1002:
1003: this .wasNullFlag = false;
1004:
1005: String encoding = this .fields[columnIndexMinusOne]
1006: .getCharacterSet();
1007:
1008: return this .this Row.getString(columnIndex - 1, encoding,
1009: this .connection);
1010: }
1011:
1012: protected synchronized Date fastDateCreate(Calendar cal, int year,
1013: int month, int day) {
1014: if (cal == null) {
1015: createCalendarIfNeeded();
1016: cal = this .fastDateCal;
1017: }
1018:
1019: boolean useGmtMillis = this .connection
1020: .getUseGmtMillisForDatetimes();
1021:
1022: return TimeUtil.fastDateCreate(useGmtMillis,
1023: useGmtMillis ? getGmtCalendar() : null, cal, year,
1024: month, day);
1025: }
1026:
1027: protected synchronized Time fastTimeCreate(Calendar cal, int hour,
1028: int minute, int second) throws SQLException {
1029: if (cal == null) {
1030: createCalendarIfNeeded();
1031: cal = this .fastDateCal;
1032: }
1033:
1034: return TimeUtil.fastTimeCreate(cal, hour, minute, second);
1035: }
1036:
1037: protected synchronized Timestamp fastTimestampCreate(Calendar cal,
1038: int year, int month, int day, int hour, int minute,
1039: int seconds, int secondsPart) {
1040: if (cal == null) {
1041: createCalendarIfNeeded();
1042: cal = this .fastDateCal;
1043: }
1044:
1045: boolean useGmtMillis = this .connection
1046: .getUseGmtMillisForDatetimes();
1047:
1048: return TimeUtil.fastTimestampCreate(useGmtMillis,
1049: useGmtMillis ? getGmtCalendar() : null, cal, year,
1050: month, day, hour, minute, seconds, secondsPart);
1051: }
1052:
1053: /*
1054: /**
1055: * Required by JDBC spec
1056: */
1057: /*
1058: protected void finalize() throws Throwable {
1059: if (!this.isClosed) {
1060: realClose(false);
1061: }
1062: }
1063: */
1064:
1065: // --------------------------JDBC 2.0-----------------------------------
1066: // ---------------------------------------------------------------------
1067: // Getter's and Setter's
1068: // ---------------------------------------------------------------------
1069:
1070: /**
1071: * Map a ResultSet column name to a ResultSet column index
1072: *
1073: * @param columnName
1074: * the name of the column
1075: *
1076: * @return the column index
1077: *
1078: * @exception SQLException
1079: * if a database access error occurs
1080: */
1081: public synchronized int findColumn(String columnName)
1082: throws SQLException {
1083: Integer index;
1084:
1085: if (!this .hasBuiltIndexMapping) {
1086: buildIndexMapping();
1087: }
1088:
1089: index = (Integer) this .columnNameToIndex.get(columnName);
1090:
1091: if (index == null) {
1092: index = (Integer) this .fullColumnNameToIndex
1093: .get(columnName);
1094: }
1095:
1096: if (index != null) {
1097: return index.intValue() + 1;
1098: }
1099:
1100: // Try this inefficient way, now
1101:
1102: for (int i = 0; i < this .fields.length; i++) {
1103: if (this .fields[i].getName().equalsIgnoreCase(columnName)) {
1104: return i + 1;
1105: } else if (this .fields[i].getFullName().equalsIgnoreCase(
1106: columnName)) {
1107: return i + 1;
1108: }
1109: }
1110:
1111: throw SQLError.createSQLException(Messages
1112: .getString("ResultSet.Column____112")
1113: + columnName
1114: + Messages.getString("ResultSet.___not_found._113"), //$NON-NLS-1$ //$NON-NLS-2$
1115: SQLError.SQL_STATE_COLUMN_NOT_FOUND);
1116: }
1117:
1118: /**
1119: * JDBC 2.0
1120: *
1121: * <p>
1122: * Moves to the first row in the result set.
1123: * </p>
1124: *
1125: * @return true if on a valid row, false if no rows in the result set.
1126: *
1127: * @exception SQLException
1128: * if a database-access error occurs, or result set type is
1129: * TYPE_FORWARD_ONLY.
1130: */
1131: public boolean first() throws SQLException {
1132: checkClosed();
1133:
1134: if (this .rowData.isEmpty()) {
1135: return false;
1136: }
1137:
1138: if (this .onInsertRow) {
1139: this .onInsertRow = false;
1140: }
1141:
1142: if (this .doingUpdates) {
1143: this .doingUpdates = false;
1144: }
1145:
1146: this .rowData.beforeFirst();
1147: this .this Row = this .rowData.next();
1148:
1149: return true;
1150: }
1151:
1152: /**
1153: * JDBC 2.0 Get an array column.
1154: *
1155: * @param i
1156: * the first column is 1, the second is 2, ...
1157: *
1158: * @return an object representing an SQL array
1159: *
1160: * @throws SQLException
1161: * if a database error occurs
1162: * @throws NotImplemented
1163: * DOCUMENT ME!
1164: */
1165: public java.sql.Array getArray(int i) throws SQLException {
1166: checkColumnBounds(i);
1167:
1168: throw new NotImplemented();
1169: }
1170:
1171: /**
1172: * JDBC 2.0 Get an array column.
1173: *
1174: * @param colName
1175: * the column name
1176: *
1177: * @return an object representing an SQL array
1178: *
1179: * @throws SQLException
1180: * if a database error occurs
1181: * @throws NotImplemented
1182: * DOCUMENT ME!
1183: */
1184: public java.sql.Array getArray(String colName) throws SQLException {
1185: return getArray(findColumn(colName));
1186: }
1187:
1188: /**
1189: * A column value can be retrieved as a stream of ASCII characters and then
1190: * read in chunks from the stream. This method is particulary suitable for
1191: * retrieving large LONGVARCHAR values. The JDBC driver will do any
1192: * necessary conversion from the database format into ASCII.
1193: *
1194: * <p>
1195: * <B>Note:</B> All the data in the returned stream must be read prior to
1196: * getting the value of any other column. The next call to a get method
1197: * implicitly closes the stream. Also, a stream may return 0 for available()
1198: * whether there is data available or not.
1199: * </p>
1200: *
1201: * @param columnIndex
1202: * the first column is 1, the second is 2, ...
1203: *
1204: * @return a Java InputStream that delivers the database column value as a
1205: * stream of one byte ASCII characters. If the value is SQL NULL
1206: * then the result is null
1207: *
1208: * @exception SQLException
1209: * if a database access error occurs
1210: *
1211: * @see getBinaryStream
1212: */
1213: public InputStream getAsciiStream(int columnIndex)
1214: throws SQLException {
1215: checkRowPos();
1216:
1217: if (!this .isBinaryEncoded) {
1218: return getBinaryStream(columnIndex);
1219: }
1220:
1221: return getNativeBinaryStream(columnIndex);
1222: }
1223:
1224: /**
1225: * DOCUMENT ME!
1226: *
1227: * @param columnName
1228: * DOCUMENT ME!
1229: *
1230: * @return DOCUMENT ME!
1231: *
1232: * @throws SQLException
1233: * DOCUMENT ME!
1234: */
1235: public InputStream getAsciiStream(String columnName)
1236: throws SQLException {
1237: return getAsciiStream(findColumn(columnName));
1238: }
1239:
1240: /**
1241: * JDBC 2.0 Get the value of a column in the current row as a
1242: * java.math.BigDecimal object.
1243: *
1244: * @param columnIndex
1245: * the first column is 1, the second is 2, ...
1246: *
1247: * @return the column value (full precision); if the value is SQL NULL, the
1248: * result is null
1249: *
1250: * @exception SQLException
1251: * if a database-access error occurs.
1252: */
1253: public BigDecimal getBigDecimal(int columnIndex)
1254: throws SQLException {
1255: if (!this .isBinaryEncoded) {
1256: String stringVal = getString(columnIndex);
1257: BigDecimal val;
1258:
1259: if (stringVal != null) {
1260: if (stringVal.length() == 0) {
1261:
1262: val = new BigDecimal(
1263: convertToZeroLiteralStringWithEmptyCheck());
1264:
1265: return val;
1266: }
1267:
1268: try {
1269: val = new BigDecimal(stringVal);
1270:
1271: return val;
1272: } catch (NumberFormatException ex) {
1273: throw SQLError
1274: .createSQLException(
1275: Messages
1276: .getString(
1277: "ResultSet.Bad_format_for_BigDecimal",
1278: new Object[] {
1279: stringVal,
1280: Constants
1281: .integerValueOf(columnIndex) }),
1282: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1283: }
1284: }
1285:
1286: return null;
1287: }
1288:
1289: return getNativeBigDecimal(columnIndex);
1290: }
1291:
1292: /**
1293: * Get the value of a column in the current row as a java.math.BigDecimal
1294: * object
1295: *
1296: * @param columnIndex
1297: * the first column is 1, the second is 2...
1298: * @param scale
1299: * the number of digits to the right of the decimal
1300: *
1301: * @return the column value; if the value is SQL NULL, null
1302: *
1303: * @exception SQLException
1304: * if a database access error occurs
1305: *
1306: * @deprecated
1307: */
1308: public BigDecimal getBigDecimal(int columnIndex, int scale)
1309: throws SQLException {
1310: if (!this .isBinaryEncoded) {
1311: String stringVal = getString(columnIndex);
1312: BigDecimal val;
1313:
1314: if (stringVal != null) {
1315: if (stringVal.length() == 0) {
1316: val = new BigDecimal(
1317: convertToZeroLiteralStringWithEmptyCheck());
1318:
1319: try {
1320: return val.setScale(scale);
1321: } catch (ArithmeticException ex) {
1322: try {
1323: return val.setScale(scale,
1324: BigDecimal.ROUND_HALF_UP);
1325: } catch (ArithmeticException arEx) {
1326: throw SQLError
1327: .createSQLException(
1328: Messages
1329: .getString("ResultSet.Bad_format_for_BigDecimal____124") //$NON-NLS-1$
1330: + stringVal
1331: + Messages
1332: .getString("ResultSet.___in_column__125")
1333: + columnIndex
1334: + "(" //$NON-NLS-1$
1335: + this .fields[columnIndex - 1]
1336: + ").",
1337: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
1338: }
1339: }
1340: }
1341:
1342: try {
1343: val = new BigDecimal(stringVal);
1344: } catch (NumberFormatException ex) {
1345: if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1346: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
1347:
1348: val = new BigDecimal(valueAsLong);
1349: } else {
1350: throw SQLError
1351: .createSQLException(
1352: Messages
1353: .getString(
1354: "ResultSet.Bad_format_for_BigDecimal",
1355: new Object[] {
1356: Constants
1357: .integerValueOf(columnIndex),
1358: stringVal }),
1359: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1360: }
1361: }
1362:
1363: try {
1364: return val.setScale(scale);
1365: } catch (ArithmeticException ex) {
1366: try {
1367: return val.setScale(scale,
1368: BigDecimal.ROUND_HALF_UP);
1369: } catch (ArithmeticException arithEx) {
1370: throw SQLError
1371: .createSQLException(
1372: Messages
1373: .getString(
1374: "ResultSet.Bad_format_for_BigDecimal",
1375: new Object[] {
1376: Constants
1377: .integerValueOf(columnIndex),
1378: stringVal }),
1379: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1380: }
1381: }
1382: }
1383:
1384: return null;
1385: }
1386:
1387: return getNativeBigDecimal(columnIndex, scale);
1388: }
1389:
1390: /**
1391: * JDBC 2.0 Get the value of a column in the current row as a
1392: * java.math.BigDecimal object.
1393: *
1394: * @param columnName
1395: * the name of the column to retrieve the value from
1396: *
1397: * @return the BigDecimal value in the column
1398: *
1399: * @throws SQLException
1400: * if an error occurs
1401: */
1402: public BigDecimal getBigDecimal(String columnName)
1403: throws SQLException {
1404: return getBigDecimal(findColumn(columnName));
1405: }
1406:
1407: /**
1408: * DOCUMENT ME!
1409: *
1410: * @param columnName
1411: * DOCUMENT ME!
1412: * @param scale
1413: * DOCUMENT ME!
1414: *
1415: * @return DOCUMENT ME!
1416: *
1417: * @throws SQLException
1418: * DOCUMENT ME!
1419: *
1420: * @deprecated
1421: */
1422: public BigDecimal getBigDecimal(String columnName, int scale)
1423: throws SQLException {
1424: return getBigDecimal(findColumn(columnName), scale);
1425: }
1426:
1427: private final BigDecimal getBigDecimalFromString(String stringVal,
1428: int columnIndex, int scale) throws SQLException {
1429: BigDecimal bdVal;
1430:
1431: if (stringVal != null) {
1432: if (stringVal.length() == 0) {
1433: bdVal = new BigDecimal(
1434: convertToZeroLiteralStringWithEmptyCheck());
1435:
1436: try {
1437: return bdVal.setScale(scale);
1438: } catch (ArithmeticException ex) {
1439: try {
1440: return bdVal.setScale(scale,
1441: BigDecimal.ROUND_HALF_UP);
1442: } catch (ArithmeticException arEx) {
1443: throw new SQLException(
1444: Messages
1445: .getString(
1446: "ResultSet.Bad_format_for_BigDecimal",
1447: new Object[] {
1448: stringVal,
1449: Constants
1450: .integerValueOf(columnIndex) }),
1451: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1452: }
1453: }
1454: }
1455:
1456: try {
1457: try {
1458: return new BigDecimal(stringVal).setScale(scale);
1459: } catch (ArithmeticException ex) {
1460: try {
1461: return new BigDecimal(stringVal).setScale(
1462: scale, BigDecimal.ROUND_HALF_UP);
1463: } catch (ArithmeticException arEx) {
1464: throw new SQLException(
1465: Messages
1466: .getString(
1467: "ResultSet.Bad_format_for_BigDecimal",
1468: new Object[] {
1469: stringVal,
1470: Constants
1471: .integerValueOf(columnIndex) }),
1472: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1473: }
1474: }
1475: } catch (NumberFormatException ex) {
1476: if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1477: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
1478:
1479: try {
1480: return new BigDecimal(valueAsLong)
1481: .setScale(scale);
1482: } catch (ArithmeticException arEx1) {
1483: try {
1484: return new BigDecimal(valueAsLong)
1485: .setScale(scale,
1486: BigDecimal.ROUND_HALF_UP);
1487: } catch (ArithmeticException arEx2) {
1488: throw new SQLException(
1489: Messages
1490: .getString(
1491: "ResultSet.Bad_format_for_BigDecimal",
1492: new Object[] {
1493: stringVal,
1494: Constants
1495: .integerValueOf(columnIndex) }),
1496: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1497: }
1498: }
1499: }
1500:
1501: if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TINY
1502: && this .connection.getTinyInt1isBit()
1503: && this .fields[columnIndex - 1].getLength() == 1) {
1504: return new BigDecimal(stringVal
1505: .equalsIgnoreCase("true") ? 1 : 0)
1506: .setScale(scale);
1507: }
1508:
1509: throw new SQLException(
1510: Messages
1511: .getString(
1512: "ResultSet.Bad_format_for_BigDecimal",
1513: new Object[] {
1514: stringVal,
1515: Constants
1516: .integerValueOf(columnIndex) }),
1517: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1518: }
1519: }
1520:
1521: return null;
1522: }
1523:
1524: /**
1525: * A column value can also be retrieved as a binary stream. This method is
1526: * suitable for retrieving LONGVARBINARY values.
1527: *
1528: * @param columnIndex
1529: * the first column is 1, the second is 2...
1530: *
1531: * @return a Java InputStream that delivers the database column value as a
1532: * stream of bytes. If the value is SQL NULL, then the result is
1533: * null
1534: *
1535: * @exception SQLException
1536: * if a database access error occurs
1537: *
1538: * @see getAsciiStream
1539: * @see getUnicodeStream
1540: */
1541: public InputStream getBinaryStream(int columnIndex)
1542: throws SQLException {
1543: checkRowPos();
1544:
1545: if (!this .isBinaryEncoded) {
1546: checkColumnBounds(columnIndex);
1547:
1548: int columnIndexMinusOne = columnIndex - 1;
1549:
1550: if (this .this Row.isNull(columnIndexMinusOne)) {
1551: this .wasNullFlag = true;
1552:
1553: return null;
1554: }
1555:
1556: this .wasNullFlag = false;
1557:
1558: return this .this Row
1559: .getBinaryInputStream(columnIndexMinusOne);
1560: }
1561:
1562: return getNativeBinaryStream(columnIndex);
1563: }
1564:
1565: /**
1566: * DOCUMENT ME!
1567: *
1568: * @param columnName
1569: * DOCUMENT ME!
1570: *
1571: * @return DOCUMENT ME!
1572: *
1573: * @throws SQLException
1574: * DOCUMENT ME!
1575: */
1576: public InputStream getBinaryStream(String columnName)
1577: throws SQLException {
1578: return getBinaryStream(findColumn(columnName));
1579: }
1580:
1581: /**
1582: * JDBC 2.0 Get a BLOB column.
1583: *
1584: * @param columnIndex
1585: * the first column is 1, the second is 2, ...
1586: *
1587: * @return an object representing a BLOB
1588: *
1589: * @throws SQLException
1590: * if an error occurs.
1591: */
1592: public java.sql.Blob getBlob(int columnIndex) throws SQLException {
1593: if (!this .isBinaryEncoded) {
1594: checkRowPos();
1595:
1596: checkColumnBounds(columnIndex);
1597:
1598: int columnIndexMinusOne = columnIndex - 1;
1599:
1600: if (this .this Row.isNull(columnIndexMinusOne)) {
1601: this .wasNullFlag = true;
1602: } else {
1603: this .wasNullFlag = false;
1604: }
1605:
1606: if (this .wasNullFlag) {
1607: return null;
1608: }
1609:
1610: if (!this .connection.getEmulateLocators()) {
1611: return new Blob(this .this Row
1612: .getColumnValue(columnIndexMinusOne));
1613: }
1614:
1615: return new BlobFromLocator(this , columnIndex);
1616: }
1617:
1618: return getNativeBlob(columnIndex);
1619: }
1620:
1621: /**
1622: * JDBC 2.0 Get a BLOB column.
1623: *
1624: * @param colName
1625: * the column name
1626: *
1627: * @return an object representing a BLOB
1628: *
1629: * @throws SQLException
1630: * if an error occurs.
1631: */
1632: public java.sql.Blob getBlob(String colName) throws SQLException {
1633: return getBlob(findColumn(colName));
1634: }
1635:
1636: /**
1637: * Get the value of a column in the current row as a Java boolean
1638: *
1639: * @param columnIndex
1640: * the first column is 1, the second is 2...
1641: *
1642: * @return the column value, false for SQL NULL
1643: *
1644: * @exception SQLException
1645: * if a database access error occurs
1646: */
1647: public boolean getBoolean(int columnIndex) throws SQLException {
1648:
1649: checkColumnBounds(columnIndex);
1650:
1651: //
1652: // MySQL 5.0 and newer have an actual BIT type,
1653: // so we need to check for that here...
1654: //
1655:
1656: int columnIndexMinusOne = columnIndex - 1;
1657:
1658: Field field = this .fields[columnIndexMinusOne];
1659:
1660: if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
1661: return byteArrayToBoolean(columnIndexMinusOne);
1662: }
1663:
1664: this .wasNullFlag = false;
1665:
1666: int sqlType = field.getSQLType();
1667:
1668: switch (sqlType) {
1669: case Types.BIT:
1670: case Types.BOOLEAN:
1671: case Types.TINYINT:
1672: case Types.SMALLINT:
1673: case Types.INTEGER:
1674: case Types.BIGINT:
1675: case Types.DECIMAL:
1676: case Types.NUMERIC:
1677: case Types.REAL:
1678: case Types.FLOAT:
1679: case Types.DOUBLE:
1680: long boolVal = getLong(columnIndex, false);
1681:
1682: return (boolVal == -1 || boolVal > 0);
1683: default:
1684: if (this .connection.getPedantic()) {
1685: // Table B-6 from JDBC spec
1686: switch (sqlType) {
1687: case Types.BINARY:
1688: case Types.VARBINARY:
1689: case Types.LONGVARBINARY:
1690: case Types.DATE:
1691: case Types.TIME:
1692: case Types.TIMESTAMP:
1693: case Types.CLOB:
1694: case Types.BLOB:
1695: case Types.ARRAY:
1696: case Types.REF:
1697: case Types.DATALINK:
1698: case Types.STRUCT:
1699: case Types.JAVA_OBJECT:
1700: throw SQLError
1701: .createSQLException(
1702: "Required type conversion not allowed",
1703: SQLError.SQL_STATE_INVALID_CHARACTER_VALUE_FOR_CAST);
1704: }
1705: }
1706:
1707: if (sqlType == Types.BINARY || sqlType == Types.VARBINARY
1708: || sqlType == Types.LONGVARBINARY
1709: || sqlType == Types.BLOB) {
1710: return byteArrayToBoolean(columnIndexMinusOne);
1711: }
1712:
1713: if (this .useUsageAdvisor) {
1714: issueConversionViaParsingWarning("getBoolean()",
1715: columnIndex, this .this Row
1716: .getColumnValue(columnIndexMinusOne),
1717: this .fields[columnIndex], new int[] {
1718: MysqlDefs.FIELD_TYPE_BIT,
1719: MysqlDefs.FIELD_TYPE_DOUBLE,
1720: MysqlDefs.FIELD_TYPE_TINY,
1721: MysqlDefs.FIELD_TYPE_SHORT,
1722: MysqlDefs.FIELD_TYPE_LONG,
1723: MysqlDefs.FIELD_TYPE_LONGLONG,
1724: MysqlDefs.FIELD_TYPE_FLOAT });
1725: }
1726:
1727: String stringVal = getString(columnIndex);
1728:
1729: return getBooleanFromString(stringVal, columnIndex);
1730: }
1731: }
1732:
1733: private boolean byteArrayToBoolean(int columnIndexMinusOne)
1734: throws SQLException {
1735: Object value = this .this Row.getColumnValue(columnIndexMinusOne);
1736:
1737: if (value == null) {
1738: this .wasNullFlag = true;
1739:
1740: return false;
1741: }
1742:
1743: this .wasNullFlag = false;
1744:
1745: if (((byte[]) value).length == 0) {
1746: return false;
1747: }
1748:
1749: byte boolVal = ((byte[]) value)[0];
1750:
1751: if (boolVal == (byte) '1') {
1752: return true;
1753: } else if (boolVal == (byte) '0') {
1754: return false;
1755: }
1756:
1757: return (boolVal == -1 || boolVal > 0);
1758: }
1759:
1760: /**
1761: * DOCUMENT ME!
1762: *
1763: * @param columnName
1764: * DOCUMENT ME!
1765: *
1766: * @return DOCUMENT ME!
1767: *
1768: * @throws SQLException
1769: * DOCUMENT ME!
1770: */
1771: public boolean getBoolean(String columnName) throws SQLException {
1772: return getBoolean(findColumn(columnName));
1773: }
1774:
1775: private final boolean getBooleanFromString(String stringVal,
1776: int columnIndex) throws SQLException {
1777: if ((stringVal != null) && (stringVal.length() > 0)) {
1778: int c = Character.toLowerCase(stringVal.charAt(0));
1779:
1780: return ((c == 't') || (c == 'y') || (c == '1') || stringVal
1781: .equals("-1"));
1782: }
1783:
1784: return false;
1785: }
1786:
1787: /**
1788: * Get the value of a column in the current row as a Java byte.
1789: *
1790: * @param columnIndex
1791: * the first column is 1, the second is 2,...
1792: *
1793: * @return the column value; 0 if SQL NULL
1794: *
1795: * @exception SQLException
1796: * if a database access error occurs
1797: */
1798: public byte getByte(int columnIndex) throws SQLException {
1799: if (!this .isBinaryEncoded) {
1800: String stringVal = getString(columnIndex);
1801:
1802: if (this .wasNullFlag || (stringVal == null)) {
1803: return 0;
1804: }
1805:
1806: return getByteFromString(stringVal, columnIndex);
1807: }
1808:
1809: return getNativeByte(columnIndex);
1810: }
1811:
1812: /**
1813: * DOCUMENT ME!
1814: *
1815: * @param columnName
1816: * DOCUMENT ME!
1817: *
1818: * @return DOCUMENT ME!
1819: *
1820: * @throws SQLException
1821: * DOCUMENT ME!
1822: */
1823: public byte getByte(String columnName) throws SQLException {
1824: return getByte(findColumn(columnName));
1825: }
1826:
1827: private final byte getByteFromString(String stringVal,
1828: int columnIndex) throws SQLException {
1829:
1830: if (stringVal != null && stringVal.length() == 0) {
1831: return (byte) convertToZeroWithEmptyCheck();
1832: }
1833:
1834: //
1835: // JDK-6 doesn't like trailing whitespace
1836: //
1837: // Note this isn't a performance issue, other
1838: // than the iteration over the string, as String.trim()
1839: // will return a new string only if whitespace is present
1840: //
1841:
1842: if (stringVal == null) {
1843: return 0;
1844: }
1845:
1846: stringVal = stringVal.trim();
1847:
1848: try {
1849: int decimalIndex = stringVal.indexOf(".");
1850:
1851: if (decimalIndex != -1) {
1852: double valueAsDouble = Double.parseDouble(stringVal);
1853:
1854: if (this .connection
1855: .getJdbcCompliantTruncationForReads()) {
1856: if (valueAsDouble < Byte.MIN_VALUE
1857: || valueAsDouble > Byte.MAX_VALUE) {
1858: throwRangeException(stringVal, columnIndex,
1859: Types.TINYINT);
1860: }
1861: }
1862:
1863: return (byte) valueAsDouble;
1864: }
1865:
1866: long valueAsLong = Long.parseLong(stringVal);
1867:
1868: if (this .connection.getJdbcCompliantTruncationForReads()) {
1869: if (valueAsLong < Byte.MIN_VALUE
1870: || valueAsLong > Byte.MAX_VALUE) {
1871: throwRangeException(String.valueOf(valueAsLong),
1872: columnIndex, Types.TINYINT);
1873: }
1874: }
1875:
1876: return (byte) valueAsLong;
1877: } catch (NumberFormatException NFE) {
1878: throw SQLError
1879: .createSQLException(
1880: Messages
1881: .getString("ResultSet.Value____173")
1882: + stringVal //$NON-NLS-1$
1883: + Messages
1884: .getString("ResultSet.___is_out_of_range_[-127,127]_174"),
1885: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
1886: }
1887: }
1888:
1889: /**
1890: * Get the value of a column in the current row as a Java byte array.
1891: *
1892: * <p>
1893: * <b>Be warned</b> If the blob is huge, then you may run out of memory.
1894: * </p>
1895: *
1896: * @param columnIndex
1897: * the first column is 1, the second is 2, ...
1898: *
1899: * @return the column value; if the value is SQL NULL, the result is null
1900: *
1901: * @exception SQLException
1902: * if a database access error occurs
1903: */
1904: public byte[] getBytes(int columnIndex) throws SQLException {
1905: return getBytes(columnIndex, false);
1906: }
1907:
1908: protected byte[] getBytes(int columnIndex, boolean noConversion)
1909: throws SQLException {
1910: if (!this .isBinaryEncoded) {
1911: checkRowPos();
1912:
1913: checkColumnBounds(columnIndex);
1914:
1915: int columnIndexMinusOne = columnIndex - 1;
1916:
1917: if (this .this Row.isNull(columnIndexMinusOne)) {
1918: this .wasNullFlag = true;
1919: } else {
1920: this .wasNullFlag = false;
1921: }
1922:
1923: if (this .wasNullFlag) {
1924: return null;
1925: }
1926:
1927: return this .this Row.getColumnValue(columnIndexMinusOne);
1928: }
1929:
1930: return getNativeBytes(columnIndex, noConversion);
1931: }
1932:
1933: /**
1934: * DOCUMENT ME!
1935: *
1936: * @param columnName
1937: * DOCUMENT ME!
1938: *
1939: * @return DOCUMENT ME!
1940: *
1941: * @throws SQLException
1942: * DOCUMENT ME!
1943: */
1944: public byte[] getBytes(String columnName) throws SQLException {
1945: return getBytes(findColumn(columnName));
1946: }
1947:
1948: private final byte[] getBytesFromString(String stringVal,
1949: int columnIndex) throws SQLException {
1950: if (stringVal != null) {
1951: return StringUtils.getBytes(stringVal, this .connection
1952: .getEncoding(), this .connection
1953: .getServerCharacterEncoding(), this .connection
1954: .parserKnowsUnicode(), this .connection);
1955: }
1956:
1957: return null;
1958: }
1959:
1960: /**
1961: * Optimization to only use one calendar per-session, or calculate it for
1962: * each call, depending on user configuration
1963: */
1964: protected Calendar getCalendarInstanceForSessionOrNew() {
1965: if (this .connection != null) {
1966: return this .connection.getCalendarInstanceForSessionOrNew();
1967: } else {
1968: // punt, no connection around
1969: return new GregorianCalendar();
1970: }
1971: }
1972:
1973: /**
1974: * JDBC 2.0
1975: *
1976: * <p>
1977: * Get the value of a column in the current row as a java.io.Reader.
1978: * </p>
1979: *
1980: * @param columnIndex
1981: * the column to get the value from
1982: *
1983: * @return the value in the column as a java.io.Reader.
1984: *
1985: * @throws SQLException
1986: * if an error occurs
1987: */
1988: public java.io.Reader getCharacterStream(int columnIndex)
1989: throws SQLException {
1990: if (!this .isBinaryEncoded) {
1991: checkColumnBounds(columnIndex);
1992:
1993: int columnIndexMinusOne = columnIndex - 1;
1994:
1995: if (this .this Row.isNull(columnIndexMinusOne)) {
1996: this .wasNullFlag = true;
1997:
1998: return null;
1999: }
2000:
2001: this .wasNullFlag = false;
2002:
2003: return this .this Row.getReader(columnIndexMinusOne);
2004: }
2005:
2006: return getNativeCharacterStream(columnIndex);
2007: }
2008:
2009: /**
2010: * JDBC 2.0
2011: *
2012: * <p>
2013: * Get the value of a column in the current row as a java.io.Reader.
2014: * </p>
2015: *
2016: * @param columnName
2017: * the column name to retrieve the value from
2018: *
2019: * @return the value as a java.io.Reader
2020: *
2021: * @throws SQLException
2022: * if an error occurs
2023: */
2024: public java.io.Reader getCharacterStream(String columnName)
2025: throws SQLException {
2026: return getCharacterStream(findColumn(columnName));
2027: }
2028:
2029: private final java.io.Reader getCharacterStreamFromString(
2030: String stringVal, int columnIndex) throws SQLException {
2031: if (stringVal != null) {
2032: return new StringReader(stringVal);
2033: }
2034:
2035: return null;
2036: }
2037:
2038: /**
2039: * JDBC 2.0 Get a CLOB column.
2040: *
2041: * @param i
2042: * the first column is 1, the second is 2, ...
2043: *
2044: * @return an object representing a CLOB
2045: *
2046: * @throws SQLException
2047: * if an error occurs
2048: */
2049: public java.sql.Clob getClob(int i) throws SQLException {
2050: if (!this .isBinaryEncoded) {
2051: String asString = getStringForClob(i);
2052:
2053: if (asString == null) {
2054: return null;
2055: }
2056:
2057: return new com.mysql.jdbc.Clob(asString);
2058: }
2059:
2060: return getNativeClob(i);
2061: }
2062:
2063: /**
2064: * JDBC 2.0 Get a CLOB column.
2065: *
2066: * @param colName
2067: * the column name
2068: *
2069: * @return an object representing a CLOB
2070: *
2071: * @throws SQLException
2072: * if an error occurs
2073: */
2074: public java.sql.Clob getClob(String colName) throws SQLException {
2075: return getClob(findColumn(colName));
2076: }
2077:
2078: private final java.sql.Clob getClobFromString(String stringVal,
2079: int columnIndex) throws SQLException {
2080: return new com.mysql.jdbc.Clob(stringVal);
2081: }
2082:
2083: /**
2084: * JDBC 2.0 Return the concurrency of this result set. The concurrency used
2085: * is determined by the statement that created the result set.
2086: *
2087: * @return the concurrency type, CONCUR_READ_ONLY, etc.
2088: *
2089: * @throws SQLException
2090: * if a database-access error occurs
2091: */
2092: public int getConcurrency() throws SQLException {
2093: return (CONCUR_READ_ONLY);
2094: }
2095:
2096: /**
2097: * Get the name of the SQL cursor used by this ResultSet
2098: *
2099: * <p>
2100: * In SQL, a result table is retrieved though a cursor that is named. The
2101: * current row of a result can be updated or deleted using a positioned
2102: * update/delete statement that references the cursor name.
2103: * </p>
2104: *
2105: * <p>
2106: * JDBC supports this SQL feature by providing the name of the SQL cursor
2107: * used by a ResultSet. The current row of a ResulSet is also the current
2108: * row of this SQL cursor.
2109: * </p>
2110: *
2111: * <p>
2112: * <B>Note:</B> If positioned update is not supported, a SQLException is
2113: * thrown.
2114: * </p>
2115: *
2116: * @return the ResultSet's SQL cursor name.
2117: *
2118: * @exception SQLException
2119: * if a database access error occurs
2120: */
2121: public String getCursorName() throws SQLException {
2122: throw SQLError
2123: .createSQLException(
2124: Messages
2125: .getString("ResultSet.Positioned_Update_not_supported"),
2126: SQLError.SQL_STATE_DRIVER_NOT_CAPABLE); //$NON-NLS-1$
2127: }
2128:
2129: /**
2130: * Get the value of a column in the current row as a java.sql.Date object
2131: *
2132: * @param columnIndex
2133: * the first column is 1, the second is 2...
2134: *
2135: * @return the column value; null if SQL NULL
2136: *
2137: * @exception java.sql.SQLException
2138: * if a database access error occurs
2139: */
2140: public java.sql.Date getDate(int columnIndex)
2141: throws java.sql.SQLException {
2142: return getDate(columnIndex, null);
2143: }
2144:
2145: /**
2146: * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
2147: * object. Use the calendar to construct an appropriate millisecond value
2148: * for the Date, if the underlying database doesn't store timezone
2149: * information.
2150: *
2151: * @param columnIndex
2152: * the first column is 1, the second is 2, ...
2153: * @param cal
2154: * the calendar to use in constructing the date
2155: *
2156: * @return the column value; if the value is SQL NULL, the result is null
2157: *
2158: * @exception SQLException
2159: * if a database-access error occurs.
2160: */
2161: public java.sql.Date getDate(int columnIndex, Calendar cal)
2162: throws SQLException {
2163: if (this .isBinaryEncoded) {
2164: return getNativeDate(columnIndex, (cal != null) ? cal
2165: .getTimeZone() : this .getDefaultTimeZone());
2166: }
2167:
2168: if (!this .useFastDateParsing) {
2169: String stringVal = getStringInternal(columnIndex, false);
2170:
2171: if (stringVal == null) {
2172: return null;
2173: }
2174:
2175: return getDateFromString(stringVal, columnIndex);
2176: }
2177:
2178: checkColumnBounds(columnIndex);
2179:
2180: int columnIndexMinusOne = columnIndex - 1;
2181:
2182: if (this .this Row.isNull(columnIndexMinusOne)) {
2183: this .wasNullFlag = true;
2184:
2185: return null;
2186: }
2187:
2188: this .wasNullFlag = false;
2189:
2190: return this .this Row.getDateFast(columnIndexMinusOne,
2191: this .connection, this );
2192: }
2193:
2194: /**
2195: * DOCUMENT ME!
2196: *
2197: * @param columnName
2198: * DOCUMENT ME!
2199: *
2200: * @return DOCUMENT ME!
2201: *
2202: * @throws java.sql.SQLException
2203: * DOCUMENT ME!
2204: */
2205: public java.sql.Date getDate(String columnName)
2206: throws java.sql.SQLException {
2207: return getDate(findColumn(columnName));
2208: }
2209:
2210: /**
2211: * Get the value of a column in the current row as a java.sql.Date object.
2212: * Use the calendar to construct an appropriate millisecond value for the
2213: * Date, if the underlying database doesn't store timezone information.
2214: *
2215: * @param columnName
2216: * is the SQL name of the column
2217: * @param cal
2218: * the calendar to use in constructing the date
2219: *
2220: * @return the column value; if the value is SQL NULL, the result is null
2221: *
2222: * @exception SQLException
2223: * if a database-access error occurs.
2224: */
2225: public java.sql.Date getDate(String columnName, Calendar cal)
2226: throws SQLException {
2227: return getDate(findColumn(columnName), cal);
2228: }
2229:
2230: private final java.sql.Date getDateFromString(String stringVal,
2231: int columnIndex) throws SQLException {
2232: int year = 0;
2233: int month = 0;
2234: int day = 0;
2235:
2236: try {
2237: this .wasNullFlag = false;
2238:
2239: if (stringVal == null) {
2240: this .wasNullFlag = true;
2241:
2242: return null;
2243: }
2244:
2245: //
2246: // JDK-6 doesn't like trailing whitespace
2247: //
2248: // Note this isn't a performance issue, other
2249: // than the iteration over the string, as String.trim()
2250: // will return a new string only if whitespace is present
2251: //
2252:
2253: stringVal = stringVal.trim();
2254:
2255: if (stringVal.equals("0") || stringVal.equals("0000-00-00")
2256: || stringVal.equals("0000-00-00 00:00:00")
2257: || stringVal.equals("00000000000000")
2258: || stringVal.equals("0")) {
2259:
2260: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
2261: .equals(this .connection
2262: .getZeroDateTimeBehavior())) {
2263: this .wasNullFlag = true;
2264:
2265: return null;
2266: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
2267: .equals(this .connection
2268: .getZeroDateTimeBehavior())) {
2269: throw SQLError
2270: .createSQLException(
2271: "Value '"
2272: + stringVal
2273: + "' can not be represented as java.sql.Date",
2274: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2275: }
2276:
2277: // We're left with the case of 'round' to a date Java _can_
2278: // represent, which is '0001-01-01'.
2279: return fastDateCreate(null, 1, 1, 1);
2280:
2281: } else if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
2282: // Convert from TIMESTAMP
2283: switch (stringVal.length()) {
2284: case 21:
2285: case 19: { // java.sql.Timestamp format
2286: year = Integer.parseInt(stringVal.substring(0, 4));
2287: month = Integer.parseInt(stringVal.substring(5, 7));
2288: day = Integer.parseInt(stringVal.substring(8, 10));
2289:
2290: return fastDateCreate(null, year, month, day);
2291: }
2292:
2293: case 14:
2294: case 8: {
2295: year = Integer.parseInt(stringVal.substring(0, 4));
2296: month = Integer.parseInt(stringVal.substring(4, 6));
2297: day = Integer.parseInt(stringVal.substring(6, 8));
2298:
2299: return fastDateCreate(null, year, month, day);
2300: }
2301:
2302: case 12:
2303: case 10:
2304: case 6: {
2305: year = Integer.parseInt(stringVal.substring(0, 2));
2306:
2307: if (year <= 69) {
2308: year = year + 100;
2309: }
2310:
2311: month = Integer.parseInt(stringVal.substring(2, 4));
2312: day = Integer.parseInt(stringVal.substring(4, 6));
2313:
2314: return fastDateCreate(null, year + 1900, month, day);
2315: }
2316:
2317: case 4: {
2318: year = Integer.parseInt(stringVal.substring(0, 4));
2319:
2320: if (year <= 69) {
2321: year = year + 100;
2322: }
2323:
2324: month = Integer.parseInt(stringVal.substring(2, 4));
2325:
2326: return fastDateCreate(null, year + 1900, month, 1);
2327: }
2328:
2329: case 2: {
2330: year = Integer.parseInt(stringVal.substring(0, 2));
2331:
2332: if (year <= 69) {
2333: year = year + 100;
2334: }
2335:
2336: return fastDateCreate(null, year + 1900, 1, 1);
2337: }
2338:
2339: default:
2340: throw SQLError
2341: .createSQLException(
2342: Messages
2343: .getString(
2344: "ResultSet.Bad_format_for_Date",
2345: new Object[] {
2346: stringVal,
2347: Constants
2348: .integerValueOf(columnIndex) }),
2349: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2350: } /* endswitch */
2351: } else if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
2352:
2353: if (stringVal.length() == 2 || stringVal.length() == 1) {
2354: year = Integer.parseInt(stringVal);
2355:
2356: if (year <= 69) {
2357: year = year + 100;
2358: }
2359:
2360: year += 1900;
2361: } else {
2362: year = Integer.parseInt(stringVal.substring(0, 4));
2363: }
2364:
2365: return fastDateCreate(null, year, 1, 1);
2366: } else if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_TIME) {
2367: return fastDateCreate(null, 1970, 1, 1); // Return EPOCH
2368: } else {
2369: if (stringVal.length() < 10) {
2370: if (stringVal.length() == 8) {
2371: return fastDateCreate(null, 1970, 1, 1); // Return EPOCH for TIME
2372: }
2373:
2374: throw SQLError
2375: .createSQLException(
2376: Messages
2377: .getString(
2378: "ResultSet.Bad_format_for_Date",
2379: new Object[] {
2380: stringVal,
2381: Constants
2382: .integerValueOf(columnIndex) }),
2383: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2384: }
2385:
2386: if (stringVal.length() != 18) {
2387: year = Integer.parseInt(stringVal.substring(0, 4));
2388: month = Integer.parseInt(stringVal.substring(5, 7));
2389: day = Integer.parseInt(stringVal.substring(8, 10));
2390: } else {
2391: // JDK-1.3 timestamp format, not real easy to parse positionally :p
2392: StringTokenizer st = new StringTokenizer(stringVal,
2393: "- ");
2394:
2395: year = Integer.parseInt(st.nextToken());
2396: month = Integer.parseInt(st.nextToken());
2397: day = Integer.parseInt(st.nextToken());
2398: }
2399: }
2400:
2401: return fastDateCreate(null, year, month, day);
2402: } catch (SQLException sqlEx) {
2403: throw sqlEx; // don't re-wrap
2404: } catch (Exception e) {
2405: throw SQLError.createSQLException(Messages.getString(
2406: "ResultSet.Bad_format_for_Date", new Object[] {
2407: stringVal,
2408: Constants.integerValueOf(columnIndex) }),
2409: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2410: }
2411: }
2412:
2413: private TimeZone getDefaultTimeZone() {
2414: return this .connection.getDefaultTimeZone();
2415: }
2416:
2417: /**
2418: * Get the value of a column in the current row as a Java double.
2419: *
2420: * @param columnIndex
2421: * the first column is 1, the second is 2,...
2422: *
2423: * @return the column value; 0 if SQL NULL
2424: *
2425: * @exception SQLException
2426: * if a database access error occurs
2427: */
2428: public double getDouble(int columnIndex) throws SQLException {
2429: if (!this .isBinaryEncoded) {
2430: return getDoubleInternal(columnIndex);
2431: }
2432:
2433: return getNativeDouble(columnIndex);
2434: }
2435:
2436: /**
2437: * DOCUMENT ME!
2438: *
2439: * @param columnName
2440: * DOCUMENT ME!
2441: *
2442: * @return DOCUMENT ME!
2443: *
2444: * @throws SQLException
2445: * DOCUMENT ME!
2446: */
2447: public double getDouble(String columnName) throws SQLException {
2448: return getDouble(findColumn(columnName));
2449: }
2450:
2451: private final double getDoubleFromString(String stringVal,
2452: int columnIndex) throws SQLException {
2453: return getDoubleInternal(stringVal, columnIndex);
2454: }
2455:
2456: /**
2457: * Converts a string representation of a number to a double. Need a faster
2458: * way to do this.
2459: *
2460: * @param colIndex
2461: * the 1-based index of the column to retrieve a double from.
2462: *
2463: * @return the double value represented by the string in buf
2464: *
2465: * @throws SQLException
2466: * if an error occurs
2467: */
2468: protected double getDoubleInternal(int colIndex)
2469: throws SQLException {
2470: return getDoubleInternal(getString(colIndex), colIndex);
2471: }
2472:
2473: /**
2474: * Converts a string representation of a number to a double. Need a faster
2475: * way to do this.
2476: *
2477: * @param stringVal
2478: * the double as a String
2479: * @param colIndex
2480: * the 1-based index of the column to retrieve a double from.
2481: *
2482: * @return the double value represented by the string in buf
2483: *
2484: * @throws SQLException
2485: * if an error occurs
2486: */
2487: protected double getDoubleInternal(String stringVal, int colIndex)
2488: throws SQLException {
2489: try {
2490: if ((stringVal == null)) {
2491: return 0;
2492: }
2493:
2494: if (stringVal.length() == 0) {
2495: return convertToZeroWithEmptyCheck();
2496: }
2497:
2498: double d = Double.parseDouble(stringVal);
2499:
2500: if (this .useStrictFloatingPoint) {
2501: // Fix endpoint rounding precision loss in MySQL server
2502: if (d == 2.147483648E9) {
2503: // Fix Odd end-point rounding on MySQL
2504: d = 2.147483647E9;
2505: } else if (d == 1.0000000036275E-15) {
2506: // Fix odd end-point rounding on MySQL
2507: d = 1.0E-15;
2508: } else if (d == 9.999999869911E14) {
2509: d = 9.99999999999999E14;
2510: } else if (d == 1.4012984643248E-45) {
2511: d = 1.4E-45;
2512: } else if (d == 1.4013E-45) {
2513: d = 1.4E-45;
2514: } else if (d == 3.4028234663853E37) {
2515: d = 3.4028235E37;
2516: } else if (d == -2.14748E9) {
2517: d = -2.147483648E9;
2518: } else if (d == 3.40282E37) {
2519: d = 3.4028235E37;
2520: }
2521: }
2522:
2523: return d;
2524: } catch (NumberFormatException e) {
2525: if (this .fields[colIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2526: long valueAsLong = getNumericRepresentationOfSQLBitType(colIndex);
2527:
2528: return valueAsLong;
2529: }
2530:
2531: throw SQLError.createSQLException(Messages.getString(
2532: "ResultSet.Bad_format_for_number", new Object[] {
2533: stringVal,
2534: Constants.integerValueOf(colIndex) }),
2535: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2536: }
2537: }
2538:
2539: /**
2540: * JDBC 2.0 Returns the fetch direction for this result set.
2541: *
2542: * @return the fetch direction for this result set.
2543: *
2544: * @exception SQLException
2545: * if a database-access error occurs
2546: */
2547: public int getFetchDirection() throws SQLException {
2548: return this .fetchDirection;
2549: }
2550:
2551: /**
2552: * JDBC 2.0 Return the fetch size for this result set.
2553: *
2554: * @return the fetch size for this result set.
2555: *
2556: * @exception SQLException
2557: * if a database-access error occurs
2558: */
2559: public int getFetchSize() throws SQLException {
2560: return this .fetchSize;
2561: }
2562:
2563: /**
2564: * Returns the first character of the query that this result set was created
2565: * from.
2566: *
2567: * @return the first character of the query...uppercased
2568: */
2569: public char getFirstCharOfQuery() {
2570: return this .firstCharOfQuery;
2571: }
2572:
2573: /**
2574: * Get the value of a column in the current row as a Java float.
2575: *
2576: * @param columnIndex
2577: * the first column is 1, the second is 2,...
2578: *
2579: * @return the column value; 0 if SQL NULL
2580: *
2581: * @exception SQLException
2582: * if a database access error occurs
2583: */
2584: public float getFloat(int columnIndex) throws SQLException {
2585: if (!this .isBinaryEncoded) {
2586: String val = null;
2587:
2588: val = getString(columnIndex);
2589:
2590: return getFloatFromString(val, columnIndex);
2591: }
2592:
2593: return getNativeFloat(columnIndex);
2594: }
2595:
2596: /**
2597: * DOCUMENT ME!
2598: *
2599: * @param columnName
2600: * DOCUMENT ME!
2601: *
2602: * @return DOCUMENT ME!
2603: *
2604: * @throws SQLException
2605: * DOCUMENT ME!
2606: */
2607: public float getFloat(String columnName) throws SQLException {
2608: return getFloat(findColumn(columnName));
2609: }
2610:
2611: private final float getFloatFromString(String val, int columnIndex)
2612: throws SQLException {
2613: try {
2614: if ((val != null)) {
2615: if (val.length() == 0) {
2616: return convertToZeroWithEmptyCheck();
2617: }
2618:
2619: float f = Float.parseFloat(val);
2620:
2621: if (this .connection
2622: .getJdbcCompliantTruncationForReads()) {
2623: if (f == Float.MIN_VALUE || f == Float.MAX_VALUE) {
2624: double valAsDouble = Double.parseDouble(val);
2625:
2626: // Straight comparison is not reliable when at
2627: // absolute endpoints of Float.MIN_VALUE or
2628: // Float.MAX_VALUE, so use epsillons with DOUBLEs
2629:
2630: if ((valAsDouble < Float.MIN_VALUE
2631: - MIN_DIFF_PREC)
2632: || (valAsDouble > Float.MAX_VALUE
2633: - MAX_DIFF_PREC)) {
2634: throwRangeException(String
2635: .valueOf(valAsDouble), columnIndex,
2636: Types.FLOAT);
2637: }
2638: }
2639: }
2640:
2641: return f;
2642: }
2643:
2644: return 0; // for NULL
2645: } catch (NumberFormatException nfe) {
2646: try {
2647: Double valueAsDouble = new Double(val);
2648: float valueAsFloat = valueAsDouble.floatValue();
2649:
2650: if (this .connection
2651: .getJdbcCompliantTruncationForReads()) {
2652:
2653: if (this .connection
2654: .getJdbcCompliantTruncationForReads()
2655: && valueAsFloat == Float.NEGATIVE_INFINITY
2656: || valueAsFloat == Float.POSITIVE_INFINITY) {
2657: throwRangeException(valueAsDouble.toString(),
2658: columnIndex, Types.FLOAT);
2659: }
2660: }
2661:
2662: return valueAsFloat;
2663: } catch (NumberFormatException newNfe) {
2664: ; // ignore, it's not a number
2665: }
2666:
2667: throw SQLError
2668: .createSQLException(
2669: Messages
2670: .getString("ResultSet.Invalid_value_for_getFloat()_-____200")
2671: + val //$NON-NLS-1$
2672: + Messages
2673: .getString("ResultSet.___in_column__201")
2674: + columnIndex,
2675: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2676: }
2677: }
2678:
2679: /**
2680: * Get the value of a column in the current row as a Java int.
2681: *
2682: * @param columnIndex
2683: * the first column is 1, the second is 2,...
2684: *
2685: * @return the column value; 0 if SQL NULL
2686: *
2687: * @exception SQLException
2688: * if a database access error occurs
2689: */
2690: public int getInt(int columnIndex) throws SQLException {
2691: checkRowPos();
2692:
2693: if (!this .isBinaryEncoded) {
2694: int columnIndexMinusOne = columnIndex - 1;
2695: if (this .connection.getUseFastIntParsing()) {
2696: checkColumnBounds(columnIndex);
2697:
2698: if (this .this Row.isNull(columnIndexMinusOne)) {
2699: this .wasNullFlag = true;
2700: } else {
2701: this .wasNullFlag = false;
2702: }
2703:
2704: if (this .wasNullFlag) {
2705: return 0;
2706: }
2707:
2708: if (this .this Row.length(columnIndexMinusOne) == 0) {
2709: return convertToZeroWithEmptyCheck();
2710: }
2711:
2712: boolean needsFullParse = this .this Row
2713: .isFloatingPointNumber(columnIndexMinusOne);
2714:
2715: if (!needsFullParse) {
2716: try {
2717: return getIntWithOverflowCheck(columnIndexMinusOne);
2718: } catch (NumberFormatException nfe) {
2719: try {
2720:
2721: return parseIntAsDouble(
2722: columnIndex,
2723: this .this Row
2724: .getString(
2725: columnIndexMinusOne,
2726: this .fields[columnIndexMinusOne]
2727: .getCharacterSet(),
2728: this .connection));
2729: } catch (NumberFormatException newNfe) {
2730: // ignore, it's not a number
2731: }
2732:
2733: if (this .fields[columnIndexMinusOne]
2734: .getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2735: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
2736:
2737: if (this .connection
2738: .getJdbcCompliantTruncationForReads()
2739: && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
2740: throwRangeException(String
2741: .valueOf(valueAsLong),
2742: columnIndex, Types.INTEGER);
2743: }
2744:
2745: return (int) valueAsLong;
2746: }
2747:
2748: throw SQLError
2749: .createSQLException(
2750: Messages
2751: .getString("ResultSet.Invalid_value_for_getInt()_-____74")
2752: + this .this Row
2753: .getString(
2754: columnIndexMinusOne,
2755: this .fields[columnIndexMinusOne]
2756: .getCharacterSet(),
2757: this .connection) //$NON-NLS-1$
2758: + "'",
2759: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2760: }
2761: }
2762: }
2763:
2764: String val = null;
2765:
2766: try {
2767: val = getString(columnIndex);
2768:
2769: if ((val != null)) {
2770: if (val.length() == 0) {
2771: return convertToZeroWithEmptyCheck();
2772: }
2773:
2774: if ((val.indexOf("e") == -1)
2775: && (val.indexOf("E") == -1)
2776: && (val.indexOf(".") == -1)) {
2777: int intVal = Integer.parseInt(val);
2778:
2779: checkForIntegerTruncation(columnIndex, null,
2780: val, intVal);
2781:
2782: return intVal;
2783: }
2784:
2785: // Convert floating point
2786: int intVal = parseIntAsDouble(columnIndex, val);
2787:
2788: checkForIntegerTruncation(columnIndex, null, val,
2789: intVal);
2790:
2791: return intVal;
2792: }
2793:
2794: return 0;
2795: } catch (NumberFormatException nfe) {
2796: try {
2797: return parseIntAsDouble(columnIndex, val);
2798: } catch (NumberFormatException newNfe) {
2799: ; // ignore, it's not a number
2800: }
2801:
2802: if (this .fields[columnIndexMinusOne].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2803: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
2804:
2805: if (this .connection
2806: .getJdbcCompliantTruncationForReads()
2807: && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
2808: throwRangeException(
2809: String.valueOf(valueAsLong),
2810: columnIndex, Types.INTEGER);
2811: }
2812:
2813: return (int) valueAsLong;
2814: }
2815:
2816: throw SQLError
2817: .createSQLException(
2818: Messages
2819: .getString("ResultSet.Invalid_value_for_getInt()_-____74")
2820: + val //$NON-NLS-1$
2821: + "'",
2822: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
2823: }
2824: }
2825:
2826: return getNativeInt(columnIndex);
2827: }
2828:
2829: /**
2830: * DOCUMENT ME!
2831: *
2832: * @param columnName
2833: * DOCUMENT ME!
2834: *
2835: * @return DOCUMENT ME!
2836: *
2837: * @throws SQLException
2838: * DOCUMENT ME!
2839: */
2840: public int getInt(String columnName) throws SQLException {
2841: return getInt(findColumn(columnName));
2842: }
2843:
2844: private final int getIntFromString(String val, int columnIndex)
2845: throws SQLException {
2846: try {
2847: if ((val != null)) {
2848:
2849: if (val.length() == 0) {
2850: return convertToZeroWithEmptyCheck();
2851: }
2852:
2853: if ((val.indexOf("e") == -1)
2854: && (val.indexOf("E") == -1)
2855: && (val.indexOf(".") == -1)) {
2856: //
2857: // JDK-6 doesn't like trailing whitespace
2858: //
2859: // Note this isn't a performance issue, other
2860: // than the iteration over the string, as String.trim()
2861: // will return a new string only if whitespace is present
2862: //
2863:
2864: val = val.trim();
2865:
2866: int valueAsInt = Integer.parseInt(val);
2867:
2868: if (this .connection
2869: .getJdbcCompliantTruncationForReads()) {
2870: if (valueAsInt == Integer.MIN_VALUE
2871: || valueAsInt == Integer.MAX_VALUE) {
2872: long valueAsLong = Long.parseLong(val);
2873:
2874: if (valueAsLong < Integer.MIN_VALUE
2875: || valueAsLong > Integer.MAX_VALUE) {
2876: throwRangeException(String
2877: .valueOf(valueAsLong),
2878: columnIndex, Types.INTEGER);
2879: }
2880: }
2881: }
2882:
2883: return valueAsInt;
2884: }
2885:
2886: // Convert floating point
2887:
2888: double valueAsDouble = Double.parseDouble(val);
2889:
2890: if (this .connection
2891: .getJdbcCompliantTruncationForReads()) {
2892: if (valueAsDouble < Integer.MIN_VALUE
2893: || valueAsDouble > Integer.MAX_VALUE) {
2894: throwRangeException(String
2895: .valueOf(valueAsDouble), columnIndex,
2896: Types.INTEGER);
2897: }
2898: }
2899:
2900: return (int) valueAsDouble;
2901: }
2902:
2903: return 0; // for NULL
2904: } catch (NumberFormatException nfe) {
2905: try {
2906: double valueAsDouble = Double.parseDouble(val);
2907:
2908: if (this .connection
2909: .getJdbcCompliantTruncationForReads()) {
2910: if (valueAsDouble < Integer.MIN_VALUE
2911: || valueAsDouble > Integer.MAX_VALUE) {
2912: throwRangeException(String
2913: .valueOf(valueAsDouble), columnIndex,
2914: Types.INTEGER);
2915: }
2916: }
2917:
2918: return (int) valueAsDouble;
2919: } catch (NumberFormatException newNfe) {
2920: ; // ignore, it's not a number
2921: }
2922:
2923: throw SQLError
2924: .createSQLException(
2925: Messages
2926: .getString("ResultSet.Invalid_value_for_getInt()_-____206")
2927: + val //$NON-NLS-1$
2928: + Messages
2929: .getString("ResultSet.___in_column__207")
2930: + columnIndex,
2931: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
2932: }
2933: }
2934:
2935: /**
2936: * Get the value of a column in the current row as a Java long.
2937: *
2938: * @param columnIndex
2939: * the first column is 1, the second is 2,...
2940: *
2941: * @return the column value; 0 if SQL NULL
2942: *
2943: * @exception SQLException
2944: * if a database access error occurs
2945: */
2946: public long getLong(int columnIndex) throws SQLException {
2947: return getLong(columnIndex, true);
2948: }
2949:
2950: private long getLong(int columnIndex, boolean overflowCheck)
2951: throws SQLException {
2952: if (!this .isBinaryEncoded) {
2953: checkRowPos();
2954:
2955: int columnIndexMinusOne = columnIndex - 1;
2956:
2957: if (this .connection.getUseFastIntParsing()) {
2958:
2959: checkColumnBounds(columnIndex);
2960:
2961: if (this .this Row.isNull(columnIndexMinusOne)) {
2962: this .wasNullFlag = true;
2963: } else {
2964: this .wasNullFlag = false;
2965: }
2966:
2967: if (this .wasNullFlag) {
2968: return 0;
2969: }
2970:
2971: if (this .this Row.length(columnIndexMinusOne) == 0) {
2972: return convertToZeroWithEmptyCheck();
2973: }
2974:
2975: boolean needsFullParse = this .this Row
2976: .isFloatingPointNumber(columnIndexMinusOne);
2977:
2978: if (!needsFullParse) {
2979: try {
2980: return getLongWithOverflowCheck(
2981: columnIndexMinusOne, overflowCheck);
2982: } catch (NumberFormatException nfe) {
2983: try {
2984: // To do: Warn of over/underflow???
2985: return parseLongAsDouble(
2986: columnIndex,
2987: this .this Row
2988: .getString(
2989: columnIndexMinusOne,
2990: this .fields[columnIndexMinusOne]
2991: .getCharacterSet(),
2992: this .connection));
2993: } catch (NumberFormatException newNfe) {
2994: // ; // ignore, it's not a number
2995: }
2996:
2997: if (this .fields[columnIndexMinusOne]
2998: .getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
2999: return getNumericRepresentationOfSQLBitType(columnIndex);
3000: }
3001:
3002: throw SQLError
3003: .createSQLException(
3004: Messages
3005: .getString("ResultSet.Invalid_value_for_getLong()_-____79")
3006: + this .this Row
3007: .getString(
3008: columnIndexMinusOne,
3009: this .fields[columnIndexMinusOne]
3010: .getCharacterSet(),
3011: this .connection) //$NON-NLS-1$
3012: + "'",
3013: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3014: }
3015: }
3016: }
3017:
3018: String val = null;
3019:
3020: try {
3021: val = getString(columnIndex);
3022:
3023: if ((val != null)) {
3024: if (val.length() == 0) {
3025: return convertToZeroWithEmptyCheck();
3026: }
3027:
3028: if ((val.indexOf("e") == -1)
3029: && (val.indexOf("E") == -1)) {
3030: return parseLongWithOverflowCheck(columnIndex,
3031: null, val, overflowCheck);
3032: }
3033:
3034: // Convert floating point
3035: return parseLongAsDouble(columnIndex, val);
3036: }
3037:
3038: return 0; // for NULL
3039: } catch (NumberFormatException nfe) {
3040: try {
3041: return parseLongAsDouble(columnIndex, val);
3042: } catch (NumberFormatException newNfe) {
3043: // ; // ignore, it's not a number
3044: }
3045:
3046: throw SQLError
3047: .createSQLException(
3048: Messages
3049: .getString("ResultSet.Invalid_value_for_getLong()_-____79")
3050: + val //$NON-NLS-1$
3051: + "'",
3052: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3053: }
3054: }
3055:
3056: return getNativeLong(columnIndex, overflowCheck, true);
3057: }
3058:
3059: /**
3060: * DOCUMENT ME!
3061: *
3062: * @param columnName
3063: * DOCUMENT ME!
3064: *
3065: * @return DOCUMENT ME!
3066: *
3067: * @throws SQLException
3068: * DOCUMENT ME!
3069: */
3070: public long getLong(String columnName) throws SQLException {
3071: return getLong(findColumn(columnName));
3072: }
3073:
3074: private final long getLongFromString(String val, int columnIndex)
3075: throws SQLException {
3076: try {
3077: if ((val != null)) {
3078:
3079: if (val.length() == 0) {
3080: return convertToZeroWithEmptyCheck();
3081: }
3082:
3083: if ((val.indexOf("e") == -1)
3084: && (val.indexOf("E") == -1)) {
3085: return parseLongWithOverflowCheck(columnIndex,
3086: null, val, true);
3087: }
3088:
3089: // Convert floating point
3090: return parseLongAsDouble(columnIndex, val);
3091: }
3092:
3093: return 0; // for NULL
3094: } catch (NumberFormatException nfe) {
3095: try {
3096: // To do: Warn of over/underflow???
3097: return parseLongAsDouble(columnIndex, val);
3098: } catch (NumberFormatException newNfe) {
3099: ; // ignore, it's not a number
3100: }
3101:
3102: throw SQLError
3103: .createSQLException(
3104: Messages
3105: .getString("ResultSet.Invalid_value_for_getLong()_-____211")
3106: + val //$NON-NLS-1$
3107: + Messages
3108: .getString("ResultSet.___in_column__212")
3109: + columnIndex,
3110: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
3111: }
3112: }
3113:
3114: /**
3115: * The numbers, types and properties of a ResultSet's columns are provided
3116: * by the getMetaData method
3117: *
3118: * @return a description of the ResultSet's columns
3119: *
3120: * @exception SQLException
3121: * if a database access error occurs
3122: */
3123: public java.sql.ResultSetMetaData getMetaData() throws SQLException {
3124: checkClosed();
3125:
3126: return new com.mysql.jdbc.ResultSetMetaData(this .fields,
3127: this .connection.getUseOldAliasMetadataBehavior());
3128: }
3129:
3130: /**
3131: * JDBC 2.0 Get an array column.
3132: *
3133: * @param i
3134: * the first column is 1, the second is 2, ...
3135: *
3136: * @return an object representing an SQL array
3137: *
3138: * @throws SQLException
3139: * if a database error occurs
3140: * @throws NotImplemented
3141: * DOCUMENT ME!
3142: */
3143: protected java.sql.Array getNativeArray(int i) throws SQLException {
3144: throw new NotImplemented();
3145: }
3146:
3147: /**
3148: * A column value can be retrieved as a stream of ASCII characters and then
3149: * read in chunks from the stream. This method is particulary suitable for
3150: * retrieving large LONGVARCHAR values. The JDBC driver will do any
3151: * necessary conversion from the database format into ASCII.
3152: *
3153: * <p>
3154: * <B>Note:</B> All the data in the returned stream must be read prior to
3155: * getting the value of any other column. The next call to a get method
3156: * implicitly closes the stream. Also, a stream may return 0 for available()
3157: * whether there is data available or not.
3158: * </p>
3159: *
3160: * @param columnIndex
3161: * the first column is 1, the second is 2, ...
3162: *
3163: * @return a Java InputStream that delivers the database column value as a
3164: * stream of one byte ASCII characters. If the value is SQL NULL
3165: * then the result is null
3166: *
3167: * @exception SQLException
3168: * if a database access error occurs
3169: *
3170: * @see getBinaryStream
3171: */
3172: protected InputStream getNativeAsciiStream(int columnIndex)
3173: throws SQLException {
3174: checkRowPos();
3175:
3176: return getNativeBinaryStream(columnIndex);
3177: }
3178:
3179: /**
3180: * JDBC 2.0 Get the value of a column in the current row as a
3181: * java.math.BigDecimal object.
3182: *
3183: * @param columnIndex
3184: * the first column is 1, the second is 2, ...
3185: *
3186: * @return the column value (full precision); if the value is SQL NULL, the
3187: * result is null
3188: *
3189: * @exception SQLException
3190: * if a database-access error occurs.
3191: */
3192: protected BigDecimal getNativeBigDecimal(int columnIndex)
3193: throws SQLException {
3194:
3195: checkColumnBounds(columnIndex);
3196:
3197: int scale = this .fields[columnIndex - 1].getDecimals();
3198:
3199: return getNativeBigDecimal(columnIndex, scale);
3200: }
3201:
3202: /**
3203: * Get the value of a column in the current row as a java.math.BigDecimal
3204: * object
3205: *
3206: * @param columnIndex
3207: * the first column is 1, the second is 2...
3208: * @param scale
3209: * the number of digits to the right of the decimal
3210: *
3211: * @return the column value; if the value is SQL NULL, null
3212: *
3213: * @exception SQLException
3214: * if a database access error occurs
3215: */
3216: protected BigDecimal getNativeBigDecimal(int columnIndex, int scale)
3217: throws SQLException {
3218: checkColumnBounds(columnIndex);
3219:
3220: String stringVal = null;
3221:
3222: Field f = this .fields[columnIndex - 1];
3223:
3224: Object value = this .this Row.getColumnValue(columnIndex - 1);
3225:
3226: if (value == null) {
3227: this .wasNullFlag = true;
3228:
3229: return null;
3230: }
3231:
3232: this .wasNullFlag = false;
3233:
3234: switch (f.getSQLType()) {
3235: case Types.DECIMAL:
3236: case Types.NUMERIC:
3237: stringVal = StringUtils.toAsciiString((byte[]) value);
3238: break;
3239: default:
3240: stringVal = getNativeString(columnIndex);
3241: }
3242:
3243: return getBigDecimalFromString(stringVal, columnIndex, scale);
3244: }
3245:
3246: /**
3247: * A column value can also be retrieved as a binary stream. This method is
3248: * suitable for retrieving LONGVARBINARY values.
3249: *
3250: * @param columnIndex
3251: * the first column is 1, the second is 2...
3252: *
3253: * @return a Java InputStream that delivers the database column value as a
3254: * stream of bytes. If the value is SQL NULL, then the result is
3255: * null
3256: *
3257: * @exception SQLException
3258: * if a database access error occurs
3259: *
3260: * @see getAsciiStream
3261: * @see getUnicodeStream
3262: */
3263: protected InputStream getNativeBinaryStream(int columnIndex)
3264: throws SQLException {
3265: checkRowPos();
3266:
3267: int columnIndexMinusOne = columnIndex - 1;
3268:
3269: if (this .this Row.isNull(columnIndexMinusOne)) {
3270: this .wasNullFlag = true;
3271:
3272: return null;
3273: }
3274:
3275: this .wasNullFlag = false;
3276:
3277: switch (this .fields[columnIndexMinusOne].getSQLType()) {
3278: case Types.BIT:
3279: case Types.BINARY:
3280: case Types.VARBINARY:
3281: case Types.BLOB:
3282: case Types.LONGVARBINARY:
3283: return this .this Row
3284: .getBinaryInputStream(columnIndexMinusOne);
3285: }
3286:
3287: byte[] b = getNativeBytes(columnIndex, false);
3288:
3289: if (b != null) {
3290: return new ByteArrayInputStream(b);
3291: }
3292:
3293: return null;
3294: }
3295:
3296: /**
3297: * JDBC 2.0 Get a BLOB column.
3298: *
3299: * @param columnIndex
3300: * the first column is 1, the second is 2, ...
3301: *
3302: * @return an object representing a BLOB
3303: *
3304: * @throws SQLException
3305: * if an error occurs.
3306: */
3307: protected java.sql.Blob getNativeBlob(int columnIndex)
3308: throws SQLException {
3309: checkRowPos();
3310:
3311: checkColumnBounds(columnIndex);
3312:
3313: Object value = this .this Row.getColumnValue(columnIndex - 1);
3314:
3315: if (value == null) {
3316: this .wasNullFlag = true;
3317: } else {
3318: this .wasNullFlag = false;
3319: }
3320:
3321: if (this .wasNullFlag) {
3322: return null;
3323: }
3324:
3325: int mysqlType = this .fields[columnIndex - 1].getMysqlType();
3326:
3327: byte[] dataAsBytes = null;
3328:
3329: switch (mysqlType) {
3330: case MysqlDefs.FIELD_TYPE_TINY_BLOB:
3331: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
3332: case MysqlDefs.FIELD_TYPE_LONG_BLOB:
3333: case MysqlDefs.FIELD_TYPE_BLOB:
3334: dataAsBytes = (byte[]) value;
3335: break;
3336:
3337: default:
3338: dataAsBytes = getNativeBytes(columnIndex, false);
3339: }
3340:
3341: if (!this .connection.getEmulateLocators()) {
3342: return new Blob(dataAsBytes);
3343: }
3344:
3345: return new BlobFromLocator(this , columnIndex);
3346: }
3347:
3348: public static boolean arraysEqual(byte[] left, byte[] right) {
3349: if (left == null) {
3350: return right == null;
3351: }
3352: if (right == null) {
3353: return false;
3354: }
3355: if (left.length != right.length) {
3356: return false;
3357: }
3358: for (int i = 0; i < left.length; i++) {
3359: if (left[i] != right[i]) {
3360: return false;
3361: }
3362: }
3363: return true;
3364: }
3365:
3366: /**
3367: * Get the value of a column in the current row as a Java byte.
3368: *
3369: * @param columnIndex
3370: * the first column is 1, the second is 2,...
3371: *
3372: * @return the column value; 0 if SQL NULL
3373: *
3374: * @exception SQLException
3375: * if a database access error occurs
3376: */
3377: protected byte getNativeByte(int columnIndex) throws SQLException {
3378: return getNativeByte(columnIndex, true);
3379: }
3380:
3381: protected byte getNativeByte(int columnIndex, boolean overflowCheck)
3382: throws SQLException {
3383: checkRowPos();
3384:
3385: checkColumnBounds(columnIndex);
3386:
3387: Object value = this .this Row.getColumnValue(columnIndex - 1);
3388:
3389: if (value == null) {
3390: this .wasNullFlag = true;
3391:
3392: return 0;
3393: }
3394:
3395: if (value == null) {
3396: this .wasNullFlag = true;
3397: } else {
3398: this .wasNullFlag = false;
3399: }
3400:
3401: if (this .wasNullFlag) {
3402: return 0;
3403: }
3404:
3405: columnIndex--;
3406:
3407: Field field = this .fields[columnIndex];
3408:
3409: switch (field.getMysqlType()) {
3410: case MysqlDefs.FIELD_TYPE_BIT:
3411: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
3412:
3413: if (overflowCheck
3414: && this .connection
3415: .getJdbcCompliantTruncationForReads()
3416: && (valueAsLong < Byte.MIN_VALUE || valueAsLong > Byte.MAX_VALUE)) {
3417: throwRangeException(String.valueOf(valueAsLong),
3418: columnIndex + 1, Types.TINYINT);
3419: }
3420:
3421: return (byte) valueAsLong;
3422: case MysqlDefs.FIELD_TYPE_TINY:
3423: byte valueAsByte = ((byte[]) value)[0];
3424:
3425: if (!field.isUnsigned()) {
3426: return valueAsByte;
3427: }
3428:
3429: short valueAsShort = (valueAsByte >= 0) ? valueAsByte
3430: : (short) (valueAsByte + (short) 256);
3431:
3432: if (overflowCheck
3433: && this .connection
3434: .getJdbcCompliantTruncationForReads()) {
3435: if (valueAsShort > Byte.MAX_VALUE) {
3436: throwRangeException(String.valueOf(valueAsShort),
3437: columnIndex + 1, Types.TINYINT);
3438: }
3439: }
3440:
3441: return (byte) valueAsShort;
3442:
3443: case MysqlDefs.FIELD_TYPE_SHORT:
3444: case MysqlDefs.FIELD_TYPE_YEAR:
3445: valueAsShort = getNativeShort(columnIndex + 1);
3446:
3447: if (overflowCheck
3448: && this .connection
3449: .getJdbcCompliantTruncationForReads()) {
3450: if (valueAsShort < Byte.MIN_VALUE
3451: || valueAsShort > Byte.MAX_VALUE) {
3452: throwRangeException(String.valueOf(valueAsShort),
3453: columnIndex + 1, Types.TINYINT);
3454: }
3455: }
3456:
3457: return (byte) valueAsShort;
3458: case MysqlDefs.FIELD_TYPE_INT24:
3459: case MysqlDefs.FIELD_TYPE_LONG:
3460: int valueAsInt = getNativeInt(columnIndex + 1, false);
3461:
3462: if (overflowCheck
3463: && this .connection
3464: .getJdbcCompliantTruncationForReads()) {
3465: if (valueAsInt < Byte.MIN_VALUE
3466: || valueAsInt > Byte.MAX_VALUE) {
3467: throwRangeException(String.valueOf(valueAsInt),
3468: columnIndex + 1, Types.TINYINT);
3469: }
3470: }
3471:
3472: return (byte) valueAsInt;
3473:
3474: case MysqlDefs.FIELD_TYPE_FLOAT:
3475: float valueAsFloat = getNativeFloat(columnIndex + 1);
3476:
3477: if (overflowCheck
3478: && this .connection
3479: .getJdbcCompliantTruncationForReads()) {
3480: if (valueAsFloat < Byte.MIN_VALUE
3481: || valueAsFloat > Byte.MAX_VALUE) {
3482:
3483: throwRangeException(String.valueOf(valueAsFloat),
3484: columnIndex + 1, Types.TINYINT);
3485: }
3486: }
3487:
3488: return (byte) valueAsFloat;
3489:
3490: case MysqlDefs.FIELD_TYPE_DOUBLE:
3491: double valueAsDouble = getNativeDouble(columnIndex + 1);
3492:
3493: if (overflowCheck
3494: && this .connection
3495: .getJdbcCompliantTruncationForReads()) {
3496: if (valueAsDouble < Byte.MIN_VALUE
3497: || valueAsDouble > Byte.MAX_VALUE) {
3498: throwRangeException(String.valueOf(valueAsDouble),
3499: columnIndex + 1, Types.TINYINT);
3500: }
3501: }
3502:
3503: return (byte) valueAsDouble;
3504:
3505: case MysqlDefs.FIELD_TYPE_LONGLONG:
3506: valueAsLong = getNativeLong(columnIndex + 1, false, true);
3507:
3508: if (overflowCheck
3509: && this .connection
3510: .getJdbcCompliantTruncationForReads()) {
3511: if (valueAsLong < Byte.MIN_VALUE
3512: || valueAsLong > Byte.MAX_VALUE) {
3513: throwRangeException(String.valueOf(valueAsLong),
3514: columnIndex + 1, Types.TINYINT);
3515: }
3516: }
3517:
3518: return (byte) valueAsLong;
3519:
3520: default:
3521: if (this .useUsageAdvisor) {
3522: issueConversionViaParsingWarning("getByte()",
3523: columnIndex, this .this Row
3524: .getColumnValue(columnIndex - 1),
3525: this .fields[columnIndex], new int[] {
3526: MysqlDefs.FIELD_TYPE_DOUBLE,
3527: MysqlDefs.FIELD_TYPE_TINY,
3528: MysqlDefs.FIELD_TYPE_SHORT,
3529: MysqlDefs.FIELD_TYPE_LONG,
3530: MysqlDefs.FIELD_TYPE_LONGLONG,
3531: MysqlDefs.FIELD_TYPE_FLOAT });
3532: }
3533:
3534: return getByteFromString(getNativeString(columnIndex + 1),
3535: columnIndex + 1);
3536: }
3537: }
3538:
3539: /**
3540: * Get the value of a column in the current row as a Java byte array.
3541: *
3542: * <p>
3543: * <b>Be warned</b> If the blob is huge, then you may run out of memory.
3544: * </p>
3545: *
3546: * @param columnIndex
3547: * the first column is 1, the second is 2, ...
3548: *
3549: * @return the column value; if the value is SQL NULL, the result is null
3550: *
3551: * @exception SQLException
3552: * if a database access error occurs
3553: */
3554: protected byte[] getNativeBytes(int columnIndex,
3555: boolean noConversion) throws SQLException {
3556: checkRowPos();
3557:
3558: checkColumnBounds(columnIndex);
3559:
3560: Object value = this .this Row.getColumnValue(columnIndex - 1);
3561:
3562: if (value == null) {
3563: this .wasNullFlag = true;
3564: } else {
3565: this .wasNullFlag = false;
3566: }
3567:
3568: if (this .wasNullFlag) {
3569: return null;
3570: }
3571:
3572: Field field = this .fields[columnIndex - 1];
3573:
3574: int mysqlType = field.getMysqlType();
3575:
3576: // Workaround for emulated locators in servers > 4.1,
3577: // as server returns SUBSTRING(blob) as STRING type...
3578: if (noConversion) {
3579: mysqlType = MysqlDefs.FIELD_TYPE_BLOB;
3580: }
3581:
3582: switch (mysqlType) {
3583: case MysqlDefs.FIELD_TYPE_TINY_BLOB:
3584: case MysqlDefs.FIELD_TYPE_MEDIUM_BLOB:
3585: case MysqlDefs.FIELD_TYPE_LONG_BLOB:
3586: case MysqlDefs.FIELD_TYPE_BLOB:
3587: case MysqlDefs.FIELD_TYPE_BIT:
3588: return (byte[]) value;
3589:
3590: default:
3591: int sqlType = field.getSQLType();
3592:
3593: if (sqlType == Types.VARBINARY || sqlType == Types.BINARY) {
3594: return (byte[]) value;
3595: }
3596:
3597: return getBytesFromString(getNativeString(columnIndex),
3598: columnIndex);
3599: }
3600: }
3601:
3602: /**
3603: * JDBC 2.0
3604: *
3605: * <p>
3606: * Get the value of a column in the current row as a java.io.Reader.
3607: * </p>
3608: *
3609: * @param columnIndex
3610: * the column to get the value from
3611: *
3612: * @return the value in the column as a java.io.Reader.
3613: *
3614: * @throws SQLException
3615: * if an error occurs
3616: */
3617: protected java.io.Reader getNativeCharacterStream(int columnIndex)
3618: throws SQLException {
3619: int columnIndexMinusOne = columnIndex - 1;
3620:
3621: switch (this .fields[columnIndexMinusOne].getSQLType()) {
3622: case Types.CHAR:
3623: case Types.VARCHAR:
3624: case Types.LONGVARCHAR:
3625: case Types.CLOB:
3626: if (this .this Row.isNull(columnIndexMinusOne)) {
3627: this .wasNullFlag = true;
3628:
3629: return null;
3630: }
3631:
3632: this .wasNullFlag = false;
3633:
3634: return this .this Row.getReader(columnIndexMinusOne);
3635: }
3636:
3637: String asString = null;
3638:
3639: asString = getStringForClob(columnIndex);
3640:
3641: if (asString == null) {
3642: return null;
3643: }
3644:
3645: return getCharacterStreamFromString(asString, columnIndex);
3646: }
3647:
3648: /**
3649: * JDBC 2.0 Get a CLOB column.
3650: *
3651: * @param columnIndex
3652: * the first column is 1, the second is 2, ...
3653: *
3654: * @return an object representing a CLOB
3655: *
3656: * @throws SQLException
3657: * if an error occurs
3658: */
3659: protected java.sql.Clob getNativeClob(int columnIndex)
3660: throws SQLException {
3661: String stringVal = getStringForClob(columnIndex);
3662:
3663: if (stringVal == null) {
3664: return null;
3665: }
3666:
3667: return getClobFromString(stringVal, columnIndex);
3668: }
3669:
3670: private String getNativeConvertToString(int columnIndex, Field field)
3671: throws SQLException {
3672:
3673: int sqlType = field.getSQLType();
3674: int mysqlType = field.getMysqlType();
3675:
3676: switch (sqlType) {
3677: case Types.BIT:
3678: return String
3679: .valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
3680: case Types.BOOLEAN:
3681: boolean booleanVal = getBoolean(columnIndex);
3682:
3683: if (this .wasNullFlag) {
3684: return null;
3685: }
3686:
3687: return String.valueOf(booleanVal);
3688:
3689: case Types.TINYINT:
3690: byte tinyintVal = getNativeByte(columnIndex, false);
3691:
3692: if (this .wasNullFlag) {
3693: return null;
3694: }
3695:
3696: if (!field.isUnsigned() || tinyintVal >= 0) {
3697: return String.valueOf(tinyintVal);
3698: }
3699:
3700: short unsignedTinyVal = (short) (tinyintVal & 0xff);
3701:
3702: return String.valueOf(unsignedTinyVal);
3703:
3704: case Types.SMALLINT:
3705:
3706: int intVal = getNativeInt(columnIndex, false);
3707:
3708: if (this .wasNullFlag) {
3709: return null;
3710: }
3711:
3712: if (!field.isUnsigned() || intVal >= 0) {
3713: return String.valueOf(intVal);
3714: }
3715:
3716: intVal = intVal & 0xffff;
3717:
3718: return String.valueOf(intVal);
3719:
3720: case Types.INTEGER:
3721: intVal = getNativeInt(columnIndex, false);
3722:
3723: if (this .wasNullFlag) {
3724: return null;
3725: }
3726:
3727: if (!field.isUnsigned()
3728: || intVal >= 0
3729: || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
3730:
3731: return String.valueOf(intVal);
3732: }
3733:
3734: long longVal = intVal & 0xffffffffL;
3735:
3736: return String.valueOf(longVal);
3737:
3738: case Types.BIGINT:
3739:
3740: if (!field.isUnsigned()) {
3741: longVal = getNativeLong(columnIndex, false, true);
3742:
3743: if (this .wasNullFlag) {
3744: return null;
3745: }
3746:
3747: return String.valueOf(longVal);
3748: }
3749:
3750: longVal = getNativeLong(columnIndex, false, false);
3751:
3752: if (this .wasNullFlag) {
3753: return null;
3754: }
3755:
3756: return String.valueOf(convertLongToUlong(longVal));
3757: case Types.REAL:
3758: float floatVal = getNativeFloat(columnIndex);
3759:
3760: if (this .wasNullFlag) {
3761: return null;
3762: }
3763:
3764: return String.valueOf(floatVal);
3765:
3766: case Types.FLOAT:
3767: case Types.DOUBLE:
3768: double doubleVal = getNativeDouble(columnIndex);
3769:
3770: if (this .wasNullFlag) {
3771: return null;
3772: }
3773:
3774: return String.valueOf(doubleVal);
3775:
3776: case Types.DECIMAL:
3777: case Types.NUMERIC:
3778: String stringVal = StringUtils
3779: .toAsciiString((byte[]) this .this Row
3780: .getColumnValue(columnIndex - 1));
3781:
3782: BigDecimal val;
3783:
3784: if (stringVal != null) {
3785: this .wasNullFlag = false;
3786:
3787: if (stringVal.length() == 0) {
3788: val = new BigDecimal(0);
3789:
3790: return val.toString();
3791: }
3792:
3793: try {
3794: val = new BigDecimal(stringVal);
3795: } catch (NumberFormatException ex) {
3796: throw SQLError
3797: .createSQLException(
3798: Messages
3799: .getString(
3800: "ResultSet.Bad_format_for_BigDecimal",
3801: new Object[] {
3802: stringVal,
3803: Constants
3804: .integerValueOf(columnIndex) }),
3805: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
3806: }
3807:
3808: return val.toString();
3809: }
3810:
3811: this .wasNullFlag = true;
3812:
3813: return null;
3814:
3815: case Types.CHAR:
3816: case Types.VARCHAR:
3817: case Types.LONGVARCHAR:
3818:
3819: return extractStringFromNativeColumn(columnIndex, mysqlType);
3820: case Types.BINARY:
3821: case Types.VARBINARY:
3822: case Types.LONGVARBINARY:
3823:
3824: if (!field.isBlob()) {
3825: return extractStringFromNativeColumn(columnIndex,
3826: mysqlType);
3827: } else if (!field.isBinary()) {
3828: return extractStringFromNativeColumn(columnIndex,
3829: mysqlType);
3830: } else {
3831: byte[] data = getBytes(columnIndex);
3832: Object obj = data;
3833:
3834: if ((data != null) && (data.length >= 2)) {
3835: if ((data[0] == -84) && (data[1] == -19)) {
3836: // Serialized object?
3837: try {
3838: ByteArrayInputStream bytesIn = new ByteArrayInputStream(
3839: data);
3840: ObjectInputStream objIn = new ObjectInputStream(
3841: bytesIn);
3842: obj = objIn.readObject();
3843: objIn.close();
3844: bytesIn.close();
3845: } catch (ClassNotFoundException cnfe) {
3846: throw SQLError
3847: .createSQLException(Messages
3848: .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
3849: + cnfe.toString()
3850: + Messages
3851: .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
3852: } catch (IOException ex) {
3853: obj = data; // not serialized?
3854: }
3855: }
3856:
3857: return obj.toString();
3858: }
3859:
3860: return extractStringFromNativeColumn(columnIndex,
3861: mysqlType);
3862: }
3863:
3864: case Types.DATE:
3865:
3866: // The YEAR datatype needs to be handled differently here.
3867: if (mysqlType == MysqlDefs.FIELD_TYPE_YEAR) {
3868: short shortVal = getNativeShort(columnIndex);
3869:
3870: if (!this .connection.getYearIsDateType()) {
3871:
3872: if (this .wasNullFlag) {
3873: return null;
3874: }
3875:
3876: return String.valueOf(shortVal);
3877: }
3878:
3879: if (field.getLength() == 2) {
3880:
3881: if (shortVal <= 69) {
3882: shortVal = (short) (shortVal + 100);
3883: }
3884:
3885: shortVal += 1900;
3886: }
3887:
3888: return fastDateCreate(null, shortVal, 1, 1).toString();
3889:
3890: }
3891:
3892: Date dt = getNativeDate(columnIndex);
3893:
3894: if (dt == null) {
3895: return null;
3896: }
3897:
3898: return String.valueOf(dt);
3899:
3900: case Types.TIME:
3901: Time tm = getNativeTime(columnIndex, null,
3902: this .defaultTimeZone, false);
3903:
3904: if (tm == null) {
3905: return null;
3906: }
3907:
3908: return String.valueOf(tm);
3909:
3910: case Types.TIMESTAMP:
3911: Timestamp tstamp = getNativeTimestamp(columnIndex, null,
3912: this .defaultTimeZone, false);
3913:
3914: if (tstamp == null) {
3915: return null;
3916: }
3917:
3918: String result = String.valueOf(tstamp);
3919:
3920: if (!this .connection.getNoDatetimeStringSync()) {
3921: return result;
3922: }
3923:
3924: if (result.endsWith(".0")) {
3925: return result.substring(0, result.length() - 2);
3926: }
3927:
3928: default:
3929: return extractStringFromNativeColumn(columnIndex, mysqlType);
3930: }
3931: }
3932:
3933: /**
3934: * Get the value of a column in the current row as a java.sql.Date object
3935: *
3936: * @param columnIndex
3937: * the first column is 1, the second is 2...
3938: *
3939: * @return the column value; null if SQL NULL
3940: *
3941: * @exception SQLException
3942: * if a database access error occurs
3943: */
3944: protected java.sql.Date getNativeDate(int columnIndex)
3945: throws SQLException {
3946: return getNativeDate(columnIndex, null);
3947: }
3948:
3949: /**
3950: * JDBC 2.0 Get the value of a column in the current row as a java.sql.Date
3951: * object. Use the calendar to construct an appropriate millisecond value
3952: * for the Date, if the underlying database doesn't store timezone
3953: * information.
3954: *
3955: * @param columnIndex
3956: * the first column is 1, the second is 2, ...
3957: * @param tz
3958: * the calendar to use in constructing the date
3959: *
3960: * @return the column value; if the value is SQL NULL, the result is null
3961: *
3962: * @exception SQLException
3963: * if a database-access error occurs.
3964: */
3965: protected java.sql.Date getNativeDate(int columnIndex, TimeZone tz)
3966: throws SQLException {
3967: checkRowPos();
3968: checkColumnBounds(columnIndex);
3969:
3970: int columnIndexMinusOne = columnIndex - 1;
3971:
3972: int mysqlType = this .fields[columnIndexMinusOne].getMysqlType();
3973:
3974: java.sql.Date dateToReturn = null;
3975:
3976: if (mysqlType == MysqlDefs.FIELD_TYPE_DATE) {
3977:
3978: dateToReturn = this .this Row.getNativeDate(
3979: columnIndexMinusOne, this .connection, this );
3980: } else {
3981:
3982: boolean rollForward = (tz != null && !tz.equals(this
3983: .getDefaultTimeZone()));
3984:
3985: dateToReturn = (Date) this .this Row.getNativeDateTimeValue(
3986: columnIndexMinusOne, null, Types.DATE, mysqlType,
3987: tz, rollForward, this .connection, this );
3988: }
3989:
3990: //
3991: // normally, we allow ResultSetImpl methods to check for null first,
3992: // but with DATETIME values we have this wacky need to support
3993: // 0000-00-00 00:00:00 -> NULL, so we have to defer
3994: // to the RowHolder implementation, and check the return value.
3995: //
3996:
3997: if (dateToReturn == null) {
3998:
3999: this .wasNullFlag = true;
4000:
4001: return null;
4002: }
4003:
4004: this .wasNullFlag = false;
4005:
4006: return dateToReturn;
4007: }
4008:
4009: java.sql.Date getNativeDateViaParseConversion(int columnIndex)
4010: throws SQLException {
4011: if (this .useUsageAdvisor) {
4012: issueConversionViaParsingWarning("getDate()", columnIndex,
4013: this .this Row.getColumnValue(columnIndex - 1),
4014: this .fields[columnIndex - 1],
4015: new int[] { MysqlDefs.FIELD_TYPE_DATE });
4016: }
4017:
4018: String stringVal = getNativeString(columnIndex);
4019:
4020: return getDateFromString(stringVal, columnIndex);
4021: }
4022:
4023: /**
4024: * Get the value of a column in the current row as a Java double.
4025: *
4026: * @param columnIndex
4027: * the first column is 1, the second is 2,...
4028: *
4029: * @return the column value; 0 if SQL NULL
4030: *
4031: * @exception SQLException
4032: * if a database access error occurs
4033: */
4034: protected double getNativeDouble(int columnIndex)
4035: throws SQLException {
4036: checkRowPos();
4037: checkColumnBounds(columnIndex);
4038:
4039: columnIndex--; // / JDBC is 1-based
4040:
4041: if (this .this Row.isNull(columnIndex)) {
4042: this .wasNullFlag = true;
4043:
4044: return 0;
4045: }
4046:
4047: this .wasNullFlag = false;
4048:
4049: Field f = this .fields[columnIndex];
4050:
4051: switch (f.getMysqlType()) {
4052: case MysqlDefs.FIELD_TYPE_DOUBLE:
4053: return this .this Row.getNativeDouble(columnIndex);
4054: case MysqlDefs.FIELD_TYPE_TINY:
4055: if (!f.isUnsigned()) {
4056: return (double) getNativeByte(columnIndex + 1);
4057: }
4058:
4059: return (double) getNativeShort(columnIndex + 1);
4060: case MysqlDefs.FIELD_TYPE_SHORT:
4061: case MysqlDefs.FIELD_TYPE_YEAR:
4062: if (!f.isUnsigned()) {
4063: return (double) getNativeShort(columnIndex + 1);
4064: }
4065:
4066: return (double) getNativeInt(columnIndex + 1);
4067: case MysqlDefs.FIELD_TYPE_INT24:
4068: case MysqlDefs.FIELD_TYPE_LONG:
4069: if (!f.isUnsigned()) {
4070: return (double) getNativeInt(columnIndex + 1);
4071: }
4072:
4073: return (double) getNativeLong(columnIndex + 1);
4074: case MysqlDefs.FIELD_TYPE_LONGLONG:
4075: long valueAsLong = getNativeLong(columnIndex + 1);
4076:
4077: if (!f.isUnsigned()) {
4078: return (double) valueAsLong;
4079: }
4080:
4081: BigInteger asBigInt = convertLongToUlong(valueAsLong);
4082:
4083: // TODO: Check for overflow
4084:
4085: return asBigInt.doubleValue();
4086: case MysqlDefs.FIELD_TYPE_FLOAT:
4087: return (double) getNativeFloat(columnIndex + 1);
4088: case MysqlDefs.FIELD_TYPE_BIT:
4089: return getNumericRepresentationOfSQLBitType(columnIndex + 1);
4090: default:
4091: String stringVal = getNativeString(columnIndex + 1);
4092:
4093: if (this .useUsageAdvisor) {
4094: issueConversionViaParsingWarning("getDouble()",
4095: columnIndex, stringVal,
4096: this .fields[columnIndex], new int[] {
4097: MysqlDefs.FIELD_TYPE_DOUBLE,
4098: MysqlDefs.FIELD_TYPE_TINY,
4099: MysqlDefs.FIELD_TYPE_SHORT,
4100: MysqlDefs.FIELD_TYPE_LONG,
4101: MysqlDefs.FIELD_TYPE_LONGLONG,
4102: MysqlDefs.FIELD_TYPE_FLOAT });
4103: }
4104:
4105: return getDoubleFromString(stringVal, columnIndex + 1);
4106: }
4107: }
4108:
4109: /**
4110: * Get the value of a column in the current row as a Java float.
4111: *
4112: * @param columnIndex
4113: * the first column is 1, the second is 2,...
4114: *
4115: * @return the column value; 0 if SQL NULL
4116: *
4117: * @exception SQLException
4118: * if a database access error occurs
4119: */
4120: protected float getNativeFloat(int columnIndex) throws SQLException {
4121: checkRowPos();
4122: checkColumnBounds(columnIndex);
4123:
4124: columnIndex--; // / JDBC is 1-based
4125:
4126: if (this .this Row.isNull(columnIndex)) {
4127: this .wasNullFlag = true;
4128:
4129: return 0;
4130: }
4131:
4132: this .wasNullFlag = false;
4133:
4134: Field f = this .fields[columnIndex];
4135:
4136: switch (f.getMysqlType()) {
4137: case MysqlDefs.FIELD_TYPE_BIT:
4138: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
4139:
4140: return valueAsLong;
4141: case MysqlDefs.FIELD_TYPE_DOUBLE:
4142:
4143: // Only foolproof way to check for overflow
4144: // Not efficient, but if you don't want to be inefficient, use the
4145: // correct binding for the type!
4146:
4147: Double valueAsDouble = new Double(
4148: getNativeDouble(columnIndex + 1));
4149:
4150: float valueAsFloat = valueAsDouble.floatValue();
4151:
4152: if (this .connection.getJdbcCompliantTruncationForReads()
4153: && valueAsFloat == Float.NEGATIVE_INFINITY
4154: || valueAsFloat == Float.POSITIVE_INFINITY) {
4155: throwRangeException(valueAsDouble.toString(),
4156: columnIndex + 1, Types.FLOAT);
4157: }
4158:
4159: return (float) getNativeDouble(columnIndex + 1);
4160: case MysqlDefs.FIELD_TYPE_TINY:
4161: if (!f.isUnsigned()) {
4162: return (float) getNativeByte(columnIndex + 1);
4163: }
4164:
4165: return (float) getNativeShort(columnIndex + 1);
4166: case MysqlDefs.FIELD_TYPE_SHORT:
4167: case MysqlDefs.FIELD_TYPE_YEAR:
4168: if (!f.isUnsigned()) {
4169: return (float) getNativeShort(columnIndex + 1);
4170: }
4171:
4172: return (float) getNativeInt(columnIndex + 1);
4173: case MysqlDefs.FIELD_TYPE_INT24:
4174: case MysqlDefs.FIELD_TYPE_LONG:
4175: if (!f.isUnsigned()) {
4176: return (float) getNativeInt(columnIndex + 1);
4177: }
4178:
4179: return (float) getNativeLong(columnIndex + 1);
4180: case MysqlDefs.FIELD_TYPE_LONGLONG:
4181: valueAsLong = getNativeLong(columnIndex + 1);
4182:
4183: if (!f.isUnsigned()) {
4184: return (float) valueAsLong;
4185: }
4186:
4187: BigInteger asBigInt = convertLongToUlong(valueAsLong);
4188:
4189: // TODO: Check for overflow
4190:
4191: return asBigInt.floatValue();
4192: case MysqlDefs.FIELD_TYPE_FLOAT:
4193:
4194: return this .this Row.getNativeFloat(columnIndex);
4195:
4196: default:
4197: String stringVal = getNativeString(columnIndex + 1);
4198:
4199: if (this .useUsageAdvisor) {
4200: issueConversionViaParsingWarning("getFloat()",
4201: columnIndex, stringVal,
4202: this .fields[columnIndex], new int[] {
4203: MysqlDefs.FIELD_TYPE_DOUBLE,
4204: MysqlDefs.FIELD_TYPE_TINY,
4205: MysqlDefs.FIELD_TYPE_SHORT,
4206: MysqlDefs.FIELD_TYPE_LONG,
4207: MysqlDefs.FIELD_TYPE_LONGLONG,
4208: MysqlDefs.FIELD_TYPE_FLOAT });
4209: }
4210:
4211: return getFloatFromString(stringVal, columnIndex + 1);
4212: }
4213: }
4214:
4215: /**
4216: * Get the value of a column in the current row as a Java int.
4217: *
4218: * @param columnIndex
4219: * the first column is 1, the second is 2,...
4220: *
4221: * @return the column value; 0 if SQL NULL
4222: *
4223: * @exception SQLException
4224: * if a database access error occurs
4225: */
4226: protected int getNativeInt(int columnIndex) throws SQLException {
4227: return getNativeInt(columnIndex, true);
4228: }
4229:
4230: protected int getNativeInt(int columnIndex, boolean overflowCheck)
4231: throws SQLException {
4232: checkRowPos();
4233: checkColumnBounds(columnIndex);
4234:
4235: columnIndex--; // / JDBC is 1-based
4236:
4237: if (this .this Row.isNull(columnIndex)) {
4238: this .wasNullFlag = true;
4239:
4240: return 0;
4241: }
4242:
4243: this .wasNullFlag = false;
4244:
4245: Field f = this .fields[columnIndex];
4246:
4247: switch (f.getMysqlType()) {
4248: case MysqlDefs.FIELD_TYPE_BIT:
4249: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex + 1);
4250:
4251: if (overflowCheck
4252: && this .connection
4253: .getJdbcCompliantTruncationForReads()
4254: && (valueAsLong < Integer.MIN_VALUE || valueAsLong > Integer.MAX_VALUE)) {
4255: throwRangeException(String.valueOf(valueAsLong),
4256: columnIndex + 1, Types.INTEGER);
4257: }
4258:
4259: return (short) valueAsLong;
4260: case MysqlDefs.FIELD_TYPE_TINY:
4261: byte tinyintVal = getNativeByte(columnIndex + 1, false);
4262:
4263: if (!f.isUnsigned() || tinyintVal >= 0) {
4264: return tinyintVal;
4265: }
4266:
4267: return tinyintVal + 256;
4268: case MysqlDefs.FIELD_TYPE_SHORT:
4269: case MysqlDefs.FIELD_TYPE_YEAR:
4270: short asShort = getNativeShort(columnIndex + 1, false);
4271:
4272: if (!f.isUnsigned() || asShort >= 0) {
4273: return asShort;
4274: }
4275:
4276: return asShort + 65536;
4277: case MysqlDefs.FIELD_TYPE_INT24:
4278: case MysqlDefs.FIELD_TYPE_LONG:
4279:
4280: int valueAsInt = this .this Row.getNativeInt(columnIndex);
4281:
4282: if (!f.isUnsigned()) {
4283: return valueAsInt;
4284: }
4285:
4286: valueAsLong = (valueAsInt >= 0) ? valueAsInt
4287: : valueAsInt + 4294967296L;
4288:
4289: if (overflowCheck
4290: && this .connection
4291: .getJdbcCompliantTruncationForReads()
4292: && valueAsLong > Integer.MAX_VALUE) {
4293: throwRangeException(String.valueOf(valueAsLong),
4294: columnIndex + 1, Types.INTEGER);
4295: }
4296:
4297: return (int) valueAsLong;
4298: case MysqlDefs.FIELD_TYPE_LONGLONG:
4299: valueAsLong = getNativeLong(columnIndex + 1, false, true);
4300:
4301: if (overflowCheck
4302: && this .connection
4303: .getJdbcCompliantTruncationForReads()) {
4304: if (valueAsLong < Integer.MIN_VALUE
4305: || valueAsLong > Integer.MAX_VALUE) {
4306: throwRangeException(String.valueOf(valueAsLong),
4307: columnIndex + 1, Types.INTEGER);
4308: }
4309: }
4310:
4311: return (int) valueAsLong;
4312: case MysqlDefs.FIELD_TYPE_DOUBLE:
4313: double valueAsDouble = getNativeDouble(columnIndex + 1);
4314:
4315: if (overflowCheck
4316: && this .connection
4317: .getJdbcCompliantTruncationForReads()) {
4318: if (valueAsDouble < Integer.MIN_VALUE
4319: || valueAsDouble > Integer.MAX_VALUE) {
4320: throwRangeException(String.valueOf(valueAsDouble),
4321: columnIndex + 1, Types.INTEGER);
4322: }
4323: }
4324:
4325: return (int) valueAsDouble;
4326: case MysqlDefs.FIELD_TYPE_FLOAT:
4327: valueAsDouble = getNativeFloat(columnIndex + 1);
4328:
4329: if (overflowCheck
4330: && this .connection
4331: .getJdbcCompliantTruncationForReads()) {
4332: if (valueAsDouble < Integer.MIN_VALUE
4333: || valueAsDouble > Integer.MAX_VALUE) {
4334: throwRangeException(String.valueOf(valueAsDouble),
4335: columnIndex + 1, Types.INTEGER);
4336: }
4337: }
4338:
4339: return (int) valueAsDouble;
4340:
4341: default:
4342: String stringVal = getNativeString(columnIndex + 1);
4343:
4344: if (this .useUsageAdvisor) {
4345: issueConversionViaParsingWarning("getInt()",
4346: columnIndex, stringVal,
4347: this .fields[columnIndex], new int[] {
4348: MysqlDefs.FIELD_TYPE_DOUBLE,
4349: MysqlDefs.FIELD_TYPE_TINY,
4350: MysqlDefs.FIELD_TYPE_SHORT,
4351: MysqlDefs.FIELD_TYPE_LONG,
4352: MysqlDefs.FIELD_TYPE_LONGLONG,
4353: MysqlDefs.FIELD_TYPE_FLOAT });
4354: }
4355:
4356: return getIntFromString(stringVal, columnIndex + 1);
4357: }
4358: }
4359:
4360: /**
4361: * Get the value of a column in the current row as a Java long.
4362: *
4363: * @param columnIndex
4364: * the first column is 1, the second is 2,...
4365: *
4366: * @return the column value; 0 if SQL NULL
4367: *
4368: * @exception SQLException
4369: * if a database access error occurs
4370: */
4371: protected long getNativeLong(int columnIndex) throws SQLException {
4372: return getNativeLong(columnIndex, true, true);
4373: }
4374:
4375: protected long getNativeLong(int columnIndex,
4376: boolean overflowCheck, boolean expandUnsignedLong)
4377: throws SQLException {
4378: checkRowPos();
4379: checkColumnBounds(columnIndex);
4380:
4381: columnIndex--; // / JDBC is 1-based
4382:
4383: if (this .this Row.isNull(columnIndex)) {
4384: this .wasNullFlag = true;
4385:
4386: return 0;
4387: }
4388:
4389: this .wasNullFlag = false;
4390:
4391: Field f = this .fields[columnIndex];
4392:
4393: switch (f.getMysqlType()) {
4394: case MysqlDefs.FIELD_TYPE_BIT:
4395: return getNumericRepresentationOfSQLBitType(columnIndex + 1);
4396: case MysqlDefs.FIELD_TYPE_TINY:
4397: if (!f.isUnsigned()) {
4398: return getNativeByte(columnIndex + 1);
4399: }
4400:
4401: return getNativeInt(columnIndex + 1);
4402: case MysqlDefs.FIELD_TYPE_SHORT:
4403: if (!f.isUnsigned()) {
4404: return getNativeShort(columnIndex + 1);
4405: }
4406:
4407: return getNativeInt(columnIndex + 1, false);
4408: case MysqlDefs.FIELD_TYPE_YEAR:
4409:
4410: return getNativeShort(columnIndex + 1);
4411: case MysqlDefs.FIELD_TYPE_INT24:
4412: case MysqlDefs.FIELD_TYPE_LONG:
4413: int asInt = getNativeInt(columnIndex + 1, false);
4414:
4415: if (!f.isUnsigned() || asInt >= 0) {
4416: return asInt;
4417: }
4418:
4419: return asInt + 4294967296L;
4420: case MysqlDefs.FIELD_TYPE_LONGLONG:
4421: long valueAsLong = this .this Row.getNativeLong(columnIndex);
4422:
4423: if (!f.isUnsigned() || !expandUnsignedLong) {
4424: return valueAsLong;
4425: }
4426:
4427: BigInteger asBigInt = convertLongToUlong(valueAsLong);
4428:
4429: if (overflowCheck
4430: && this .connection
4431: .getJdbcCompliantTruncationForReads()
4432: && ((asBigInt.compareTo(new BigInteger(String
4433: .valueOf(Long.MAX_VALUE))) > 0) || (asBigInt
4434: .compareTo(new BigInteger(String
4435: .valueOf(Long.MIN_VALUE))) < 0))) {
4436: throwRangeException(asBigInt.toString(),
4437: columnIndex + 1, Types.BIGINT);
4438: }
4439:
4440: return getLongFromString(asBigInt.toString(),
4441: columnIndex + 1);
4442:
4443: case MysqlDefs.FIELD_TYPE_DOUBLE:
4444: double valueAsDouble = getNativeDouble(columnIndex + 1);
4445:
4446: if (overflowCheck
4447: && this .connection
4448: .getJdbcCompliantTruncationForReads()) {
4449: if (valueAsDouble < Long.MIN_VALUE
4450: || valueAsDouble > Long.MAX_VALUE) {
4451: throwRangeException(String.valueOf(valueAsDouble),
4452: columnIndex + 1, Types.BIGINT);
4453: }
4454: }
4455:
4456: return (long) valueAsDouble;
4457: case MysqlDefs.FIELD_TYPE_FLOAT:
4458: valueAsDouble = getNativeFloat(columnIndex + 1);
4459:
4460: if (overflowCheck
4461: && this .connection
4462: .getJdbcCompliantTruncationForReads()) {
4463: if (valueAsDouble < Long.MIN_VALUE
4464: || valueAsDouble > Long.MAX_VALUE) {
4465: throwRangeException(String.valueOf(valueAsDouble),
4466: columnIndex + 1, Types.BIGINT);
4467: }
4468: }
4469:
4470: return (long) valueAsDouble;
4471: default:
4472: String stringVal = getNativeString(columnIndex + 1);
4473:
4474: if (this .useUsageAdvisor) {
4475: issueConversionViaParsingWarning("getLong()",
4476: columnIndex, stringVal,
4477: this .fields[columnIndex], new int[] {
4478: MysqlDefs.FIELD_TYPE_DOUBLE,
4479: MysqlDefs.FIELD_TYPE_TINY,
4480: MysqlDefs.FIELD_TYPE_SHORT,
4481: MysqlDefs.FIELD_TYPE_LONG,
4482: MysqlDefs.FIELD_TYPE_LONGLONG,
4483: MysqlDefs.FIELD_TYPE_FLOAT });
4484: }
4485:
4486: return getLongFromString(stringVal, columnIndex + 1);
4487: }
4488: }
4489:
4490: /**
4491: * JDBC 2.0 Get a REF(<structured-type>) column.
4492: *
4493: * @param i
4494: * the first column is 1, the second is 2, ...
4495: *
4496: * @return an object representing data of an SQL REF type
4497: *
4498: * @throws SQLException
4499: * as this is not implemented
4500: * @throws NotImplemented
4501: * DOCUMENT ME!
4502: */
4503: protected java.sql.Ref getNativeRef(int i) throws SQLException {
4504: throw new NotImplemented();
4505: }
4506:
4507: /**
4508: * Get the value of a column in the current row as a Java short.
4509: *
4510: * @param columnIndex
4511: * the first column is 1, the second is 2,...
4512: *
4513: * @return the column value; 0 if SQL NULL
4514: *
4515: * @exception SQLException
4516: * if a database access error occurs
4517: */
4518: protected short getNativeShort(int columnIndex) throws SQLException {
4519: return getNativeShort(columnIndex, true);
4520: }
4521:
4522: protected short getNativeShort(int columnIndex,
4523: boolean overflowCheck) throws SQLException {
4524: checkRowPos();
4525: checkColumnBounds(columnIndex);
4526:
4527: columnIndex--; // / JDBC is 1-based
4528:
4529: if (this .this Row.isNull(columnIndex)) {
4530: this .wasNullFlag = true;
4531:
4532: return 0;
4533: }
4534:
4535: this .wasNullFlag = false;
4536:
4537: Field f = this .fields[columnIndex];
4538:
4539: switch (f.getMysqlType()) {
4540:
4541: case MysqlDefs.FIELD_TYPE_TINY:
4542: byte tinyintVal = getNativeByte(columnIndex + 1, false);
4543:
4544: if (!f.isUnsigned() || tinyintVal >= 0) {
4545: return tinyintVal;
4546: }
4547:
4548: return (short) (tinyintVal + (short) 256);
4549: case MysqlDefs.FIELD_TYPE_SHORT:
4550: case MysqlDefs.FIELD_TYPE_YEAR:
4551:
4552: short asShort = this .this Row.getNativeShort(columnIndex);
4553:
4554: if (!f.isUnsigned()) {
4555: return asShort;
4556: }
4557:
4558: int valueAsInt = asShort & 0xffff;
4559:
4560: if (overflowCheck
4561: && this .connection
4562: .getJdbcCompliantTruncationForReads()
4563: && valueAsInt > Short.MAX_VALUE) {
4564: throwRangeException(String.valueOf(valueAsInt),
4565: columnIndex + 1, Types.SMALLINT);
4566: }
4567:
4568: return (short) valueAsInt;
4569: case MysqlDefs.FIELD_TYPE_INT24:
4570: case MysqlDefs.FIELD_TYPE_LONG:
4571: if (!f.isUnsigned()) {
4572: valueAsInt = getNativeInt(columnIndex + 1, false);
4573:
4574: if (overflowCheck
4575: && this .connection
4576: .getJdbcCompliantTruncationForReads()
4577: && valueAsInt > Short.MAX_VALUE
4578: || valueAsInt < Short.MIN_VALUE) {
4579: throwRangeException(String.valueOf(valueAsInt),
4580: columnIndex + 1, Types.SMALLINT);
4581: }
4582:
4583: return (short) valueAsInt;
4584: }
4585:
4586: long valueAsLong = getNativeLong(columnIndex + 1, false,
4587: true);
4588:
4589: if (overflowCheck
4590: && this .connection
4591: .getJdbcCompliantTruncationForReads()
4592: && valueAsLong > Short.MAX_VALUE) {
4593: throwRangeException(String.valueOf(valueAsLong),
4594: columnIndex + 1, Types.SMALLINT);
4595: }
4596:
4597: return (short) valueAsLong;
4598:
4599: case MysqlDefs.FIELD_TYPE_LONGLONG:
4600: valueAsLong = getNativeLong(columnIndex + 1, false, false);
4601:
4602: if (!f.isUnsigned()) {
4603: if (overflowCheck
4604: && this .connection
4605: .getJdbcCompliantTruncationForReads()) {
4606: if (valueAsLong < Short.MIN_VALUE
4607: || valueAsLong > Short.MAX_VALUE) {
4608: throwRangeException(
4609: String.valueOf(valueAsLong),
4610: columnIndex + 1, Types.SMALLINT);
4611: }
4612: }
4613:
4614: return (short) valueAsLong;
4615: }
4616:
4617: BigInteger asBigInt = convertLongToUlong(valueAsLong);
4618:
4619: if (overflowCheck
4620: && this .connection
4621: .getJdbcCompliantTruncationForReads()
4622: && ((asBigInt.compareTo(new BigInteger(String
4623: .valueOf(Short.MAX_VALUE))) > 0) || (asBigInt
4624: .compareTo(new BigInteger(String
4625: .valueOf(Short.MIN_VALUE))) < 0))) {
4626: throwRangeException(asBigInt.toString(),
4627: columnIndex + 1, Types.SMALLINT);
4628: }
4629:
4630: return (short) getIntFromString(asBigInt.toString(),
4631: columnIndex + 1);
4632:
4633: case MysqlDefs.FIELD_TYPE_DOUBLE:
4634: double valueAsDouble = getNativeDouble(columnIndex + 1);
4635:
4636: if (overflowCheck
4637: && this .connection
4638: .getJdbcCompliantTruncationForReads()) {
4639: if (valueAsDouble < Short.MIN_VALUE
4640: || valueAsDouble > Short.MAX_VALUE) {
4641: throwRangeException(String.valueOf(valueAsDouble),
4642: columnIndex + 1, Types.SMALLINT);
4643: }
4644: }
4645:
4646: return (short) valueAsDouble;
4647: case MysqlDefs.FIELD_TYPE_FLOAT:
4648: float valueAsFloat = getNativeFloat(columnIndex + 1);
4649:
4650: if (overflowCheck
4651: && this .connection
4652: .getJdbcCompliantTruncationForReads()) {
4653: if (valueAsFloat < Short.MIN_VALUE
4654: || valueAsFloat > Short.MAX_VALUE) {
4655: throwRangeException(String.valueOf(valueAsFloat),
4656: columnIndex + 1, Types.SMALLINT);
4657: }
4658: }
4659:
4660: return (short) valueAsFloat;
4661: default:
4662: String stringVal = getNativeString(columnIndex + 1);
4663:
4664: if (this .useUsageAdvisor) {
4665: issueConversionViaParsingWarning("getShort()",
4666: columnIndex, stringVal,
4667: this .fields[columnIndex], new int[] {
4668: MysqlDefs.FIELD_TYPE_DOUBLE,
4669: MysqlDefs.FIELD_TYPE_TINY,
4670: MysqlDefs.FIELD_TYPE_SHORT,
4671: MysqlDefs.FIELD_TYPE_LONG,
4672: MysqlDefs.FIELD_TYPE_LONGLONG,
4673: MysqlDefs.FIELD_TYPE_FLOAT });
4674: }
4675:
4676: return getShortFromString(stringVal, columnIndex + 1);
4677: }
4678: }
4679:
4680: /**
4681: * Get the value of a column in the current row as a Java String
4682: *
4683: * @param columnIndex
4684: * the first column is 1, the second is 2...
4685: *
4686: * @return the column value, null for SQL NULL
4687: *
4688: * @exception SQLException
4689: * if a database access error occurs
4690: */
4691: protected String getNativeString(int columnIndex)
4692: throws SQLException {
4693: checkRowPos();
4694: checkColumnBounds(columnIndex);
4695:
4696: if (this .fields == null) {
4697: throw SQLError
4698: .createSQLException(
4699: Messages
4700: .getString("ResultSet.Query_generated_no_fields_for_ResultSet_133"), //$NON-NLS-1$
4701: SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
4702: }
4703:
4704: if (this .this Row.isNull(columnIndex - 1)) {
4705: this .wasNullFlag = true;
4706:
4707: return null;
4708: }
4709:
4710: this .wasNullFlag = false;
4711:
4712: String stringVal = null;
4713:
4714: Field field = this .fields[columnIndex - 1];
4715:
4716: // TODO: Check Types Here.
4717: stringVal = getNativeConvertToString(columnIndex, field);
4718:
4719: if (field.isZeroFill() && (stringVal != null)) {
4720: int origLength = stringVal.length();
4721:
4722: StringBuffer zeroFillBuf = new StringBuffer(origLength);
4723:
4724: long numZeros = field.getLength() - origLength;
4725:
4726: for (long i = 0; i < numZeros; i++) {
4727: zeroFillBuf.append('0');
4728: }
4729:
4730: zeroFillBuf.append(stringVal);
4731:
4732: stringVal = zeroFillBuf.toString();
4733: }
4734:
4735: return stringVal;
4736: }
4737:
4738: private Time getNativeTime(int columnIndex,
4739: Calendar targetCalendar, TimeZone tz, boolean rollForward)
4740: throws SQLException {
4741: checkRowPos();
4742: checkColumnBounds(columnIndex);
4743:
4744: int columnIndexMinusOne = columnIndex - 1;
4745:
4746: int mysqlType = this .fields[columnIndexMinusOne].getMysqlType();
4747:
4748: Time timeVal = null;
4749:
4750: if (mysqlType == MysqlDefs.FIELD_TYPE_TIME) {
4751: timeVal = this .this Row.getNativeTime(columnIndexMinusOne,
4752: targetCalendar, tz, rollForward, this .connection,
4753: this );
4754:
4755: } else {
4756: timeVal = (Time) this .this Row.getNativeDateTimeValue(
4757: columnIndexMinusOne, null, Types.TIME, mysqlType,
4758: tz, rollForward, this .connection, this );
4759: }
4760:
4761: //
4762: // normally, we allow ResultSetImpl methods to check for null first,
4763: // but with DATETIME values we have this wacky need to support
4764: // 0000-00-00 00:00:00 -> NULL, so we have to defer
4765: // to the RowHolder implementation, and check the return value.
4766: //
4767:
4768: if (timeVal == null) {
4769:
4770: this .wasNullFlag = true;
4771:
4772: return null;
4773: }
4774:
4775: this .wasNullFlag = false;
4776:
4777: return timeVal;
4778: }
4779:
4780: Time getNativeTimeViaParseConversion(int columnIndex,
4781: Calendar targetCalendar, TimeZone tz, boolean rollForward)
4782: throws SQLException {
4783: if (this .useUsageAdvisor) {
4784: issueConversionViaParsingWarning("getTime()", columnIndex,
4785: this .this Row.getColumnValue(columnIndex - 1),
4786: this .fields[columnIndex - 1],
4787: new int[] { MysqlDefs.FIELD_TYPE_TIME });
4788: }
4789:
4790: String strTime = getNativeString(columnIndex);
4791:
4792: return getTimeFromString(strTime, targetCalendar, columnIndex,
4793: tz, rollForward);
4794: }
4795:
4796: private Timestamp getNativeTimestamp(int columnIndex,
4797: Calendar targetCalendar, TimeZone tz, boolean rollForward)
4798: throws SQLException {
4799: checkRowPos();
4800: checkColumnBounds(columnIndex);
4801:
4802: int columnIndexMinusOne = columnIndex - 1;
4803:
4804: Timestamp tsVal = null;
4805:
4806: int mysqlType = this .fields[columnIndexMinusOne].getMysqlType();
4807:
4808: switch (mysqlType) {
4809: case MysqlDefs.FIELD_TYPE_DATETIME:
4810: case MysqlDefs.FIELD_TYPE_TIMESTAMP:
4811: tsVal = this .this Row.getNativeTimestamp(
4812: columnIndexMinusOne, targetCalendar, tz,
4813: rollForward, this .connection, this );
4814: break;
4815:
4816: default:
4817:
4818: tsVal = (Timestamp) this .this Row.getNativeDateTimeValue(
4819: columnIndexMinusOne, null, Types.TIMESTAMP,
4820: mysqlType, tz, rollForward, this .connection, this );
4821: }
4822:
4823: //
4824: // normally, we allow ResultSetImpl methods to check for null first,
4825: // but with DATETIME values we have this wacky need to support
4826: // 0000-00-00 00:00:00 -> NULL, so we have to defer
4827: // to the RowHolder implementation, and check the return value.
4828: //
4829:
4830: if (tsVal == null) {
4831:
4832: this .wasNullFlag = true;
4833:
4834: return null;
4835: }
4836:
4837: this .wasNullFlag = false;
4838:
4839: return tsVal;
4840: }
4841:
4842: Timestamp getNativeTimestampViaParseConversion(int columnIndex,
4843: Calendar targetCalendar, TimeZone tz, boolean rollForward)
4844: throws SQLException {
4845: if (this .useUsageAdvisor) {
4846: issueConversionViaParsingWarning("getTimestamp()",
4847: columnIndex, this .this Row
4848: .getColumnValue(columnIndex - 1),
4849: this .fields[columnIndex - 1], new int[] {
4850: MysqlDefs.FIELD_TYPE_TIMESTAMP,
4851: MysqlDefs.FIELD_TYPE_DATETIME });
4852: }
4853:
4854: String strTimestamp = getNativeString(columnIndex);
4855:
4856: return getTimestampFromString(columnIndex, targetCalendar,
4857: strTimestamp, tz, rollForward);
4858: }
4859:
4860: // ---------------------------------------------------------------------
4861: // Updates
4862: // ---------------------------------------------------------------------
4863:
4864: /**
4865: * A column value can also be retrieved as a stream of Unicode characters.
4866: * We implement this as a binary stream.
4867: *
4868: * @param columnIndex
4869: * the first column is 1, the second is 2...
4870: *
4871: * @return a Java InputStream that delivers the database column value as a
4872: * stream of two byte Unicode characters. If the value is SQL NULL,
4873: * then the result is null
4874: *
4875: * @exception SQLException
4876: * if a database access error occurs
4877: *
4878: * @see getAsciiStream
4879: * @see getBinaryStream
4880: */
4881: protected InputStream getNativeUnicodeStream(int columnIndex)
4882: throws SQLException {
4883: checkRowPos();
4884:
4885: return getBinaryStream(columnIndex);
4886: }
4887:
4888: /**
4889: * @see ResultSetInternalMethods#getURL(int)
4890: */
4891: protected URL getNativeURL(int colIndex) throws SQLException {
4892: String val = getString(colIndex);
4893:
4894: if (val == null) {
4895: return null;
4896: }
4897:
4898: try {
4899: return new URL(val);
4900: } catch (MalformedURLException mfe) {
4901: throw SQLError.createSQLException(Messages
4902: .getString("ResultSet.Malformed_URL____141")
4903: + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
4904: }
4905: }
4906:
4907: /**
4908: * DOCUMENT ME!
4909: *
4910: * @return Returns the nextResultSet, if any, null if none exists.
4911: */
4912: public ResultSetInternalMethods getNextResultSet() {
4913: return this .nextResultSet;
4914: }
4915:
4916: /**
4917: * Get the value of a column in the current row as a Java object
4918: *
4919: * <p>
4920: * This method will return the value of the given column as a Java object.
4921: * The type of the Java object will be the default Java Object type
4922: * corresponding to the column's SQL type, following the mapping specified
4923: * in the JDBC specification.
4924: * </p>
4925: *
4926: * <p>
4927: * This method may also be used to read database specific abstract data
4928: * types.
4929: * </p>
4930: *
4931: * @param columnIndex
4932: * the first column is 1, the second is 2...
4933: *
4934: * @return a Object holding the column value
4935: *
4936: * @exception SQLException
4937: * if a database access error occurs
4938: */
4939: public Object getObject(int columnIndex) throws SQLException {
4940: checkRowPos();
4941: checkColumnBounds(columnIndex);
4942:
4943: int columnIndexMinusOne = columnIndex - 1;
4944:
4945: if (this .this Row.isNull(columnIndexMinusOne)) {
4946: this .wasNullFlag = true;
4947:
4948: return null;
4949: }
4950:
4951: this .wasNullFlag = false;
4952:
4953: Field field;
4954: field = this .fields[columnIndexMinusOne];
4955:
4956: switch (field.getSQLType()) {
4957: case Types.BIT:
4958: case Types.BOOLEAN:
4959: if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT
4960: && !field.isSingleBit()) {
4961: return getBytes(columnIndex);
4962: }
4963:
4964: // valueOf would be nicer here, but it isn't
4965: // present in JDK-1.3.1, which is what the CTS
4966: // uses.
4967: return Boolean.valueOf(getBoolean(columnIndex));
4968:
4969: case Types.TINYINT:
4970: if (!field.isUnsigned()) {
4971: return Constants.integerValueOf(getByte(columnIndex));
4972: }
4973:
4974: return Constants.integerValueOf(getInt(columnIndex));
4975:
4976: case Types.SMALLINT:
4977:
4978: return Constants.integerValueOf(getInt(columnIndex));
4979:
4980: case Types.INTEGER:
4981:
4982: if (!field.isUnsigned()
4983: || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
4984: return Constants.integerValueOf(getInt(columnIndex));
4985: }
4986:
4987: return Constants.longValueOf(getLong(columnIndex));
4988:
4989: case Types.BIGINT:
4990:
4991: if (!field.isUnsigned()) {
4992: return Constants.longValueOf(getLong(columnIndex));
4993: }
4994:
4995: String stringVal = getString(columnIndex);
4996:
4997: if (stringVal == null) {
4998: return null;
4999: }
5000:
5001: try {
5002: return new BigInteger(stringVal);
5003: } catch (NumberFormatException nfe) {
5004: throw SQLError.createSQLException(Messages.getString(
5005: "ResultSet.Bad_format_for_BigInteger",
5006: new Object[] {
5007: Constants.integerValueOf(columnIndex),
5008: stringVal }),
5009: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
5010: }
5011:
5012: case Types.DECIMAL:
5013: case Types.NUMERIC:
5014: stringVal = getString(columnIndex);
5015:
5016: BigDecimal val;
5017:
5018: if (stringVal != null) {
5019: if (stringVal.length() == 0) {
5020: val = new BigDecimal(0);
5021:
5022: return val;
5023: }
5024:
5025: try {
5026: val = new BigDecimal(stringVal);
5027: } catch (NumberFormatException ex) {
5028: throw SQLError
5029: .createSQLException(
5030: Messages
5031: .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
5032: + stringVal
5033: + Messages
5034: .getString("ResultSet.___in_column__87")
5035: + columnIndex
5036: + "(" //$NON-NLS-1$
5037: + this .fields[columnIndex - 1]
5038: + ").",
5039: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5040: }
5041:
5042: return val;
5043: }
5044:
5045: return null;
5046:
5047: case Types.REAL:
5048: return new Float(getFloat(columnIndex));
5049:
5050: case Types.FLOAT:
5051: case Types.DOUBLE:
5052: return new Double(getDouble(columnIndex));
5053:
5054: case Types.CHAR:
5055: case Types.VARCHAR:
5056: if (!field.isOpaqueBinary()) {
5057: return getString(columnIndex);
5058: }
5059:
5060: return getBytes(columnIndex);
5061: case Types.LONGVARCHAR:
5062: if (!field.isOpaqueBinary()) {
5063: return getStringForClob(columnIndex);
5064: }
5065:
5066: return getBytes(columnIndex);
5067:
5068: case Types.BINARY:
5069: case Types.VARBINARY:
5070: case Types.LONGVARBINARY:
5071: if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_GEOMETRY) {
5072: return getBytes(columnIndex);
5073: } else if (field.isBinary() || field.isBlob()) {
5074: byte[] data = getBytes(columnIndex);
5075:
5076: if (this .connection.getAutoDeserialize()) {
5077: Object obj = data;
5078:
5079: if ((data != null) && (data.length >= 2)) {
5080: if ((data[0] == -84) && (data[1] == -19)) {
5081: // Serialized object?
5082: try {
5083: ByteArrayInputStream bytesIn = new ByteArrayInputStream(
5084: data);
5085: ObjectInputStream objIn = new ObjectInputStream(
5086: bytesIn);
5087: obj = objIn.readObject();
5088: objIn.close();
5089: bytesIn.close();
5090: } catch (ClassNotFoundException cnfe) {
5091: throw SQLError
5092: .createSQLException(Messages
5093: .getString("ResultSet.Class_not_found___91") //$NON-NLS-1$
5094: + cnfe.toString()
5095: + Messages
5096: .getString("ResultSet._while_reading_serialized_object_92")); //$NON-NLS-1$
5097: } catch (IOException ex) {
5098: obj = data; // not serialized?
5099: }
5100: } else {
5101: return getString(columnIndex);
5102: }
5103: }
5104:
5105: return obj;
5106: }
5107:
5108: return data;
5109: }
5110:
5111: return getBytes(columnIndex);
5112:
5113: case Types.DATE:
5114: if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
5115: && !this .connection.getYearIsDateType()) {
5116: return Constants.shortValueOf(getShort(columnIndex));
5117: }
5118:
5119: return getDate(columnIndex);
5120:
5121: case Types.TIME:
5122: return getTime(columnIndex);
5123:
5124: case Types.TIMESTAMP:
5125: return getTimestamp(columnIndex);
5126:
5127: default:
5128: return getString(columnIndex);
5129: }
5130: }
5131:
5132: /**
5133: * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
5134: * determine the class from which to construct data of SQL structured and
5135: * distinct types.
5136: *
5137: * @param i
5138: * the first column is 1, the second is 2, ...
5139: * @param map
5140: * the mapping from SQL type names to Java classes
5141: *
5142: * @return an object representing the SQL value
5143: *
5144: * @throws SQLException
5145: * because this is not implemented
5146: */
5147: public Object getObject(int i, java.util.Map map)
5148: throws SQLException {
5149: return getObject(i);
5150: }
5151:
5152: /**
5153: * Get the value of a column in the current row as a Java object
5154: *
5155: * <p>
5156: * This method will return the value of the given column as a Java object.
5157: * The type of the Java object will be the default Java Object type
5158: * corresponding to the column's SQL type, following the mapping specified
5159: * in the JDBC specification.
5160: * </p>
5161: *
5162: * <p>
5163: * This method may also be used to read database specific abstract data
5164: * types.
5165: * </p>
5166: *
5167: * @param columnName
5168: * is the SQL name of the column
5169: *
5170: * @return a Object holding the column value
5171: *
5172: * @exception SQLException
5173: * if a database access error occurs
5174: */
5175: public Object getObject(String columnName) throws SQLException {
5176: return getObject(findColumn(columnName));
5177: }
5178:
5179: /**
5180: * JDBC 2.0 Returns the value of column i as a Java object. Use the map to
5181: * determine the class from which to construct data of SQL structured and
5182: * distinct types.
5183: *
5184: * @param colName
5185: * the column name
5186: * @param map
5187: * the mapping from SQL type names to Java classes
5188: *
5189: * @return an object representing the SQL value
5190: *
5191: * @throws SQLException
5192: * as this is not implemented
5193: */
5194: public Object getObject(String colName, java.util.Map map)
5195: throws SQLException {
5196: return getObject(findColumn(colName), map);
5197: }
5198:
5199: public Object getObjectStoredProc(int columnIndex,
5200: int desiredSqlType) throws SQLException {
5201: checkRowPos();
5202: checkColumnBounds(columnIndex);
5203:
5204: Object value = this .this Row.getColumnValue(columnIndex - 1);
5205:
5206: if (value == null) {
5207: this .wasNullFlag = true;
5208:
5209: return null;
5210: }
5211:
5212: this .wasNullFlag = false;
5213:
5214: Field field;
5215: field = this .fields[columnIndex - 1];
5216:
5217: switch (desiredSqlType) {
5218: case Types.BIT:
5219: case Types.BOOLEAN:
5220: // valueOf would be nicer here, but it isn't
5221: // present in JDK-1.3.1, which is what the CTS
5222: // uses.
5223: return Boolean.valueOf(getBoolean(columnIndex));
5224:
5225: case Types.TINYINT:
5226: return Constants.integerValueOf(getInt(columnIndex));
5227:
5228: case Types.SMALLINT:
5229: return Constants.integerValueOf(getInt(columnIndex));
5230:
5231: case Types.INTEGER:
5232:
5233: if (!field.isUnsigned()
5234: || field.getMysqlType() == MysqlDefs.FIELD_TYPE_INT24) {
5235: return Constants.integerValueOf(getInt(columnIndex));
5236: }
5237:
5238: return Constants.longValueOf(getLong(columnIndex));
5239:
5240: case Types.BIGINT:
5241:
5242: if (field.isUnsigned()) {
5243: return getBigDecimal(columnIndex);
5244: }
5245:
5246: return Constants.longValueOf(getLong(columnIndex));
5247:
5248: case Types.DECIMAL:
5249: case Types.NUMERIC:
5250:
5251: String stringVal = getString(columnIndex);
5252: BigDecimal val;
5253:
5254: if (stringVal != null) {
5255: if (stringVal.length() == 0) {
5256: val = new BigDecimal(0);
5257:
5258: return val;
5259: }
5260:
5261: try {
5262: val = new BigDecimal(stringVal);
5263: } catch (NumberFormatException ex) {
5264: throw SQLError
5265: .createSQLException(
5266: Messages
5267: .getString("ResultSet.Bad_format_for_BigDecimal____86") //$NON-NLS-1$
5268: + stringVal
5269: + Messages
5270: .getString("ResultSet.___in_column__87")
5271: + columnIndex
5272: + "(" //$NON-NLS-1$
5273: + this .fields[columnIndex - 1]
5274: + ").",
5275: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5276: }
5277:
5278: return val;
5279: }
5280:
5281: return null;
5282:
5283: case Types.REAL:
5284: return new Float(getFloat(columnIndex));
5285:
5286: case Types.FLOAT:
5287:
5288: if (!this .connection.getRunningCTS13()) {
5289: return new Double(getFloat(columnIndex));
5290: } else {
5291: return new Float(getFloat(columnIndex)); // NB - bug in JDBC
5292: // compliance test,
5293: // according
5294: // to JDBC spec, FLOAT type should return DOUBLE
5295: // but causes ClassCastException in CTS :(
5296: }
5297: case Types.DOUBLE:
5298: return new Double(getDouble(columnIndex));
5299:
5300: case Types.CHAR:
5301: case Types.VARCHAR:
5302: return getString(columnIndex);
5303: case Types.LONGVARCHAR:
5304: return getStringForClob(columnIndex);
5305: case Types.BINARY:
5306: case Types.VARBINARY:
5307: case Types.LONGVARBINARY:
5308: return getBytes(columnIndex);
5309:
5310: case Types.DATE:
5311: if (field.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR
5312: && !this .connection.getYearIsDateType()) {
5313: return Constants.shortValueOf(getShort(columnIndex));
5314: }
5315:
5316: return getDate(columnIndex);
5317:
5318: case Types.TIME:
5319: return getTime(columnIndex);
5320:
5321: case Types.TIMESTAMP:
5322: return getTimestamp(columnIndex);
5323:
5324: default:
5325: return getString(columnIndex);
5326: }
5327: }
5328:
5329: public Object getObjectStoredProc(int i, java.util.Map map,
5330: int desiredSqlType) throws SQLException {
5331: return getObjectStoredProc(i, desiredSqlType);
5332: }
5333:
5334: public Object getObjectStoredProc(String columnName,
5335: int desiredSqlType) throws SQLException {
5336: return getObjectStoredProc(findColumn(columnName),
5337: desiredSqlType);
5338: }
5339:
5340: public Object getObjectStoredProc(String colName,
5341: java.util.Map map, int desiredSqlType) throws SQLException {
5342: return getObjectStoredProc(findColumn(colName), map,
5343: desiredSqlType);
5344: }
5345:
5346: /**
5347: * JDBC 2.0 Get a REF(<structured-type>) column.
5348: *
5349: * @param i
5350: * the first column is 1, the second is 2, ...
5351: *
5352: * @return an object representing data of an SQL REF type
5353: *
5354: * @throws SQLException
5355: * as this is not implemented
5356: * @throws NotImplemented
5357: * DOCUMENT ME!
5358: */
5359: public java.sql.Ref getRef(int i) throws SQLException {
5360: checkColumnBounds(i);
5361: throw new NotImplemented();
5362: }
5363:
5364: /**
5365: * JDBC 2.0 Get a REF(<structured-type>) column.
5366: *
5367: * @param colName
5368: * the column name
5369: *
5370: * @return an object representing data of an SQL REF type
5371: *
5372: * @throws SQLException
5373: * as this method is not implemented.
5374: * @throws NotImplemented
5375: * DOCUMENT ME!
5376: */
5377: public java.sql.Ref getRef(String colName) throws SQLException {
5378: return getRef(findColumn(colName));
5379: }
5380:
5381: /**
5382: * JDBC 2.0
5383: *
5384: * <p>
5385: * Determine the current row number. The first row is number 1, the second
5386: * number 2, etc.
5387: * </p>
5388: *
5389: * @return the current row number, else return 0 if there is no current row
5390: *
5391: * @exception SQLException
5392: * if a database-access error occurs.
5393: */
5394: public int getRow() throws SQLException {
5395: checkClosed();
5396:
5397: int currentRowNumber = this .rowData.getCurrentRowNumber();
5398: int row = 0;
5399:
5400: // Non-dynamic result sets can be interrogated
5401: // for this information
5402: if (!this .rowData.isDynamic()) {
5403: if ((currentRowNumber < 0) || this .rowData.isAfterLast()
5404: || this .rowData.isEmpty()) {
5405: row = 0;
5406: } else {
5407: row = currentRowNumber + 1;
5408: }
5409: } else {
5410: // dynamic (streaming) can not
5411: row = currentRowNumber + 1;
5412: }
5413:
5414: return row;
5415: }
5416:
5417: /**
5418: * Returns the server info (if any), or null if none.
5419: *
5420: * @return server info created for this ResultSet
5421: */
5422: public String getServerInfo() {
5423: return this .serverInfo;
5424: }
5425:
5426: private long getNumericRepresentationOfSQLBitType(int columnIndex)
5427: throws SQLException {
5428:
5429: Object value = this .this Row.getColumnValue(columnIndex - 1);
5430:
5431: if (this .fields[columnIndex - 1].isSingleBit()
5432: || ((byte[]) value).length == 1) {
5433: return ((byte[]) value)[0];
5434: }
5435:
5436: byte[] asBytes = (byte[]) value;
5437:
5438: int shift = 0;
5439:
5440: long[] steps = new long[asBytes.length];
5441:
5442: for (int i = asBytes.length - 1; i >= 0; i--) {
5443: steps[i] = (long) (asBytes[i] & 0xff) << shift;
5444: shift += 8;
5445: }
5446:
5447: long valueAsLong = 0;
5448:
5449: for (int i = 0; i < asBytes.length; i++) {
5450: valueAsLong |= steps[i];
5451: }
5452:
5453: return valueAsLong;
5454: }
5455:
5456: /**
5457: * Get the value of a column in the current row as a Java short.
5458: *
5459: * @param columnIndex
5460: * the first column is 1, the second is 2,...
5461: *
5462: * @return the column value; 0 if SQL NULL
5463: *
5464: * @exception SQLException
5465: * if a database access error occurs
5466: */
5467: public short getShort(int columnIndex) throws SQLException {
5468: if (!this .isBinaryEncoded) {
5469: checkRowPos();
5470:
5471: if (this .connection.getUseFastIntParsing()) {
5472:
5473: checkColumnBounds(columnIndex);
5474:
5475: Object value = this .this Row
5476: .getColumnValue(columnIndex - 1);
5477:
5478: if (value == null) {
5479: this .wasNullFlag = true;
5480: } else {
5481: this .wasNullFlag = false;
5482: }
5483:
5484: if (this .wasNullFlag) {
5485: return 0;
5486: }
5487:
5488: byte[] shortAsBytes = (byte[]) value;
5489:
5490: if (shortAsBytes.length == 0) {
5491: return (short) convertToZeroWithEmptyCheck();
5492: }
5493:
5494: boolean needsFullParse = false;
5495:
5496: for (int i = 0; i < shortAsBytes.length; i++) {
5497: if (((char) shortAsBytes[i] == 'e')
5498: || ((char) shortAsBytes[i] == 'E')) {
5499: needsFullParse = true;
5500:
5501: break;
5502: }
5503: }
5504:
5505: if (!needsFullParse) {
5506: try {
5507: return parseShortWithOverflowCheck(columnIndex,
5508: shortAsBytes, null);
5509: } catch (NumberFormatException nfe) {
5510: try {
5511: // To do: Warn of over/underflow???
5512: return parseShortAsDouble(columnIndex,
5513: new String(shortAsBytes));
5514: } catch (NumberFormatException newNfe) {
5515: ; // ignore, it's not a number
5516: }
5517:
5518: if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5519: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
5520:
5521: if (this .connection
5522: .getJdbcCompliantTruncationForReads()
5523: && (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE)) {
5524: throwRangeException(String
5525: .valueOf(valueAsLong),
5526: columnIndex, Types.SMALLINT);
5527: }
5528:
5529: return (short) valueAsLong;
5530: }
5531:
5532: throw SQLError
5533: .createSQLException(
5534: Messages
5535: .getString("ResultSet.Invalid_value_for_getShort()_-____96")
5536: + new String(
5537: shortAsBytes) //$NON-NLS-1$
5538: + "'",
5539: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5540: }
5541: }
5542: }
5543:
5544: String val = null;
5545:
5546: try {
5547: val = getString(columnIndex);
5548:
5549: if ((val != null)) {
5550:
5551: if (val.length() == 0) {
5552: return (short) convertToZeroWithEmptyCheck();
5553: }
5554:
5555: if ((val.indexOf("e") == -1)
5556: && (val.indexOf("E") == -1)
5557: && (val.indexOf(".") == -1)) {
5558: return parseShortWithOverflowCheck(columnIndex,
5559: null, val);
5560: }
5561:
5562: // Convert floating point
5563: return parseShortAsDouble(columnIndex, val);
5564: }
5565:
5566: return 0; // for NULL
5567: } catch (NumberFormatException nfe) {
5568: try {
5569: return parseShortAsDouble(columnIndex, val);
5570: } catch (NumberFormatException newNfe) {
5571: ; // ignore, it's not a number
5572: }
5573:
5574: if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5575: long valueAsLong = getNumericRepresentationOfSQLBitType(columnIndex);
5576:
5577: if (this .connection
5578: .getJdbcCompliantTruncationForReads()
5579: && (valueAsLong < Short.MIN_VALUE || valueAsLong > Short.MAX_VALUE)) {
5580: throwRangeException(
5581: String.valueOf(valueAsLong),
5582: columnIndex, Types.SMALLINT);
5583: }
5584:
5585: return (short) valueAsLong;
5586: }
5587:
5588: throw SQLError
5589: .createSQLException(
5590: Messages
5591: .getString("ResultSet.Invalid_value_for_getShort()_-____96")
5592: + val //$NON-NLS-1$
5593: + "'",
5594: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5595: }
5596: }
5597:
5598: return getNativeShort(columnIndex);
5599: }
5600:
5601: /**
5602: * DOCUMENT ME!
5603: *
5604: * @param columnName
5605: * DOCUMENT ME!
5606: *
5607: * @return DOCUMENT ME!
5608: *
5609: * @throws SQLException
5610: * DOCUMENT ME!
5611: */
5612: public short getShort(String columnName) throws SQLException {
5613: return getShort(findColumn(columnName));
5614: }
5615:
5616: private final short getShortFromString(String val, int columnIndex)
5617: throws SQLException {
5618: try {
5619: if ((val != null)) {
5620:
5621: if (val.length() == 0) {
5622: return (short) convertToZeroWithEmptyCheck();
5623: }
5624:
5625: if ((val.indexOf("e") == -1)
5626: && (val.indexOf("E") == -1)
5627: && (val.indexOf(".") == -1)) {
5628: return parseShortWithOverflowCheck(columnIndex,
5629: null, val);
5630: }
5631:
5632: // Convert floating point
5633: return parseShortAsDouble(columnIndex, val);
5634: }
5635:
5636: return 0; // for NULL
5637: } catch (NumberFormatException nfe) {
5638: try {
5639: return parseShortAsDouble(columnIndex, val);
5640: } catch (NumberFormatException newNfe) {
5641: ; // ignore, it's not a number
5642: }
5643:
5644: throw SQLError
5645: .createSQLException(
5646: Messages
5647: .getString("ResultSet.Invalid_value_for_getShort()_-____217")
5648: + val //$NON-NLS-1$
5649: + Messages
5650: .getString("ResultSet.___in_column__218")
5651: + columnIndex,
5652: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
5653: }
5654: }
5655:
5656: /**
5657: * JDBC 2.0 Return the Statement that produced the ResultSet.
5658: *
5659: * @return the Statment that produced the result set, or null if the result
5660: * was produced some other way.
5661: *
5662: * @exception SQLException
5663: * if a database-access error occurs
5664: */
5665: public java.sql.Statement getStatement() throws SQLException {
5666: if (this .isClosed && !this .retainOwningStatement) {
5667: throw SQLError
5668: .createSQLException(
5669: "Operation not allowed on closed ResultSet. Statements "
5670: + "can be retained over result set closure by setting the connection property "
5671: + "\"retainStatementAfterResultSetClose\" to \"true\".",
5672: SQLError.SQL_STATE_GENERAL_ERROR);
5673:
5674: }
5675:
5676: if (this .wrapperStatement != null) {
5677: return this .wrapperStatement;
5678: }
5679:
5680: return this .owningStatement;
5681: }
5682:
5683: /**
5684: * Get the value of a column in the current row as a Java String
5685: *
5686: * @param columnIndex
5687: * the first column is 1, the second is 2...
5688: *
5689: * @return the column value, null for SQL NULL
5690: *
5691: * @exception SQLException
5692: * if a database access error occurs
5693: */
5694: public String getString(int columnIndex) throws SQLException {
5695: String stringVal = getStringInternal(columnIndex, true);
5696:
5697: if (this .padCharsWithSpace) {
5698: Field f = this .fields[columnIndex - 1];
5699:
5700: if (f.getMysqlType() == MysqlDefs.FIELD_TYPE_STRING) {
5701: int fieldLength = (int) f.getLength() /* safe, bytes in a CHAR <= 1024 */
5702: / f.getMaxBytesPerCharacter(); /* safe, this will never be 0 */
5703:
5704: int currentLength = stringVal.length();
5705:
5706: if (currentLength < fieldLength) {
5707: StringBuffer paddedBuf = new StringBuffer(
5708: fieldLength);
5709: paddedBuf.append(stringVal);
5710:
5711: int difference = fieldLength - currentLength;
5712:
5713: paddedBuf.append(EMPTY_SPACE, 0, difference);
5714:
5715: stringVal = paddedBuf.toString();
5716: }
5717: }
5718: }
5719:
5720: return stringVal;
5721: }
5722:
5723: /**
5724: * The following routines simply convert the columnName into a columnIndex
5725: * and then call the appropriate routine above.
5726: *
5727: * @param columnName
5728: * is the SQL name of the column
5729: *
5730: * @return the column value
5731: *
5732: * @exception SQLException
5733: * if a database access error occurs
5734: */
5735: public String getString(String columnName) throws SQLException {
5736: return getString(findColumn(columnName));
5737: }
5738:
5739: private String getStringForClob(int columnIndex)
5740: throws SQLException {
5741: String asString = null;
5742:
5743: String forcedEncoding = this .connection
5744: .getClobCharacterEncoding();
5745:
5746: if (forcedEncoding == null) {
5747: if (!this .isBinaryEncoded) {
5748: asString = getString(columnIndex);
5749: } else {
5750: asString = getNativeString(columnIndex);
5751: }
5752: } else {
5753: try {
5754: byte[] asBytes = null;
5755:
5756: if (!this .isBinaryEncoded) {
5757: asBytes = getBytes(columnIndex);
5758: } else {
5759: asBytes = getNativeBytes(columnIndex, true);
5760: }
5761:
5762: if (asBytes != null) {
5763: asString = new String(asBytes, forcedEncoding);
5764: }
5765: } catch (UnsupportedEncodingException uee) {
5766: throw SQLError.createSQLException(
5767: "Unsupported character encoding "
5768: + forcedEncoding,
5769: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
5770: }
5771: }
5772:
5773: return asString;
5774: }
5775:
5776: protected String getStringInternal(int columnIndex,
5777: boolean checkDateTypes) throws SQLException {
5778: if (!this .isBinaryEncoded) {
5779: checkRowPos();
5780: checkColumnBounds(columnIndex);
5781:
5782: if (this .fields == null) {
5783: throw SQLError
5784: .createSQLException(
5785: Messages
5786: .getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$
5787: SQLError.SQL_STATE_INVALID_COLUMN_NUMBER);
5788: }
5789:
5790: // JDBC is 1-based, Java is not !?
5791:
5792: int internalColumnIndex = columnIndex - 1;
5793:
5794: if (this .this Row.isNull(internalColumnIndex)) {
5795: this .wasNullFlag = true;
5796:
5797: return null;
5798: }
5799:
5800: this .wasNullFlag = false;
5801:
5802: Field metadata = this .fields[internalColumnIndex];
5803:
5804: String stringVal = null;
5805:
5806: if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
5807: if (metadata.isSingleBit()) {
5808: byte[] value = this .this Row
5809: .getColumnValue(internalColumnIndex);
5810:
5811: if (value.length == 0) {
5812: return String
5813: .valueOf(convertToZeroWithEmptyCheck());
5814: }
5815:
5816: return String.valueOf(value[0]);
5817: }
5818:
5819: return String
5820: .valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
5821: }
5822:
5823: String encoding = metadata.getCharacterSet();
5824:
5825: stringVal = this .this Row.getString(internalColumnIndex,
5826: encoding, this .connection);
5827:
5828: //
5829: // Special handling for YEAR type from mysql, some people
5830: // want it as a DATE, others want to treat it as a SHORT
5831: //
5832:
5833: if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
5834: if (!this .connection.getYearIsDateType()) {
5835: return stringVal;
5836: }
5837:
5838: Date dt = getDateFromString(stringVal, columnIndex);
5839:
5840: if (dt == null) {
5841: this .wasNullFlag = true;
5842:
5843: return null;
5844: }
5845:
5846: this .wasNullFlag = false;
5847:
5848: return dt.toString();
5849: }
5850:
5851: // Handles timezone conversion and zero-date behavior
5852:
5853: if (checkDateTypes
5854: && !this .connection.getNoDatetimeStringSync()) {
5855: switch (metadata.getSQLType()) {
5856: case Types.TIME:
5857: Time tm = getTimeFromString(stringVal, null,
5858: columnIndex, this .getDefaultTimeZone(),
5859: false);
5860:
5861: if (tm == null) {
5862: this .wasNullFlag = true;
5863:
5864: return null;
5865: }
5866:
5867: this .wasNullFlag = false;
5868:
5869: return tm.toString();
5870: case Types.DATE:
5871:
5872: Date dt = getDateFromString(stringVal, columnIndex);
5873:
5874: if (dt == null) {
5875: this .wasNullFlag = true;
5876:
5877: return null;
5878: }
5879:
5880: this .wasNullFlag = false;
5881:
5882: return dt.toString();
5883: case Types.TIMESTAMP:
5884: Timestamp ts = getTimestampFromString(columnIndex,
5885: null, stringVal, this .getDefaultTimeZone(),
5886: false);
5887:
5888: if (ts == null) {
5889: this .wasNullFlag = true;
5890:
5891: return null;
5892: }
5893:
5894: this .wasNullFlag = false;
5895:
5896: return ts.toString();
5897: default:
5898: break;
5899: }
5900: }
5901:
5902: return stringVal;
5903: }
5904:
5905: return getNativeString(columnIndex);
5906: }
5907:
5908: /**
5909: * Get the value of a column in the current row as a java.sql.Time object
5910: *
5911: * @param columnIndex
5912: * the first column is 1, the second is 2...
5913: *
5914: * @return the column value; null if SQL NULL
5915: *
5916: * @throws java.sql.SQLException
5917: * if a database access error occurs
5918: */
5919: public Time getTime(int columnIndex) throws java.sql.SQLException {
5920: return getTimeInternal(columnIndex, null, this
5921: .getDefaultTimeZone(), false);
5922: }
5923:
5924: /**
5925: * Get the value of a column in the current row as a java.sql.Time object.
5926: * Use the calendar to construct an appropriate millisecond value for the
5927: * Time, if the underlying database doesn't store timezone information.
5928: *
5929: * @param columnIndex
5930: * the first column is 1, the second is 2, ...
5931: * @param cal
5932: * the calendar to use in constructing the time
5933: *
5934: * @return the column value; if the value is SQL NULL, the result is null
5935: *
5936: * @exception SQLException
5937: * if a database-access error occurs.
5938: */
5939: public java.sql.Time getTime(int columnIndex, Calendar cal)
5940: throws SQLException {
5941: return getTimeInternal(columnIndex, cal, cal.getTimeZone(),
5942: true);
5943: }
5944:
5945: /**
5946: * Get the value of a column in the current row as a java.sql.Time object.
5947: *
5948: * @param columnName
5949: * is the SQL name of the column
5950: *
5951: * @return the column value; if the value is SQL NULL, the result is null
5952: *
5953: * @throws java.sql.SQLException
5954: * if a database-access error occurs.
5955: */
5956: public Time getTime(String columnName) throws java.sql.SQLException {
5957: return getTime(findColumn(columnName));
5958: }
5959:
5960: /**
5961: * Get the value of a column in the current row as a java.sql.Time object.
5962: * Use the calendar to construct an appropriate millisecond value for the
5963: * Time, if the underlying database doesn't store timezone information.
5964: *
5965: * @param columnName
5966: * is the SQL name of the column
5967: * @param cal
5968: * the calendar to use in constructing the time
5969: *
5970: * @return the column value; if the value is SQL NULL, the result is null
5971: *
5972: * @exception SQLException
5973: * if a database-access error occurs.
5974: */
5975: public java.sql.Time getTime(String columnName, Calendar cal)
5976: throws SQLException {
5977: return getTime(findColumn(columnName), cal);
5978: }
5979:
5980: private Time getTimeFromString(String timeAsString,
5981: Calendar targetCalendar, int columnIndex, TimeZone tz,
5982: boolean rollForward) throws SQLException {
5983: int hr = 0;
5984: int min = 0;
5985: int sec = 0;
5986:
5987: try {
5988:
5989: if (timeAsString == null) {
5990: this .wasNullFlag = true;
5991:
5992: return null;
5993: }
5994:
5995: //
5996: // JDK-6 doesn't like trailing whitespace
5997: //
5998: // Note this isn't a performance issue, other
5999: // than the iteration over the string, as String.trim()
6000: // will return a new string only if whitespace is present
6001: //
6002:
6003: timeAsString = timeAsString.trim();
6004:
6005: if (timeAsString.equals("0")
6006: || timeAsString.equals("0000-00-00")
6007: || timeAsString.equals("0000-00-00 00:00:00")
6008: || timeAsString.equals("00000000000000")) {
6009: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
6010: .equals(this .connection
6011: .getZeroDateTimeBehavior())) {
6012: this .wasNullFlag = true;
6013:
6014: return null;
6015: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
6016: .equals(this .connection
6017: .getZeroDateTimeBehavior())) {
6018: throw SQLError
6019: .createSQLException(
6020: "Value '"
6021: + timeAsString
6022: + "' can not be represented as java.sql.Time",
6023: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6024: }
6025:
6026: // We're left with the case of 'round' to a time Java _can_
6027: // represent, which is '00:00:00'
6028: return fastTimeCreate(null, 0, 0, 0);
6029: }
6030:
6031: this .wasNullFlag = false;
6032:
6033: Field timeColField = this .fields[columnIndex - 1];
6034:
6035: if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_TIMESTAMP) {
6036: // It's a timestamp
6037: int length = timeAsString.length();
6038:
6039: switch (length) {
6040: case 19: { // YYYY-MM-DD hh:mm:ss
6041:
6042: hr = Integer.parseInt(timeAsString.substring(
6043: length - 8, length - 6));
6044: min = Integer.parseInt(timeAsString.substring(
6045: length - 5, length - 3));
6046: sec = Integer.parseInt(timeAsString.substring(
6047: length - 2, length));
6048: }
6049:
6050: break;
6051: case 14:
6052: case 12: {
6053: hr = Integer.parseInt(timeAsString.substring(
6054: length - 6, length - 4));
6055: min = Integer.parseInt(timeAsString.substring(
6056: length - 4, length - 2));
6057: sec = Integer.parseInt(timeAsString.substring(
6058: length - 2, length));
6059: }
6060:
6061: break;
6062:
6063: case 10: {
6064: hr = Integer.parseInt(timeAsString.substring(6, 8));
6065: min = Integer.parseInt(timeAsString
6066: .substring(8, 10));
6067: sec = 0;
6068: }
6069:
6070: break;
6071:
6072: default:
6073: throw SQLError
6074: .createSQLException(
6075: Messages
6076: .getString("ResultSet.Timestamp_too_small_to_convert_to_Time_value_in_column__257") //$NON-NLS-1$
6077: + columnIndex
6078: + "("
6079: + this .fields[columnIndex - 1]
6080: + ").",
6081: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6082: } /* endswitch */
6083:
6084: SQLWarning precisionLost = new SQLWarning(
6085: Messages
6086: .getString("ResultSet.Precision_lost_converting_TIMESTAMP_to_Time_with_getTime()_on_column__261") //$NON-NLS-1$
6087: + columnIndex
6088: + "("
6089: + this .fields[columnIndex - 1] + ").");
6090:
6091: if (this .warningChain == null) {
6092: this .warningChain = precisionLost;
6093: } else {
6094: this .warningChain.setNextWarning(precisionLost);
6095: }
6096: } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATETIME) {
6097: hr = Integer.parseInt(timeAsString.substring(11, 13));
6098: min = Integer.parseInt(timeAsString.substring(14, 16));
6099: sec = Integer.parseInt(timeAsString.substring(17, 19));
6100:
6101: SQLWarning precisionLost = new SQLWarning(
6102: Messages
6103: .getString("ResultSet.Precision_lost_converting_DATETIME_to_Time_with_getTime()_on_column__264") //$NON-NLS-1$
6104: + columnIndex
6105: + "("
6106: + this .fields[columnIndex - 1] + ").");
6107:
6108: if (this .warningChain == null) {
6109: this .warningChain = precisionLost;
6110: } else {
6111: this .warningChain.setNextWarning(precisionLost);
6112: }
6113: } else if (timeColField.getMysqlType() == MysqlDefs.FIELD_TYPE_DATE) {
6114: return fastTimeCreate(null, 0, 0, 0); // midnight on the given
6115: // date
6116: } else {
6117: // convert a String to a Time
6118: if ((timeAsString.length() != 5)
6119: && (timeAsString.length() != 8)) {
6120: throw SQLError
6121: .createSQLException(
6122: Messages
6123: .getString("ResultSet.Bad_format_for_Time____267") //$NON-NLS-1$
6124: + timeAsString
6125: + Messages
6126: .getString("ResultSet.___in_column__268")
6127: + columnIndex,
6128: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6129: }
6130:
6131: hr = Integer.parseInt(timeAsString.substring(0, 2));
6132: min = Integer.parseInt(timeAsString.substring(3, 5));
6133: sec = (timeAsString.length() == 5) ? 0 : Integer
6134: .parseInt(timeAsString.substring(6));
6135: }
6136:
6137: Calendar sessionCalendar = this
6138: .getCalendarInstanceForSessionOrNew();
6139:
6140: synchronized (sessionCalendar) {
6141: return TimeUtil.changeTimezone(this .connection,
6142: sessionCalendar, targetCalendar,
6143: fastTimeCreate(sessionCalendar, hr, min, sec),
6144: this .connection.getServerTimezoneTZ(), tz,
6145: rollForward);
6146: }
6147: } catch (Exception ex) {
6148: throw SQLError.createSQLException(ex.toString(),
6149: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6150: }
6151: }
6152:
6153: /**
6154: * Get the value of a column in the current row as a java.sql.Time object in
6155: * the given timezone
6156: *
6157: * @param columnIndex
6158: * the first column is 1, the second is 2...
6159: * @param tz
6160: * the Timezone to use
6161: *
6162: * @return the column value; null if SQL NULL
6163: *
6164: * @exception java.sql.SQLException
6165: * if a database access error occurs
6166: */
6167: private Time getTimeInternal(int columnIndex,
6168: Calendar targetCalendar, TimeZone tz, boolean rollForward)
6169: throws java.sql.SQLException {
6170: if (this .isBinaryEncoded) {
6171: return getNativeTime(columnIndex, targetCalendar, tz,
6172: rollForward);
6173: }
6174:
6175: if (!this .useFastDateParsing) {
6176: String timeAsString = getStringInternal(columnIndex, false);
6177:
6178: return getTimeFromString(timeAsString, targetCalendar,
6179: columnIndex, tz, rollForward);
6180: }
6181:
6182: checkColumnBounds(columnIndex);
6183:
6184: int columnIndexMinusOne = columnIndex - 1;
6185:
6186: if (this .this Row.isNull(columnIndexMinusOne)) {
6187: this .wasNullFlag = true;
6188:
6189: return null;
6190: }
6191:
6192: this .wasNullFlag = false;
6193:
6194: return this .this Row.getTimeFast(columnIndexMinusOne,
6195: targetCalendar, tz, rollForward, this .connection, this );
6196: }
6197:
6198: /**
6199: * Get the value of a column in the current row as a java.sql.Timestamp
6200: * object
6201: *
6202: * @param columnIndex
6203: * the first column is 1, the second is 2...
6204: *
6205: * @return the column value; null if SQL NULL
6206: *
6207: * @exception java.sql.SQLException
6208: * if a database access error occurs
6209: */
6210: public Timestamp getTimestamp(int columnIndex)
6211: throws java.sql.SQLException {
6212: checkColumnBounds(columnIndex);
6213:
6214: return getTimestampInternal(columnIndex, null, this
6215: .getDefaultTimeZone(), false);
6216: }
6217:
6218: /**
6219: * Get the value of a column in the current row as a java.sql.Timestamp
6220: * object. Use the calendar to construct an appropriate millisecond value
6221: * for the Timestamp, if the underlying database doesn't store timezone
6222: * information.
6223: *
6224: * @param columnIndex
6225: * the first column is 1, the second is 2, ...
6226: * @param cal
6227: * the calendar to use in constructing the timestamp
6228: *
6229: * @return the column value; if the value is SQL NULL, the result is null
6230: *
6231: * @exception SQLException
6232: * if a database-access error occurs.
6233: */
6234: public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal)
6235: throws SQLException {
6236: return getTimestampInternal(columnIndex, cal,
6237: cal.getTimeZone(), true);
6238: }
6239:
6240: /**
6241: * DOCUMENT ME!
6242: *
6243: * @param columnName
6244: * DOCUMENT ME!
6245: *
6246: * @return DOCUMENT ME!
6247: *
6248: * @throws java.sql.SQLException
6249: * DOCUMENT ME!
6250: */
6251: public Timestamp getTimestamp(String columnName)
6252: throws java.sql.SQLException {
6253: return getTimestamp(findColumn(columnName));
6254: }
6255:
6256: /**
6257: * Get the value of a column in the current row as a java.sql.Timestamp
6258: * object. Use the calendar to construct an appropriate millisecond value
6259: * for the Timestamp, if the underlying database doesn't store timezone
6260: * information.
6261: *
6262: * @param columnName
6263: * is the SQL name of the column
6264: * @param cal
6265: * the calendar to use in constructing the timestamp
6266: *
6267: * @return the column value; if the value is SQL NULL, the result is null
6268: *
6269: * @exception SQLException
6270: * if a database-access error occurs.
6271: */
6272: public java.sql.Timestamp getTimestamp(String columnName,
6273: Calendar cal) throws SQLException {
6274: return getTimestamp(findColumn(columnName), cal);
6275: }
6276:
6277: private Timestamp getTimestampFromString(int columnIndex,
6278: Calendar targetCalendar, String timestampValue,
6279: TimeZone tz, boolean rollForward)
6280: throws java.sql.SQLException {
6281: try {
6282: this .wasNullFlag = false;
6283:
6284: if (timestampValue == null) {
6285: this .wasNullFlag = true;
6286:
6287: return null;
6288: }
6289:
6290: //
6291: // JDK-6 doesn't like trailing whitespace
6292: //
6293: // Note this isn't a performance issue, other
6294: // than the iteration over the string, as String.trim()
6295: // will return a new string only if whitespace is present
6296: //
6297:
6298: timestampValue = timestampValue.trim();
6299:
6300: int length = timestampValue.length();
6301:
6302: Calendar sessionCalendar = this .connection
6303: .getUseJDBCCompliantTimezoneShift() ? this .connection
6304: .getUtcCalendar()
6305: : getCalendarInstanceForSessionOrNew();
6306:
6307: synchronized (sessionCalendar) {
6308: if ((length > 0)
6309: && (timestampValue.charAt(0) == '0')
6310: && (timestampValue.equals("0000-00-00")
6311: || timestampValue
6312: .equals("0000-00-00 00:00:00")
6313: || timestampValue
6314: .equals("00000000000000") || timestampValue
6315: .equals("0"))) {
6316:
6317: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
6318: .equals(this .connection
6319: .getZeroDateTimeBehavior())) {
6320: this .wasNullFlag = true;
6321:
6322: return null;
6323: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
6324: .equals(this .connection
6325: .getZeroDateTimeBehavior())) {
6326: throw SQLError
6327: .createSQLException(
6328: "Value '"
6329: + timestampValue
6330: + "' can not be represented as java.sql.Timestamp",
6331: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6332: }
6333:
6334: // We're left with the case of 'round' to a date Java _can_
6335: // represent, which is '0001-01-01'.
6336: return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0,
6337: 0);
6338:
6339: } else if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
6340:
6341: return TimeUtil.changeTimezone(this .connection,
6342: sessionCalendar, targetCalendar,
6343: fastTimestampCreate(sessionCalendar,
6344: Integer.parseInt(timestampValue
6345: .substring(0, 4)), 1, 1, 0,
6346: 0, 0, 0), this .connection
6347: .getServerTimezoneTZ(), tz,
6348: rollForward);
6349:
6350: } else {
6351: if (timestampValue.endsWith(".")) {
6352: timestampValue = timestampValue.substring(0,
6353: timestampValue.length() - 1);
6354: }
6355:
6356: // Convert from TIMESTAMP or DATE
6357: switch (length) {
6358: case 26:
6359: case 25:
6360: case 24:
6361: case 23:
6362: case 22:
6363: case 21:
6364: case 20:
6365: case 19: {
6366: int year = Integer.parseInt(timestampValue
6367: .substring(0, 4));
6368: int month = Integer.parseInt(timestampValue
6369: .substring(5, 7));
6370: int day = Integer.parseInt(timestampValue
6371: .substring(8, 10));
6372: int hour = Integer.parseInt(timestampValue
6373: .substring(11, 13));
6374: int minutes = Integer.parseInt(timestampValue
6375: .substring(14, 16));
6376: int seconds = Integer.parseInt(timestampValue
6377: .substring(17, 19));
6378:
6379: int nanos = 0;
6380:
6381: if (length > 19) {
6382: int decimalIndex = timestampValue
6383: .lastIndexOf('.');
6384:
6385: if (decimalIndex != -1) {
6386: if ((decimalIndex + 2) <= timestampValue
6387: .length()) {
6388: nanos = Integer
6389: .parseInt(timestampValue
6390: .substring(decimalIndex + 1));
6391: } else {
6392: throw new IllegalArgumentException(); // re-thrown
6393: // further
6394: // down
6395: // with
6396: // a
6397: // much better error message
6398: }
6399: }
6400: }
6401:
6402: return TimeUtil.changeTimezone(this .connection,
6403: sessionCalendar, targetCalendar,
6404: fastTimestampCreate(sessionCalendar,
6405: year, month, day, hour,
6406: minutes, seconds, nanos),
6407: this .connection.getServerTimezoneTZ(),
6408: tz, rollForward);
6409: }
6410:
6411: case 14: {
6412: int year = Integer.parseInt(timestampValue
6413: .substring(0, 4));
6414: int month = Integer.parseInt(timestampValue
6415: .substring(4, 6));
6416: int day = Integer.parseInt(timestampValue
6417: .substring(6, 8));
6418: int hour = Integer.parseInt(timestampValue
6419: .substring(8, 10));
6420: int minutes = Integer.parseInt(timestampValue
6421: .substring(10, 12));
6422: int seconds = Integer.parseInt(timestampValue
6423: .substring(12, 14));
6424:
6425: return TimeUtil.changeTimezone(this .connection,
6426: sessionCalendar, targetCalendar,
6427: fastTimestampCreate(sessionCalendar,
6428: year, month, day, hour,
6429: minutes, seconds, 0),
6430: this .connection.getServerTimezoneTZ(),
6431: tz, rollForward);
6432: }
6433:
6434: case 12: {
6435: int year = Integer.parseInt(timestampValue
6436: .substring(0, 2));
6437:
6438: if (year <= 69) {
6439: year = (year + 100);
6440: }
6441:
6442: int month = Integer.parseInt(timestampValue
6443: .substring(2, 4));
6444: int day = Integer.parseInt(timestampValue
6445: .substring(4, 6));
6446: int hour = Integer.parseInt(timestampValue
6447: .substring(6, 8));
6448: int minutes = Integer.parseInt(timestampValue
6449: .substring(8, 10));
6450: int seconds = Integer.parseInt(timestampValue
6451: .substring(10, 12));
6452:
6453: return TimeUtil.changeTimezone(this .connection,
6454: sessionCalendar, targetCalendar,
6455: fastTimestampCreate(sessionCalendar,
6456: year + 1900, month, day, hour,
6457: minutes, seconds, 0),
6458: this .connection.getServerTimezoneTZ(),
6459: tz, rollForward);
6460: }
6461:
6462: case 10: {
6463: int year;
6464: int month;
6465: int day;
6466: int hour;
6467: int minutes;
6468:
6469: if ((this .fields[columnIndex - 1]
6470: .getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
6471: || (timestampValue.indexOf("-") != -1)) {
6472: year = Integer.parseInt(timestampValue
6473: .substring(0, 4));
6474: month = Integer.parseInt(timestampValue
6475: .substring(5, 7));
6476: day = Integer.parseInt(timestampValue
6477: .substring(8, 10));
6478: hour = 0;
6479: minutes = 0;
6480: } else {
6481: year = Integer.parseInt(timestampValue
6482: .substring(0, 2));
6483:
6484: if (year <= 69) {
6485: year = (year + 100);
6486: }
6487:
6488: month = Integer.parseInt(timestampValue
6489: .substring(2, 4));
6490: day = Integer.parseInt(timestampValue
6491: .substring(4, 6));
6492: hour = Integer.parseInt(timestampValue
6493: .substring(6, 8));
6494: minutes = Integer.parseInt(timestampValue
6495: .substring(8, 10));
6496:
6497: year += 1900; // two-digit year
6498: }
6499:
6500: return TimeUtil.changeTimezone(this .connection,
6501: sessionCalendar, targetCalendar,
6502: fastTimestampCreate(sessionCalendar,
6503: year, month, day, hour,
6504: minutes, 0, 0), this .connection
6505: .getServerTimezoneTZ(), tz,
6506: rollForward);
6507: }
6508:
6509: case 8: {
6510: if (timestampValue.indexOf(":") != -1) {
6511: int hour = Integer.parseInt(timestampValue
6512: .substring(0, 2));
6513: int minutes = Integer
6514: .parseInt(timestampValue.substring(
6515: 3, 5));
6516: int seconds = Integer
6517: .parseInt(timestampValue.substring(
6518: 6, 8));
6519:
6520: return TimeUtil.changeTimezone(
6521: this .connection, sessionCalendar,
6522: targetCalendar,
6523: fastTimestampCreate(
6524: sessionCalendar, 1970, 1,
6525: 1, hour, minutes, seconds,
6526: 0), this .connection
6527: .getServerTimezoneTZ(), tz,
6528: rollForward);
6529:
6530: }
6531:
6532: int year = Integer.parseInt(timestampValue
6533: .substring(0, 4));
6534: int month = Integer.parseInt(timestampValue
6535: .substring(4, 6));
6536: int day = Integer.parseInt(timestampValue
6537: .substring(6, 8));
6538:
6539: return TimeUtil.changeTimezone(this .connection,
6540: sessionCalendar, targetCalendar,
6541: fastTimestampCreate(sessionCalendar,
6542: year - 1900, month - 1, day, 0,
6543: 0, 0, 0), this .connection
6544: .getServerTimezoneTZ(), tz,
6545: rollForward);
6546: }
6547:
6548: case 6: {
6549: int year = Integer.parseInt(timestampValue
6550: .substring(0, 2));
6551:
6552: if (year <= 69) {
6553: year = (year + 100);
6554: }
6555:
6556: int month = Integer.parseInt(timestampValue
6557: .substring(2, 4));
6558: int day = Integer.parseInt(timestampValue
6559: .substring(4, 6));
6560:
6561: return TimeUtil.changeTimezone(this .connection,
6562: sessionCalendar, targetCalendar,
6563: fastTimestampCreate(sessionCalendar,
6564: year + 1900, month, day, 0, 0,
6565: 0, 0), this .connection
6566: .getServerTimezoneTZ(), tz,
6567: rollForward);
6568: }
6569:
6570: case 4: {
6571: int year = Integer.parseInt(timestampValue
6572: .substring(0, 2));
6573:
6574: if (year <= 69) {
6575: year = (year + 100);
6576: }
6577:
6578: int month = Integer.parseInt(timestampValue
6579: .substring(2, 4));
6580:
6581: return TimeUtil.changeTimezone(this .connection,
6582: sessionCalendar, targetCalendar,
6583: fastTimestampCreate(sessionCalendar,
6584: year + 1900, month, 1, 0, 0, 0,
6585: 0), this .connection
6586: .getServerTimezoneTZ(), tz,
6587: rollForward);
6588: }
6589:
6590: case 2: {
6591: int year = Integer.parseInt(timestampValue
6592: .substring(0, 2));
6593:
6594: if (year <= 69) {
6595: year = (year + 100);
6596: }
6597:
6598: return TimeUtil.changeTimezone(this .connection,
6599: sessionCalendar, targetCalendar,
6600: fastTimestampCreate(null, year + 1900,
6601: 1, 1, 0, 0, 0, 0),
6602: this .connection.getServerTimezoneTZ(),
6603: tz, rollForward);
6604: }
6605:
6606: default:
6607: throw new java.sql.SQLException(
6608: "Bad format for Timestamp '"
6609: + timestampValue
6610: + "' in column " + columnIndex
6611: + ".",
6612: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6613: }
6614: }
6615: }
6616: } catch (Exception e) {
6617: throw new java.sql.SQLException("Cannot convert value '"
6618: + timestampValue + "' from column " + columnIndex
6619: + " to TIMESTAMP.",
6620: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6621: }
6622:
6623: }
6624:
6625: private Timestamp getTimestampFromBytes(int columnIndex,
6626: Calendar targetCalendar, byte[] timestampAsBytes,
6627: TimeZone tz, boolean rollForward)
6628: throws java.sql.SQLException {
6629: checkColumnBounds(columnIndex);
6630:
6631: try {
6632: this .wasNullFlag = false;
6633:
6634: if (timestampAsBytes == null) {
6635: this .wasNullFlag = true;
6636:
6637: return null;
6638: }
6639:
6640: int length = timestampAsBytes.length;
6641:
6642: Calendar sessionCalendar = this .connection
6643: .getUseJDBCCompliantTimezoneShift() ? this .connection
6644: .getUtcCalendar()
6645: : getCalendarInstanceForSessionOrNew();
6646:
6647: synchronized (sessionCalendar) {
6648: boolean allZeroTimestamp = true;
6649:
6650: boolean onlyTimePresent = StringUtils.indexOf(
6651: timestampAsBytes, ':') != -1;
6652:
6653: for (int i = 0; i < length; i++) {
6654: byte b = timestampAsBytes[i];
6655:
6656: if (b == ' ' || b == '-' || b == '/') {
6657: onlyTimePresent = false;
6658: }
6659:
6660: if (b != '0' && b != ' ' && b != ':' && b != '-'
6661: && b != '/' && b != '.') {
6662: allZeroTimestamp = false;
6663:
6664: break;
6665: }
6666: }
6667:
6668: if (!onlyTimePresent && allZeroTimestamp) {
6669:
6670: if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_CONVERT_TO_NULL
6671: .equals(this .connection
6672: .getZeroDateTimeBehavior())) {
6673: this .wasNullFlag = true;
6674:
6675: return null;
6676: } else if (ConnectionPropertiesImpl.ZERO_DATETIME_BEHAVIOR_EXCEPTION
6677: .equals(this .connection
6678: .getZeroDateTimeBehavior())) {
6679: throw SQLError
6680: .createSQLException(
6681: "Value '"
6682: + timestampAsBytes
6683: + "' can not be represented as java.sql.Timestamp",
6684: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6685: }
6686:
6687: // We're left with the case of 'round' to a date Java _can_
6688: // represent, which is '0001-01-01'.
6689: return fastTimestampCreate(null, 1, 1, 1, 0, 0, 0,
6690: 0);
6691:
6692: } else if (this .fields[columnIndex - 1].getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
6693:
6694: return TimeUtil.changeTimezone(this .connection,
6695: sessionCalendar, targetCalendar,
6696: fastTimestampCreate(sessionCalendar,
6697: StringUtils.getInt(
6698: timestampAsBytes, 0, 4), 1,
6699: 1, 0, 0, 0, 0), this .connection
6700: .getServerTimezoneTZ(), tz,
6701: rollForward);
6702:
6703: } else {
6704: if (timestampAsBytes[length - 1] == '.') {
6705: length--;
6706: }
6707:
6708: // Convert from TIMESTAMP or DATE
6709: switch (length) {
6710: case 26:
6711: case 25:
6712: case 24:
6713: case 23:
6714: case 22:
6715: case 21:
6716: case 20:
6717: case 19: {
6718: int year = StringUtils.getInt(timestampAsBytes,
6719: 0, 4);
6720: int month = StringUtils.getInt(
6721: timestampAsBytes, 5, 7);
6722: int day = StringUtils.getInt(timestampAsBytes,
6723: 8, 10);
6724: int hour = StringUtils.getInt(timestampAsBytes,
6725: 11, 13);
6726: int minutes = StringUtils.getInt(
6727: timestampAsBytes, 14, 16);
6728: int seconds = StringUtils.getInt(
6729: timestampAsBytes, 17, 19);
6730:
6731: int nanos = 0;
6732:
6733: if (length > 19) {
6734: int decimalIndex = StringUtils.lastIndexOf(
6735: timestampAsBytes, '.');
6736:
6737: if (decimalIndex != -1) {
6738: if ((decimalIndex + 2) <= length) {
6739: nanos = StringUtils.getInt(
6740: timestampAsBytes,
6741: decimalIndex + 1, length);
6742: } else {
6743: throw new IllegalArgumentException(); // re-thrown
6744: // further
6745: // down
6746: // with
6747: // a
6748: // much better error message
6749: }
6750: }
6751: }
6752:
6753: return TimeUtil.changeTimezone(this .connection,
6754: sessionCalendar, targetCalendar,
6755: fastTimestampCreate(sessionCalendar,
6756: year, month, day, hour,
6757: minutes, seconds, nanos),
6758: this .connection.getServerTimezoneTZ(),
6759: tz, rollForward);
6760: }
6761:
6762: case 14: {
6763: int year = StringUtils.getInt(timestampAsBytes,
6764: 0, 4);
6765: int month = StringUtils.getInt(
6766: timestampAsBytes, 4, 6);
6767: int day = StringUtils.getInt(timestampAsBytes,
6768: 6, 8);
6769: int hour = StringUtils.getInt(timestampAsBytes,
6770: 8, 10);
6771: int minutes = StringUtils.getInt(
6772: timestampAsBytes, 10, 12);
6773: int seconds = StringUtils.getInt(
6774: timestampAsBytes, 12, 14);
6775:
6776: return TimeUtil.changeTimezone(this .connection,
6777: sessionCalendar, targetCalendar,
6778: fastTimestampCreate(sessionCalendar,
6779: year, month, day, hour,
6780: minutes, seconds, 0),
6781: this .connection.getServerTimezoneTZ(),
6782: tz, rollForward);
6783: }
6784:
6785: case 12: {
6786: int year = StringUtils.getInt(timestampAsBytes,
6787: 0, 2);
6788:
6789: if (year <= 69) {
6790: year = (year + 100);
6791: }
6792:
6793: int month = StringUtils.getInt(
6794: timestampAsBytes, 2, 4);
6795: int day = StringUtils.getInt(timestampAsBytes,
6796: 4, 6);
6797: int hour = StringUtils.getInt(timestampAsBytes,
6798: 6, 8);
6799: int minutes = StringUtils.getInt(
6800: timestampAsBytes, 8, 10);
6801: int seconds = StringUtils.getInt(
6802: timestampAsBytes, 10, 12);
6803:
6804: return TimeUtil.changeTimezone(this .connection,
6805: sessionCalendar, targetCalendar,
6806: fastTimestampCreate(sessionCalendar,
6807: year + 1900, month, day, hour,
6808: minutes, seconds, 0),
6809: this .connection.getServerTimezoneTZ(),
6810: tz, rollForward);
6811: }
6812:
6813: case 10: {
6814: int year;
6815: int month;
6816: int day;
6817: int hour;
6818: int minutes;
6819:
6820: if ((this .fields[columnIndex - 1]
6821: .getMysqlType() == MysqlDefs.FIELD_TYPE_DATE)
6822: || (StringUtils.indexOf(
6823: timestampAsBytes, '-') != -1)) {
6824: year = StringUtils.getInt(timestampAsBytes,
6825: 0, 4);
6826: month = StringUtils.getInt(
6827: timestampAsBytes, 5, 7);
6828: day = StringUtils.getInt(timestampAsBytes,
6829: 8, 10);
6830: hour = 0;
6831: minutes = 0;
6832: } else {
6833: year = StringUtils.getInt(timestampAsBytes,
6834: 0, 2);
6835:
6836: if (year <= 69) {
6837: year = (year + 100);
6838: }
6839:
6840: month = StringUtils.getInt(
6841: timestampAsBytes, 2, 4);
6842: day = StringUtils.getInt(timestampAsBytes,
6843: 4, 6);
6844: hour = StringUtils.getInt(timestampAsBytes,
6845: 6, 8);
6846: minutes = StringUtils.getInt(
6847: timestampAsBytes, 8, 10);
6848:
6849: year += 1900; // two-digit year
6850: }
6851:
6852: return TimeUtil.changeTimezone(this .connection,
6853: sessionCalendar, targetCalendar,
6854: fastTimestampCreate(sessionCalendar,
6855: year, month, day, hour,
6856: minutes, 0, 0), this .connection
6857: .getServerTimezoneTZ(), tz,
6858: rollForward);
6859: }
6860:
6861: case 8: {
6862: if (StringUtils.indexOf(timestampAsBytes, ':') != -1) {
6863: int hour = StringUtils.getInt(
6864: timestampAsBytes, 0, 2);
6865: int minutes = StringUtils.getInt(
6866: timestampAsBytes, 3, 5);
6867: int seconds = StringUtils.getInt(
6868: timestampAsBytes, 6, 8);
6869:
6870: return TimeUtil.changeTimezone(
6871: this .connection, sessionCalendar,
6872: targetCalendar,
6873: fastTimestampCreate(
6874: sessionCalendar, 1970, 1,
6875: 1, hour, minutes, seconds,
6876: 0), this .connection
6877: .getServerTimezoneTZ(), tz,
6878: rollForward);
6879:
6880: }
6881:
6882: int year = StringUtils.getInt(timestampAsBytes,
6883: 0, 4);
6884: int month = StringUtils.getInt(
6885: timestampAsBytes, 4, 6);
6886: int day = StringUtils.getInt(timestampAsBytes,
6887: 6, 8);
6888:
6889: return TimeUtil.changeTimezone(this .connection,
6890: sessionCalendar, targetCalendar,
6891: fastTimestampCreate(sessionCalendar,
6892: year - 1900, month - 1, day, 0,
6893: 0, 0, 0), this .connection
6894: .getServerTimezoneTZ(), tz,
6895: rollForward);
6896: }
6897:
6898: case 6: {
6899: int year = StringUtils.getInt(timestampAsBytes,
6900: 0, 2);
6901:
6902: if (year <= 69) {
6903: year = (year + 100);
6904: }
6905:
6906: int month = StringUtils.getInt(
6907: timestampAsBytes, 2, 4);
6908: int day = StringUtils.getInt(timestampAsBytes,
6909: 4, 6);
6910:
6911: return TimeUtil.changeTimezone(this .connection,
6912: sessionCalendar, targetCalendar,
6913: fastTimestampCreate(sessionCalendar,
6914: year + 1900, month, day, 0, 0,
6915: 0, 0), this .connection
6916: .getServerTimezoneTZ(), tz,
6917: rollForward);
6918: }
6919:
6920: case 4: {
6921: int year = StringUtils.getInt(timestampAsBytes,
6922: 0, 2);
6923:
6924: if (year <= 69) {
6925: year = (year + 100);
6926: }
6927:
6928: int month = StringUtils.getInt(
6929: timestampAsBytes, 2, 4);
6930:
6931: return TimeUtil.changeTimezone(this .connection,
6932: sessionCalendar, targetCalendar,
6933: fastTimestampCreate(sessionCalendar,
6934: year + 1900, month, 1, 0, 0, 0,
6935: 0), this .connection
6936: .getServerTimezoneTZ(), tz,
6937: rollForward);
6938: }
6939:
6940: case 2: {
6941: int year = StringUtils.getInt(timestampAsBytes,
6942: 0, 2);
6943:
6944: if (year <= 69) {
6945: year = (year + 100);
6946: }
6947:
6948: return TimeUtil.changeTimezone(this .connection,
6949: sessionCalendar, targetCalendar,
6950: fastTimestampCreate(null, year + 1900,
6951: 1, 1, 0, 0, 0, 0),
6952: this .connection.getServerTimezoneTZ(),
6953: tz, rollForward);
6954: }
6955:
6956: default:
6957: throw new java.sql.SQLException(
6958: "Bad format for Timestamp '"
6959: + new String(timestampAsBytes)
6960: + "' in column " + columnIndex
6961: + ".",
6962: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6963: }
6964: }
6965: }
6966: } catch (Exception e) {
6967: throw new java.sql.SQLException("Cannot convert value '"
6968: + new String(timestampAsBytes) + "' from column "
6969: + columnIndex + " to TIMESTAMP.",
6970: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
6971: }
6972: }
6973:
6974: /**
6975: * Get the value of a column in the current row as a java.sql.Timestamp
6976: * object in the given timezone
6977: *
6978: * @param columnIndex
6979: * the first column is 1, the second is 2...
6980: * @param tz
6981: * the timezone to use
6982: *
6983: * @return the column value; null if SQL NULL
6984: *
6985: * @exception java.sql.SQLException
6986: * if a database access error occurs
6987: */
6988: private Timestamp getTimestampInternal(int columnIndex,
6989: Calendar targetCalendar, TimeZone tz, boolean rollForward)
6990: throws java.sql.SQLException {
6991: if (this .isBinaryEncoded) {
6992: return getNativeTimestamp(columnIndex, targetCalendar, tz,
6993: rollForward);
6994: }
6995:
6996: Timestamp tsVal = null;
6997:
6998: if (!this .useFastDateParsing) {
6999: String timestampValue = getStringInternal(columnIndex,
7000: false);
7001:
7002: tsVal = getTimestampFromString(columnIndex, targetCalendar,
7003: timestampValue, tz, rollForward);
7004: } else {
7005: tsVal = this .this Row.getTimestampFast(columnIndex - 1,
7006: targetCalendar, tz, rollForward, this .connection,
7007: this );
7008: }
7009:
7010: if (tsVal == null) {
7011: this .wasNullFlag = true;
7012: } else {
7013: this .wasNullFlag = false;
7014: }
7015:
7016: return tsVal;
7017: }
7018:
7019: /**
7020: * JDBC 2.0 Return the type of this result set. The type is determined based
7021: * on the statement that created the result set.
7022: *
7023: * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or
7024: * TYPE_SCROLL_SENSITIVE
7025: *
7026: * @exception SQLException
7027: * if a database-access error occurs
7028: */
7029: public int getType() throws SQLException {
7030: return this .resultSetType;
7031: }
7032:
7033: /**
7034: * A column value can also be retrieved as a stream of Unicode characters.
7035: * We implement this as a binary stream.
7036: *
7037: * @param columnIndex
7038: * the first column is 1, the second is 2...
7039: *
7040: * @return a Java InputStream that delivers the database column value as a
7041: * stream of two byte Unicode characters. If the value is SQL NULL,
7042: * then the result is null
7043: *
7044: * @exception SQLException
7045: * if a database access error occurs
7046: *
7047: * @see getAsciiStream
7048: * @see getBinaryStream
7049: * @deprecated
7050: */
7051: public InputStream getUnicodeStream(int columnIndex)
7052: throws SQLException {
7053: if (!this .isBinaryEncoded) {
7054: checkRowPos();
7055:
7056: return getBinaryStream(columnIndex);
7057: }
7058:
7059: return getNativeBinaryStream(columnIndex);
7060: }
7061:
7062: /**
7063: * DOCUMENT ME!
7064: *
7065: * @param columnName
7066: * DOCUMENT ME!
7067: *
7068: * @return DOCUMENT ME!
7069: *
7070: * @throws SQLException
7071: * DOCUMENT ME!
7072: *
7073: * @deprecated
7074: */
7075: public InputStream getUnicodeStream(String columnName)
7076: throws SQLException {
7077: return getUnicodeStream(findColumn(columnName));
7078: }
7079:
7080: public long getUpdateCount() {
7081: return this .updateCount;
7082: }
7083:
7084: public long getUpdateID() {
7085: return this .updateId;
7086: }
7087:
7088: /**
7089: * @see ResultSetInternalMethods#getURL(int)
7090: */
7091: public URL getURL(int colIndex) throws SQLException {
7092: String val = getString(colIndex);
7093:
7094: if (val == null) {
7095: return null;
7096: }
7097:
7098: try {
7099: return new URL(val);
7100: } catch (MalformedURLException mfe) {
7101: throw SQLError.createSQLException(Messages
7102: .getString("ResultSet.Malformed_URL____104")
7103: + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
7104: }
7105: }
7106:
7107: /**
7108: * @see ResultSetInternalMethods#getURL(String)
7109: */
7110: public URL getURL(String colName) throws SQLException {
7111: String val = getString(colName);
7112:
7113: if (val == null) {
7114: return null;
7115: }
7116:
7117: try {
7118: return new URL(val);
7119: } catch (MalformedURLException mfe) {
7120: throw SQLError.createSQLException(Messages
7121: .getString("ResultSet.Malformed_URL____107")
7122: + val + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
7123: }
7124: }
7125:
7126: /**
7127: * The first warning reported by calls on this ResultSet is returned.
7128: * Subsequent ResultSet warnings will be chained to this
7129: * java.sql.SQLWarning.
7130: *
7131: * <p>
7132: * The warning chain is automatically cleared each time a new row is read.
7133: * </p>
7134: *
7135: * <p>
7136: * <B>Note:</B> This warning chain only covers warnings caused by ResultSet
7137: * methods. Any warnings caused by statement methods (such as reading OUT
7138: * parameters) will be chained on the Statement object.
7139: * </p>
7140: *
7141: * @return the first java.sql.SQLWarning or null;
7142: *
7143: * @exception SQLException
7144: * if a database access error occurs.
7145: */
7146: public java.sql.SQLWarning getWarnings() throws SQLException {
7147: return this .warningChain;
7148: }
7149:
7150: /**
7151: * JDBC 2.0 Insert the contents of the insert row into the result set and
7152: * the database. Must be on the insert row when this method is called.
7153: *
7154: * @exception SQLException
7155: * if a database-access error occurs, if called when not on
7156: * the insert row, or if all non-nullable columns in the
7157: * insert row have not been given a value
7158: * @throws NotUpdatable
7159: * DOCUMENT ME!
7160: */
7161: public void insertRow() throws SQLException {
7162: throw new NotUpdatable();
7163: }
7164:
7165: /**
7166: * JDBC 2.0
7167: *
7168: * <p>
7169: * Determine if the cursor is after the last row in the result set.
7170: * </p>
7171: *
7172: * @return true if after the last row, false otherwise. Returns false when
7173: * the result set contains no rows.
7174: *
7175: * @exception SQLException
7176: * if a database-access error occurs.
7177: */
7178: public boolean isAfterLast() throws SQLException {
7179: checkClosed();
7180:
7181: boolean b = this .rowData.isAfterLast();
7182:
7183: return b;
7184: }
7185:
7186: /**
7187: * JDBC 2.0
7188: *
7189: * <p>
7190: * Determine if the cursor is before the first row in the result set.
7191: * </p>
7192: *
7193: * @return true if before the first row, false otherwise. Returns false when
7194: * the result set contains no rows.
7195: *
7196: * @exception SQLException
7197: * if a database-access error occurs.
7198: */
7199: public boolean isBeforeFirst() throws SQLException {
7200: checkClosed();
7201:
7202: return this .rowData.isBeforeFirst();
7203: }
7204:
7205: /**
7206: * JDBC 2.0
7207: *
7208: * <p>
7209: * Determine if the cursor is on the first row of the result set.
7210: * </p>
7211: *
7212: * @return true if on the first row, false otherwise.
7213: *
7214: * @exception SQLException
7215: * if a database-access error occurs.
7216: */
7217: public boolean isFirst() throws SQLException {
7218: checkClosed();
7219:
7220: return this .rowData.isFirst();
7221: }
7222:
7223: /**
7224: * JDBC 2.0
7225: *
7226: * <p>
7227: * Determine if the cursor is on the last row of the result set. Note:
7228: * Calling isLast() may be expensive since the JDBC driver might need to
7229: * fetch ahead one row in order to determine whether the current row is the
7230: * last row in the result set.
7231: * </p>
7232: *
7233: * @return true if on the last row, false otherwise.
7234: *
7235: * @exception SQLException
7236: * if a database-access error occurs.
7237: */
7238: public boolean isLast() throws SQLException {
7239: checkClosed();
7240:
7241: return this .rowData.isLast();
7242: }
7243:
7244: /**
7245: * @param string
7246: * @param mysqlType
7247: * @param s
7248: */
7249: private void issueConversionViaParsingWarning(String methodName,
7250: int columnIndex, Object value, Field fieldInfo,
7251: int[] typesWithNoParseConversion) throws SQLException {
7252:
7253: StringBuffer originalQueryBuf = new StringBuffer();
7254:
7255: if (this .owningStatement != null
7256: && this .owningStatement instanceof com.mysql.jdbc.PreparedStatement) {
7257: originalQueryBuf
7258: .append(Messages
7259: .getString("ResultSet.CostlyConversionCreatedFromQuery"));
7260: originalQueryBuf
7261: .append(((com.mysql.jdbc.PreparedStatement) this .owningStatement).originalSql);
7262: originalQueryBuf.append("\n\n");
7263: } else {
7264: originalQueryBuf.append(".");
7265: }
7266:
7267: StringBuffer convertibleTypesBuf = new StringBuffer();
7268:
7269: for (int i = 0; i < typesWithNoParseConversion.length; i++) {
7270: convertibleTypesBuf.append(MysqlDefs
7271: .typeToName(typesWithNoParseConversion[i]));
7272: convertibleTypesBuf.append("\n");
7273: }
7274:
7275: String message = Messages
7276: .getString(
7277: "ResultSet.CostlyConversion",
7278: new Object[] {
7279: methodName,
7280: new Integer(columnIndex + 1),
7281: fieldInfo.getOriginalName(),
7282: fieldInfo.getOriginalTableName(),
7283: originalQueryBuf.toString(),
7284: value != null ? value.getClass()
7285: .getName()
7286: : ResultSetMetaData
7287: .getClassNameForJavaType(
7288: fieldInfo
7289: .getSQLType(),
7290: fieldInfo
7291: .isUnsigned(),
7292: fieldInfo
7293: .getMysqlType(),
7294: fieldInfo
7295: .isBinary()
7296: || fieldInfo
7297: .isBlob(),
7298: fieldInfo
7299: .isOpaqueBinary()),
7300: MysqlDefs.typeToName(fieldInfo
7301: .getMysqlType()),
7302: convertibleTypesBuf.toString() });
7303:
7304: this .eventSink.consumeEvent(new ProfilerEvent(
7305: ProfilerEvent.TYPE_WARN, "",
7306: (this .owningStatement == null) ? "N/A"
7307: : this .owningStatement.currentCatalog,
7308: this .connectionId,
7309: (this .owningStatement == null) ? (-1)
7310: : this .owningStatement.getId(), this .resultId,
7311: System.currentTimeMillis(), 0, Constants.MILLIS_I18N,
7312: null, this .pointOfOrigin, message));
7313:
7314: }
7315:
7316: /**
7317: * JDBC 2.0
7318: *
7319: * <p>
7320: * Moves to the last row in the result set.
7321: * </p>
7322: *
7323: * @return true if on a valid row, false if no rows in the result set.
7324: *
7325: * @exception SQLException
7326: * if a database-access error occurs, or result set type is
7327: * TYPE_FORWARD_ONLY.
7328: */
7329: public boolean last() throws SQLException {
7330: checkClosed();
7331:
7332: if (this .rowData.size() == 0) {
7333: return false;
7334: }
7335:
7336: if (this .onInsertRow) {
7337: this .onInsertRow = false;
7338: }
7339:
7340: if (this .doingUpdates) {
7341: this .doingUpdates = false;
7342: }
7343:
7344: if (this .this Row != null) {
7345: this .this Row.closeOpenStreams();
7346: }
7347:
7348: this .rowData.beforeLast();
7349: this .this Row = this .rowData.next();
7350:
7351: return true;
7352: }
7353:
7354: // /////////////////////////////////////////
7355: //
7356: // These number conversion routines save
7357: // a ton of "new()s", especially for the heavily
7358: // used getInt() and getDouble() methods
7359: //
7360: // /////////////////////////////////////////
7361:
7362: /**
7363: * JDBC 2.0 Move the cursor to the remembered cursor position, usually the
7364: * current row. Has no effect unless the cursor is on the insert row.
7365: *
7366: * @exception SQLException
7367: * if a database-access error occurs, or the result set is
7368: * not updatable
7369: * @throws NotUpdatable
7370: * DOCUMENT ME!
7371: */
7372: public void moveToCurrentRow() throws SQLException {
7373: throw new NotUpdatable();
7374: }
7375:
7376: /**
7377: * JDBC 2.0 Move to the insert row. The current cursor position is
7378: * remembered while the cursor is positioned on the insert row. The insert
7379: * row is a special row associated with an updatable result set. It is
7380: * essentially a buffer where a new row may be constructed by calling the
7381: * updateXXX() methods prior to inserting the row into the result set. Only
7382: * the updateXXX(), getXXX(), and insertRow() methods may be called when the
7383: * cursor is on the insert row. All of the columns in a result set must be
7384: * given a value each time this method is called before calling insertRow().
7385: * UpdateXXX()must be called before getXXX() on a column.
7386: *
7387: * @exception SQLException
7388: * if a database-access error occurs, or the result set is
7389: * not updatable
7390: * @throws NotUpdatable
7391: * DOCUMENT ME!
7392: */
7393: public void moveToInsertRow() throws SQLException {
7394: throw new NotUpdatable();
7395: }
7396:
7397: /**
7398: * A ResultSet is initially positioned before its first row, the first call
7399: * to next makes the first row the current row; the second call makes the
7400: * second row the current row, etc.
7401: *
7402: * <p>
7403: * If an input stream from the previous row is open, it is implicitly
7404: * closed. The ResultSet's warning chain is cleared when a new row is read
7405: * </p>
7406: *
7407: * @return true if the new current is valid; false if there are no more rows
7408: *
7409: * @exception SQLException
7410: * if a database access error occurs
7411: */
7412: public boolean next() throws SQLException {
7413: checkClosed();
7414:
7415: if (this .onInsertRow) {
7416: this .onInsertRow = false;
7417: }
7418:
7419: if (this .doingUpdates) {
7420: this .doingUpdates = false;
7421: }
7422:
7423: boolean b;
7424:
7425: if (!reallyResult()) {
7426: throw SQLError
7427: .createSQLException(
7428: Messages
7429: .getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"),
7430: SQLError.SQL_STATE_GENERAL_ERROR); //$NON-NLS-1$
7431: }
7432:
7433: if (this .this Row != null) {
7434: this .this Row.closeOpenStreams();
7435: }
7436:
7437: if (this .rowData.size() == 0) {
7438: b = false;
7439: } else {
7440: this .this Row = this .rowData.next();
7441:
7442: if (this .this Row == null) {
7443: b = false;
7444: } else {
7445: clearWarnings();
7446:
7447: b = true;
7448:
7449: }
7450: }
7451:
7452: return b;
7453: }
7454:
7455: private int parseIntAsDouble(int columnIndex, String val)
7456: throws NumberFormatException, SQLException {
7457: if (val == null) {
7458: return 0;
7459: }
7460:
7461: double valueAsDouble = Double.parseDouble(val);
7462:
7463: if (this .connection.getJdbcCompliantTruncationForReads()) {
7464: if (valueAsDouble < Integer.MIN_VALUE
7465: || valueAsDouble > Integer.MAX_VALUE) {
7466: throwRangeException(String.valueOf(valueAsDouble),
7467: columnIndex, Types.INTEGER);
7468: }
7469: }
7470:
7471: return (int) valueAsDouble;
7472: }
7473:
7474: private int getIntWithOverflowCheck(int columnIndex)
7475: throws SQLException {
7476: int intValue = this .this Row.getInt(columnIndex);
7477:
7478: checkForIntegerTruncation(
7479: columnIndex + 1 /* only reported in errors */, null,
7480: this .this Row.getString(columnIndex,
7481: this .fields[columnIndex].getCharacterSet(),
7482: this .connection), intValue);
7483:
7484: return intValue;
7485: }
7486:
7487: private void checkForIntegerTruncation(int columnIndex,
7488: byte[] valueAsBytes, String valueAsString, int intValue)
7489: throws SQLException {
7490: if (this .connection.getJdbcCompliantTruncationForReads()) {
7491: if (intValue == Integer.MIN_VALUE
7492: || intValue == Integer.MAX_VALUE) {
7493: long valueAsLong = Long
7494: .parseLong(valueAsString == null ? new String(
7495: valueAsBytes) : valueAsString);
7496:
7497: if (valueAsLong < Integer.MIN_VALUE
7498: || valueAsLong > Integer.MAX_VALUE) {
7499: throwRangeException(
7500: valueAsString == null ? new String(
7501: valueAsBytes) : valueAsString,
7502: columnIndex, Types.INTEGER);
7503: }
7504: }
7505: }
7506: }
7507:
7508: private long parseLongAsDouble(int columnIndex, String val)
7509: throws NumberFormatException, SQLException {
7510: if (val == null) {
7511: return 0;
7512: }
7513:
7514: double valueAsDouble = Double.parseDouble(val);
7515:
7516: if (this .connection.getJdbcCompliantTruncationForReads()) {
7517: if (valueAsDouble < Long.MIN_VALUE
7518: || valueAsDouble > Long.MAX_VALUE) {
7519: throwRangeException(val, columnIndex, Types.BIGINT);
7520: }
7521: }
7522:
7523: return (long) valueAsDouble;
7524: }
7525:
7526: private long getLongWithOverflowCheck(int columnIndex,
7527: boolean doOverflowCheck) throws SQLException {
7528: long longValue = this .this Row.getLong(columnIndex);
7529:
7530: if (doOverflowCheck) {
7531: checkForLongTruncation(
7532: columnIndex + 1 /* only reported in errors */,
7533: null, this .this Row.getString(columnIndex,
7534: this .fields[columnIndex].getCharacterSet(),
7535: this .connection), longValue);
7536: }
7537:
7538: return longValue;
7539: }
7540:
7541: private long parseLongWithOverflowCheck(int columnIndex,
7542: byte[] valueAsBytes, String valueAsString, boolean doCheck)
7543: throws NumberFormatException, SQLException {
7544:
7545: long longValue = 0;
7546:
7547: if (valueAsBytes == null && valueAsString == null) {
7548: return 0;
7549: }
7550:
7551: if (valueAsBytes != null) {
7552: longValue = StringUtils.getLong(valueAsBytes);
7553: } else {
7554: //
7555: // JDK-6 doesn't like trailing whitespace
7556: //
7557: // Note this isn't a performance issue, other
7558: // than the iteration over the string, as String.trim()
7559: // will return a new string only if whitespace is present
7560: //
7561:
7562: valueAsString = valueAsString.trim();
7563:
7564: longValue = Long.parseLong(valueAsString);
7565: }
7566:
7567: if (doCheck
7568: && this .connection.getJdbcCompliantTruncationForReads()) {
7569: checkForLongTruncation(columnIndex, valueAsBytes,
7570: valueAsString, longValue);
7571: }
7572:
7573: return longValue;
7574: }
7575:
7576: private void checkForLongTruncation(int columnIndex,
7577: byte[] valueAsBytes, String valueAsString, long longValue)
7578: throws SQLException {
7579: if (longValue == Long.MIN_VALUE || longValue == Long.MAX_VALUE) {
7580: double valueAsDouble = Double
7581: .parseDouble(valueAsString == null ? new String(
7582: valueAsBytes) : valueAsString);
7583:
7584: if (valueAsDouble < Long.MIN_VALUE
7585: || valueAsDouble > Long.MAX_VALUE) {
7586: throwRangeException(valueAsString == null ? new String(
7587: valueAsBytes) : valueAsString, columnIndex,
7588: Types.BIGINT);
7589: }
7590: }
7591: }
7592:
7593: private short parseShortAsDouble(int columnIndex, String val)
7594: throws NumberFormatException, SQLException {
7595: if (val == null) {
7596: return 0;
7597: }
7598:
7599: double valueAsDouble = Double.parseDouble(val);
7600:
7601: if (this .connection.getJdbcCompliantTruncationForReads()) {
7602: if (valueAsDouble < Short.MIN_VALUE
7603: || valueAsDouble > Short.MAX_VALUE) {
7604: throwRangeException(String.valueOf(valueAsDouble),
7605: columnIndex, Types.SMALLINT);
7606: }
7607: }
7608:
7609: return (short) valueAsDouble;
7610: }
7611:
7612: private short parseShortWithOverflowCheck(int columnIndex,
7613: byte[] valueAsBytes, String valueAsString)
7614: throws NumberFormatException, SQLException {
7615:
7616: short shortValue = 0;
7617:
7618: if (valueAsBytes == null && valueAsString == null) {
7619: return 0;
7620: }
7621:
7622: if (valueAsBytes != null) {
7623: shortValue = StringUtils.getShort(valueAsBytes);
7624: } else {
7625: //
7626: // JDK-6 doesn't like trailing whitespace
7627: //
7628: // Note this isn't a performance issue, other
7629: // than the iteration over the string, as String.trim()
7630: // will return a new string only if whitespace is present
7631: //
7632:
7633: valueAsString = valueAsString.trim();
7634:
7635: shortValue = Short.parseShort(valueAsString);
7636: }
7637:
7638: if (this .connection.getJdbcCompliantTruncationForReads()) {
7639: if (shortValue == Short.MIN_VALUE
7640: || shortValue == Short.MAX_VALUE) {
7641: long valueAsLong = Long
7642: .parseLong(valueAsString == null ? new String(
7643: valueAsBytes) : valueAsString);
7644:
7645: if (valueAsLong < Short.MIN_VALUE
7646: || valueAsLong > Short.MAX_VALUE) {
7647: throwRangeException(
7648: valueAsString == null ? new String(
7649: valueAsBytes) : valueAsString,
7650: columnIndex, Types.SMALLINT);
7651: }
7652: }
7653: }
7654:
7655: return shortValue;
7656: }
7657:
7658: // --------------------------JDBC 2.0-----------------------------------
7659: // ---------------------------------------------------------------------
7660: // Getter's and Setter's
7661: // ---------------------------------------------------------------------
7662:
7663: /**
7664: * The prev method is not part of JDBC, but because of the architecture of
7665: * this driver it is possible to move both forward and backward within the
7666: * result set.
7667: *
7668: * <p>
7669: * If an input stream from the previous row is open, it is implicitly
7670: * closed. The ResultSet's warning chain is cleared when a new row is read
7671: * </p>
7672: *
7673: * @return true if the new current is valid; false if there are no more rows
7674: *
7675: * @exception java.sql.SQLException
7676: * if a database access error occurs
7677: */
7678: public boolean prev() throws java.sql.SQLException {
7679: checkClosed();
7680:
7681: int rowIndex = this .rowData.getCurrentRowNumber();
7682:
7683: if (this .this Row != null) {
7684: this .this Row.closeOpenStreams();
7685: }
7686:
7687: if ((rowIndex - 1) >= 0) {
7688: rowIndex--;
7689: this .rowData.setCurrentRow(rowIndex);
7690: this .this Row = this .rowData.getAt(rowIndex);
7691:
7692: return true;
7693: } else if ((rowIndex - 1) == -1) {
7694: rowIndex--;
7695: this .rowData.setCurrentRow(rowIndex);
7696: this .this Row = null;
7697:
7698: return false;
7699: } else {
7700: return false;
7701: }
7702: }
7703:
7704: /**
7705: * JDBC 2.0
7706: *
7707: * <p>
7708: * Moves to the previous row in the result set.
7709: * </p>
7710: *
7711: * <p>
7712: * Note: previous() is not the same as relative(-1) since it makes sense to
7713: * call previous() when there is no current row.
7714: * </p>
7715: *
7716: * @return true if on a valid row, false if off the result set.
7717: *
7718: * @exception SQLException
7719: * if a database-access error occurs, or result set type is
7720: * TYPE_FORWAR_DONLY.
7721: */
7722: public boolean previous() throws SQLException {
7723: if (this .onInsertRow) {
7724: this .onInsertRow = false;
7725: }
7726:
7727: if (this .doingUpdates) {
7728: this .doingUpdates = false;
7729: }
7730:
7731: return prev();
7732: }
7733:
7734: /**
7735: * Closes this ResultSet and releases resources.
7736: *
7737: * @param calledExplicitly
7738: * was this called by close()?
7739: *
7740: * @throws SQLException
7741: * if an error occurs
7742: */
7743: public void realClose(boolean calledExplicitly) throws SQLException {
7744: if (this .isClosed) {
7745: return;
7746: }
7747:
7748: try {
7749: if (this .useUsageAdvisor) {
7750:
7751: // Report on result set closed by driver instead of application
7752:
7753: if (!calledExplicitly) {
7754: this .eventSink
7755: .consumeEvent(new ProfilerEvent(
7756: ProfilerEvent.TYPE_WARN,
7757: "",
7758: (this .owningStatement == null) ? "N/A"
7759: : this .owningStatement.currentCatalog,
7760: this .connectionId,
7761: (this .owningStatement == null) ? (-1)
7762: : this .owningStatement
7763: .getId(),
7764: this .resultId,
7765: System.currentTimeMillis(),
7766: 0,
7767: Constants.MILLIS_I18N,
7768: null,
7769: this .pointOfOrigin,
7770: Messages
7771: .getString("ResultSet.ResultSet_implicitly_closed_by_driver"))); //$NON-NLS-1$
7772: }
7773:
7774: if (this .rowData instanceof RowDataStatic) {
7775:
7776: // Report on possibly too-large result sets
7777:
7778: if (this .rowData.size() > this .connection
7779: .getResultSetSizeThreshold()) {
7780: this .eventSink
7781: .consumeEvent(new ProfilerEvent(
7782: ProfilerEvent.TYPE_WARN,
7783: "",
7784: (this .owningStatement == null) ? Messages
7785: .getString("ResultSet.N/A_159")
7786: : this .owningStatement.currentCatalog, //$NON-NLS-1$
7787: this .connectionId,
7788: (this .owningStatement == null) ? (-1)
7789: : this .owningStatement
7790: .getId(),
7791: this .resultId,
7792: System.currentTimeMillis(),
7793: 0,
7794: Constants.MILLIS_I18N,
7795: null,
7796: this .pointOfOrigin,
7797: Messages
7798: .getString(
7799: "ResultSet.Too_Large_Result_Set",
7800: new Object[] {
7801: new Integer(
7802: this .rowData
7803: .size()),
7804: new Integer(
7805: this .connection
7806: .getResultSetSizeThreshold()) })));
7807: }
7808:
7809: if (!isLast() && !isAfterLast()
7810: && (this .rowData.size() != 0)) {
7811:
7812: this .eventSink
7813: .consumeEvent(new ProfilerEvent(
7814: ProfilerEvent.TYPE_WARN,
7815: "",
7816: (this .owningStatement == null) ? Messages
7817: .getString("ResultSet.N/A_159")
7818: : this .owningStatement.currentCatalog, //$NON-NLS-1$
7819: this .connectionId,
7820: (this .owningStatement == null) ? (-1)
7821: : this .owningStatement
7822: .getId(),
7823: this .resultId,
7824: System.currentTimeMillis(),
7825: 0,
7826: Constants.MILLIS_I18N,
7827: null,
7828: this .pointOfOrigin,
7829: Messages
7830: .getString(
7831: "ResultSet.Possible_incomplete_traversal_of_result_set", //$NON-NLS-1$
7832: new Object[] {
7833: new Integer(
7834: getRow()),
7835: new Integer(
7836: this .rowData
7837: .size()) })));
7838: }
7839: }
7840:
7841: //
7842: // Report on any columns that were selected but
7843: // not referenced
7844: //
7845:
7846: if (this .columnUsed.length > 0
7847: && !this .rowData.wasEmpty()) {
7848: StringBuffer buf = new StringBuffer(
7849: Messages
7850: .getString("ResultSet.The_following_columns_were_never_referenced")); //$NON-NLS-1$
7851:
7852: boolean issueWarn = false;
7853:
7854: for (int i = 0; i < this .columnUsed.length; i++) {
7855: if (!this .columnUsed[i]) {
7856: if (!issueWarn) {
7857: issueWarn = true;
7858: } else {
7859: buf.append(", ");
7860: }
7861:
7862: buf.append(this .fields[i].getFullName());
7863: }
7864: }
7865:
7866: if (issueWarn) {
7867: this .eventSink
7868: .consumeEvent(new ProfilerEvent(
7869: ProfilerEvent.TYPE_WARN,
7870: "",
7871: (this .owningStatement == null) ? "N/A"
7872: : this .owningStatement.currentCatalog,
7873: this .connectionId,
7874: (this .owningStatement == null) ? (-1)
7875: : this .owningStatement
7876: .getId(), 0,
7877: System.currentTimeMillis(), 0,
7878: Constants.MILLIS_I18N, null,
7879: this .pointOfOrigin, buf
7880: .toString()));
7881: }
7882: }
7883: }
7884: } finally {
7885: SQLException exceptionDuringClose = null;
7886:
7887: if (this .rowData != null) {
7888: try {
7889: this .rowData.close();
7890: } catch (SQLException sqlEx) {
7891: exceptionDuringClose = sqlEx;
7892: }
7893: }
7894:
7895: this .rowData = null;
7896: this .defaultTimeZone = null;
7897: this .fields = null;
7898: this .columnNameToIndex = null;
7899: this .fullColumnNameToIndex = null;
7900: this .eventSink = null;
7901: this .warningChain = null;
7902:
7903: if (!this .retainOwningStatement) {
7904: this .owningStatement = null;
7905: }
7906:
7907: this .catalog = null;
7908: this .serverInfo = null;
7909: this .this Row = null;
7910: this .fastDateCal = null;
7911: this .connection = null;
7912:
7913: this .isClosed = true;
7914:
7915: if (exceptionDuringClose != null) {
7916: throw exceptionDuringClose;
7917: }
7918: }
7919: }
7920:
7921: public boolean reallyResult() {
7922: if (this .rowData != null) {
7923: return true;
7924: }
7925:
7926: return this .reallyResult;
7927: }
7928:
7929: /**
7930: * JDBC 2.0 Refresh the value of the current row with its current value in
7931: * the database. Cannot be called when on the insert row. The refreshRow()
7932: * method provides a way for an application to explicitly tell the JDBC
7933: * driver to refetch a row(s) from the database. An application may want to
7934: * call refreshRow() when caching or prefetching is being done by the JDBC
7935: * driver to fetch the latest value of a row from the database. The JDBC
7936: * driver may actually refresh multiple rows at once if the fetch size is
7937: * greater than one. All values are refetched subject to the transaction
7938: * isolation level and cursor sensitivity. If refreshRow() is called after
7939: * calling updateXXX(), but before calling updateRow() then the updates made
7940: * to the row are lost. Calling refreshRow() frequently will likely slow
7941: * performance.
7942: *
7943: * @exception SQLException
7944: * if a database-access error occurs, or if called when on
7945: * the insert row.
7946: * @throws NotUpdatable
7947: * DOCUMENT ME!
7948: */
7949: public void refreshRow() throws SQLException {
7950: throw new NotUpdatable();
7951: }
7952:
7953: /**
7954: * JDBC 2.0
7955: *
7956: * <p>
7957: * Moves a relative number of rows, either positive or negative. Attempting
7958: * to move beyond the first/last row in the result set positions the cursor
7959: * before/after the the first/last row. Calling relative(0) is valid, but
7960: * does not change the cursor position.
7961: * </p>
7962: *
7963: * <p>
7964: * Note: Calling relative(1) is different than calling next() since is makes
7965: * sense to call next() when there is no current row, for example, when the
7966: * cursor is positioned before the first row or after the last row of the
7967: * result set.
7968: * </p>
7969: *
7970: * @param rows
7971: * the number of relative rows to move the cursor.
7972: *
7973: * @return true if on a row, false otherwise.
7974: *
7975: * @throws SQLException
7976: * if a database-access error occurs, or there is no current
7977: * row, or result set type is TYPE_FORWARD_ONLY.
7978: */
7979: public boolean relative(int rows) throws SQLException {
7980: checkClosed();
7981:
7982: if (this .rowData.size() == 0) {
7983: return false;
7984: }
7985:
7986: if (this .this Row != null) {
7987: this .this Row.closeOpenStreams();
7988: }
7989:
7990: this .rowData.moveRowRelative(rows);
7991: this .this Row = this .rowData.getAt(this .rowData
7992: .getCurrentRowNumber());
7993:
7994: return (!this .rowData.isAfterLast() && !this .rowData
7995: .isBeforeFirst());
7996: }
7997:
7998: /**
7999: * JDBC 2.0 Determine if this row has been deleted. A deleted row may leave
8000: * a visible "hole" in a result set. This method can be used to detect holes
8001: * in a result set. The value returned depends on whether or not the result
8002: * set can detect deletions.
8003: *
8004: * @return true if deleted and deletes are detected
8005: *
8006: * @exception SQLException
8007: * if a database-access error occurs
8008: * @throws NotImplemented
8009: * DOCUMENT ME!
8010: *
8011: * @see DatabaseMetaData#deletesAreDetected
8012: */
8013: public boolean rowDeleted() throws SQLException {
8014: throw new NotImplemented();
8015: }
8016:
8017: /**
8018: * JDBC 2.0 Determine if the current row has been inserted. The value
8019: * returned depends on whether or not the result set can detect visible
8020: * inserts.
8021: *
8022: * @return true if inserted and inserts are detected
8023: *
8024: * @exception SQLException
8025: * if a database-access error occurs
8026: * @throws NotImplemented
8027: * DOCUMENT ME!
8028: *
8029: * @see DatabaseMetaData#insertsAreDetected
8030: */
8031: public boolean rowInserted() throws SQLException {
8032: throw new NotImplemented();
8033: }
8034:
8035: /**
8036: * JDBC 2.0 Determine if the current row has been updated. The value
8037: * returned depends on whether or not the result set can detect updates.
8038: *
8039: * @return true if the row has been visibly updated by the owner or another,
8040: * and updates are detected
8041: *
8042: * @exception SQLException
8043: * if a database-access error occurs
8044: * @throws NotImplemented
8045: * DOCUMENT ME!
8046: *
8047: * @see DatabaseMetaData#updatesAreDetected
8048: */
8049: public boolean rowUpdated() throws SQLException {
8050: throw new NotImplemented();
8051: }
8052:
8053: /**
8054: * Flag that this result set is 'binary' encoded (from a PreparedStatement),
8055: * not stored as strings.
8056: */
8057: protected void setBinaryEncoded() {
8058: this .isBinaryEncoded = true;
8059: }
8060:
8061: private void setDefaultTimeZone(TimeZone defaultTimeZone) {
8062: this .defaultTimeZone = defaultTimeZone;
8063: }
8064:
8065: /**
8066: * JDBC 2.0 Give a hint as to the direction in which the rows in this result
8067: * set will be processed. The initial value is determined by the statement
8068: * that produced the result set. The fetch direction may be changed at any
8069: * time.
8070: *
8071: * @param direction
8072: * the direction to fetch rows in.
8073: *
8074: * @exception SQLException
8075: * if a database-access error occurs, or the result set type
8076: * is TYPE_FORWARD_ONLY and direction is not FETCH_FORWARD.
8077: * MM.MySQL actually ignores this, because it has the whole
8078: * result set anyway, so the direction is immaterial.
8079: */
8080: public void setFetchDirection(int direction) throws SQLException {
8081: if ((direction != FETCH_FORWARD)
8082: && (direction != FETCH_REVERSE)
8083: && (direction != FETCH_UNKNOWN)) {
8084: throw SQLError
8085: .createSQLException(
8086: Messages
8087: .getString("ResultSet.Illegal_value_for_fetch_direction_64"),
8088: SQLError.SQL_STATE_ILLEGAL_ARGUMENT); //$NON-NLS-1$
8089: }
8090:
8091: this .fetchDirection = direction;
8092: }
8093:
8094: /**
8095: * JDBC 2.0 Give the JDBC driver a hint as to the number of rows that should
8096: * be fetched from the database when more rows are needed for this result
8097: * set. If the fetch size specified is zero, then the JDBC driver ignores
8098: * the value, and is free to make its own best guess as to what the fetch
8099: * size should be. The default value is set by the statement that creates
8100: * the result set. The fetch size may be changed at any time.
8101: *
8102: * @param rows
8103: * the number of rows to fetch
8104: *
8105: * @exception SQLException
8106: * if a database-access error occurs, or the condition 0 lteq
8107: * rows lteq this.getMaxRows() is not satisfied. Currently
8108: * ignored by this driver.
8109: */
8110: public void setFetchSize(int rows) throws SQLException {
8111: if (rows < 0) { /* || rows > getMaxRows() */
8112: throw SQLError
8113: .createSQLException(
8114: Messages
8115: .getString("ResultSet.Value_must_be_between_0_and_getMaxRows()_66"), //$NON-NLS-1$
8116: SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
8117: }
8118:
8119: this .fetchSize = rows;
8120: }
8121:
8122: /**
8123: * Sets the first character of the query that this result set was created
8124: * from.
8125: *
8126: * @param c
8127: * the first character of the query...uppercased
8128: */
8129: public void setFirstCharOfQuery(char c) {
8130: this .firstCharOfQuery = c;
8131: }
8132:
8133: /**
8134: * DOCUMENT ME!
8135: *
8136: * @param nextResultSet
8137: * Sets the next result set in the result set chain for multiple
8138: * result sets.
8139: */
8140: protected void setNextResultSet(
8141: ResultSetInternalMethods nextResultSet) {
8142: this .nextResultSet = nextResultSet;
8143: }
8144:
8145: public void setOwningStatement(
8146: com.mysql.jdbc.StatementImpl owningStatement) {
8147: this .owningStatement = owningStatement;
8148: }
8149:
8150: /**
8151: * Sets the concurrency (JDBC2)
8152: *
8153: * @param concurrencyFlag
8154: * CONCUR_UPDATABLE or CONCUR_READONLY
8155: */
8156: protected void setResultSetConcurrency(int concurrencyFlag) {
8157: this .resultSetConcurrency = concurrencyFlag;
8158: }
8159:
8160: /**
8161: * Sets the result set type for (JDBC2)
8162: *
8163: * @param typeFlag
8164: * SCROLL_SENSITIVE or SCROLL_INSENSITIVE (we only support
8165: * SCROLL_INSENSITIVE)
8166: */
8167: protected void setResultSetType(int typeFlag) {
8168: this .resultSetType = typeFlag;
8169: }
8170:
8171: /**
8172: * Sets server info (if any)
8173: *
8174: * @param info
8175: * the server info message
8176: */
8177: protected void setServerInfo(String info) {
8178: this .serverInfo = info;
8179: }
8180:
8181: public void setStatementUsedForFetchingRows(PreparedStatement stmt) {
8182: this .statementUsedForFetchingRows = stmt;
8183: }
8184:
8185: /**
8186: * @param wrapperStatement
8187: * The wrapperStatement to set.
8188: */
8189: public void setWrapperStatement(java.sql.Statement wrapperStatement) {
8190: this .wrapperStatement = wrapperStatement;
8191: }
8192:
8193: private void throwRangeException(String valueAsString,
8194: int columnIndex, int jdbcType) throws SQLException {
8195: String datatype = null;
8196:
8197: switch (jdbcType) {
8198: case Types.TINYINT:
8199: datatype = "TINYINT";
8200: break;
8201: case Types.SMALLINT:
8202: datatype = "SMALLINT";
8203: break;
8204: case Types.INTEGER:
8205: datatype = "INTEGER";
8206: break;
8207: case Types.BIGINT:
8208: datatype = "BIGINT";
8209: break;
8210: case Types.REAL:
8211: datatype = "REAL";
8212: break;
8213: case Types.FLOAT:
8214: datatype = "FLOAT";
8215: break;
8216: case Types.DOUBLE:
8217: datatype = "DOUBLE";
8218: break;
8219: case Types.DECIMAL:
8220: datatype = "DECIMAL";
8221: break;
8222: default:
8223: datatype = " (JDBC type '" + jdbcType + "')";
8224: }
8225:
8226: throw SQLError.createSQLException("'" + valueAsString
8227: + "' in column '" + columnIndex
8228: + "' is outside valid range for the datatype "
8229: + datatype + ".",
8230: SQLError.SQL_STATE_NUMERIC_VALUE_OUT_OF_RANGE);
8231: }
8232:
8233: /**
8234: * DOCUMENT ME!
8235: *
8236: * @return DOCUMENT ME!
8237: */
8238: public String toString() {
8239: if (this .reallyResult) {
8240: return super .toString();
8241: }
8242:
8243: return "Result set representing update count of "
8244: + this .updateCount;
8245: }
8246:
8247: /**
8248: * @see ResultSetInternalMethods#updateArray(int, Array)
8249: */
8250: public void updateArray(int arg0, Array arg1) throws SQLException {
8251: throw new NotImplemented();
8252: }
8253:
8254: /**
8255: * @see ResultSetInternalMethods#updateArray(String, Array)
8256: */
8257: public void updateArray(String arg0, Array arg1)
8258: throws SQLException {
8259: throw new NotImplemented();
8260: }
8261:
8262: /**
8263: * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
8264: * methods are used to update column values in the current row, or the
8265: * insert row. The updateXXX() methods do not update the underlying
8266: * database, instead the updateRow() or insertRow() methods are called to
8267: * update the database.
8268: *
8269: * @param columnIndex
8270: * the first column is 1, the second is 2, ...
8271: * @param x
8272: * the new column value
8273: * @param length
8274: * the length of the stream
8275: *
8276: * @exception SQLException
8277: * if a database-access error occurs
8278: * @throws NotUpdatable
8279: * DOCUMENT ME!
8280: */
8281: public void updateAsciiStream(int columnIndex,
8282: java.io.InputStream x, int length) throws SQLException {
8283: throw new NotUpdatable();
8284: }
8285:
8286: /**
8287: * JDBC 2.0 Update a column with an ascii stream value. The updateXXX()
8288: * methods are used to update column values in the current row, or the
8289: * insert row. The updateXXX() methods do not update the underlying
8290: * database, instead the updateRow() or insertRow() methods are called to
8291: * update the database.
8292: *
8293: * @param columnName
8294: * the name of the column
8295: * @param x
8296: * the new column value
8297: * @param length
8298: * of the stream
8299: *
8300: * @exception SQLException
8301: * if a database-access error occurs
8302: */
8303: public void updateAsciiStream(String columnName,
8304: java.io.InputStream x, int length) throws SQLException {
8305: updateAsciiStream(findColumn(columnName), x, length);
8306: }
8307:
8308: /**
8309: * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
8310: * are used to update column values in the current row, or the insert row.
8311: * The updateXXX() methods do not update the underlying database, instead
8312: * the updateRow() or insertRow() methods are called to update the database.
8313: *
8314: * @param columnIndex
8315: * the first column is 1, the second is 2, ...
8316: * @param x
8317: * the new column value
8318: *
8319: * @exception SQLException
8320: * if a database-access error occurs
8321: * @throws NotUpdatable
8322: * DOCUMENT ME!
8323: */
8324: public void updateBigDecimal(int columnIndex, BigDecimal x)
8325: throws SQLException {
8326: throw new NotUpdatable();
8327: }
8328:
8329: /**
8330: * JDBC 2.0 Update a column with a BigDecimal value. The updateXXX() methods
8331: * are used to update column values in the current row, or the insert row.
8332: * The updateXXX() methods do not update the underlying database, instead
8333: * the updateRow() or insertRow() methods are called to update the database.
8334: *
8335: * @param columnName
8336: * the name of the column
8337: * @param x
8338: * the new column value
8339: *
8340: * @exception SQLException
8341: * if a database-access error occurs
8342: */
8343: public void updateBigDecimal(String columnName, BigDecimal x)
8344: throws SQLException {
8345: updateBigDecimal(findColumn(columnName), x);
8346: }
8347:
8348: /**
8349: * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
8350: * methods are used to update column values in the current row, or the
8351: * insert row. The updateXXX() methods do not update the underlying
8352: * database, instead the updateRow() or insertRow() methods are called to
8353: * update the database.
8354: *
8355: * @param columnIndex
8356: * the first column is 1, the second is 2, ...
8357: * @param x
8358: * the new column value
8359: * @param length
8360: * the length of the stream
8361: *
8362: * @exception SQLException
8363: * if a database-access error occurs
8364: * @throws NotUpdatable
8365: * DOCUMENT ME!
8366: */
8367: public void updateBinaryStream(int columnIndex,
8368: java.io.InputStream x, int length) throws SQLException {
8369: throw new NotUpdatable();
8370: }
8371:
8372: /**
8373: * JDBC 2.0 Update a column with a binary stream value. The updateXXX()
8374: * methods are used to update column values in the current row, or the
8375: * insert row. The updateXXX() methods do not update the underlying
8376: * database, instead the updateRow() or insertRow() methods are called to
8377: * update the database.
8378: *
8379: * @param columnName
8380: * the name of the column
8381: * @param x
8382: * the new column value
8383: * @param length
8384: * of the stream
8385: *
8386: * @exception SQLException
8387: * if a database-access error occurs
8388: */
8389: public void updateBinaryStream(String columnName,
8390: java.io.InputStream x, int length) throws SQLException {
8391: updateBinaryStream(findColumn(columnName), x, length);
8392: }
8393:
8394: /**
8395: * @see ResultSetInternalMethods#updateBlob(int, Blob)
8396: */
8397: public void updateBlob(int arg0, java.sql.Blob arg1)
8398: throws SQLException {
8399: throw new NotUpdatable();
8400: }
8401:
8402: /**
8403: * @see ResultSetInternalMethods#updateBlob(String, Blob)
8404: */
8405: public void updateBlob(String arg0, java.sql.Blob arg1)
8406: throws SQLException {
8407: throw new NotUpdatable();
8408: }
8409:
8410: /**
8411: * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
8412: * are used to update column values in the current row, or the insert row.
8413: * The updateXXX() methods do not update the underlying database, instead
8414: * the updateRow() or insertRow() methods are called to update the database.
8415: *
8416: * @param columnIndex
8417: * the first column is 1, the second is 2, ...
8418: * @param x
8419: * the new column value
8420: *
8421: * @exception SQLException
8422: * if a database-access error occurs
8423: * @throws NotUpdatable
8424: * DOCUMENT ME!
8425: */
8426: public void updateBoolean(int columnIndex, boolean x)
8427: throws SQLException {
8428: throw new NotUpdatable();
8429: }
8430:
8431: /**
8432: * JDBC 2.0 Update a column with a boolean value. The updateXXX() methods
8433: * are used to update column values in the current row, or the insert row.
8434: * The updateXXX() methods do not update the underlying database, instead
8435: * the updateRow() or insertRow() methods are called to update the database.
8436: *
8437: * @param columnName
8438: * the name of the column
8439: * @param x
8440: * the new column value
8441: *
8442: * @exception SQLException
8443: * if a database-access error occurs
8444: */
8445: public void updateBoolean(String columnName, boolean x)
8446: throws SQLException {
8447: updateBoolean(findColumn(columnName), x);
8448: }
8449:
8450: /**
8451: * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
8452: * used to update column values in the current row, or the insert row. The
8453: * updateXXX() methods do not update the underlying database, instead the
8454: * updateRow() or insertRow() methods are called to update the database.
8455: *
8456: * @param columnIndex
8457: * the first column is 1, the second is 2, ...
8458: * @param x
8459: * the new column value
8460: *
8461: * @exception SQLException
8462: * if a database-access error occurs
8463: * @throws NotUpdatable
8464: * DOCUMENT ME!
8465: */
8466: public void updateByte(int columnIndex, byte x) throws SQLException {
8467: throw new NotUpdatable();
8468: }
8469:
8470: /**
8471: * JDBC 2.0 Update a column with a byte value. The updateXXX() methods are
8472: * used to update column values in the current row, or the insert row. The
8473: * updateXXX() methods do not update the underlying database, instead the
8474: * updateRow() or insertRow() methods are called to update the database.
8475: *
8476: * @param columnName
8477: * the name of the column
8478: * @param x
8479: * the new column value
8480: *
8481: * @exception SQLException
8482: * if a database-access error occurs
8483: */
8484: public void updateByte(String columnName, byte x)
8485: throws SQLException {
8486: updateByte(findColumn(columnName), x);
8487: }
8488:
8489: /**
8490: * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
8491: * are used to update column values in the current row, or the insert row.
8492: * The updateXXX() methods do not update the underlying database, instead
8493: * the updateRow() or insertRow() methods are called to update the database.
8494: *
8495: * @param columnIndex
8496: * the first column is 1, the second is 2, ...
8497: * @param x
8498: * the new column value
8499: *
8500: * @exception SQLException
8501: * if a database-access error occurs
8502: * @throws NotUpdatable
8503: * DOCUMENT ME!
8504: */
8505: public void updateBytes(int columnIndex, byte[] x)
8506: throws SQLException {
8507: throw new NotUpdatable();
8508: }
8509:
8510: /**
8511: * JDBC 2.0 Update a column with a byte array value. The updateXXX() methods
8512: * are used to update column values in the current row, or the insert row.
8513: * The updateXXX() methods do not update the underlying database, instead
8514: * the updateRow() or insertRow() methods are called to update the database.
8515: *
8516: * @param columnName
8517: * the name of the column
8518: * @param x
8519: * the new column value
8520: *
8521: * @exception SQLException
8522: * if a database-access error occurs
8523: */
8524: public void updateBytes(String columnName, byte[] x)
8525: throws SQLException {
8526: updateBytes(findColumn(columnName), x);
8527: }
8528:
8529: /**
8530: * JDBC 2.0 Update a column with a character stream value. The updateXXX()
8531: * methods are used to update column values in the current row, or the
8532: * insert row. The updateXXX() methods do not update the underlying
8533: * database, instead the updateRow() or insertRow() methods are called to
8534: * update the database.
8535: *
8536: * @param columnIndex
8537: * the first column is 1, the second is 2, ...
8538: * @param x
8539: * the new column value
8540: * @param length
8541: * the length of the stream
8542: *
8543: * @exception SQLException
8544: * if a database-access error occurs
8545: * @throws NotUpdatable
8546: * DOCUMENT ME!
8547: */
8548: public void updateCharacterStream(int columnIndex,
8549: java.io.Reader x, int length) throws SQLException {
8550: throw new NotUpdatable();
8551: }
8552:
8553: /**
8554: * JDBC 2.0 Update a column with a character stream value. The updateXXX()
8555: * methods are used to update column values in the current row, or the
8556: * insert row. The updateXXX() methods do not update the underlying
8557: * database, instead the updateRow() or insertRow() methods are called to
8558: * update the database.
8559: *
8560: * @param columnName
8561: * the name of the column
8562: * @param reader
8563: * the stream to update the column with
8564: * @param length
8565: * of the stream
8566: *
8567: * @throws SQLException
8568: * if a database-access error occurs
8569: */
8570: public void updateCharacterStream(String columnName,
8571: java.io.Reader reader, int length) throws SQLException {
8572: updateCharacterStream(findColumn(columnName), reader, length);
8573: }
8574:
8575: /**
8576: * @see ResultSetInternalMethods#updateClob(int, Clob)
8577: */
8578: public void updateClob(int arg0, java.sql.Clob arg1)
8579: throws SQLException {
8580: throw new NotImplemented();
8581: }
8582:
8583: /**
8584: * @see ResultSetInternalMethods#updateClob(String, Clob)
8585: */
8586: public void updateClob(String columnName, java.sql.Clob clob)
8587: throws SQLException {
8588: updateClob(findColumn(columnName), clob);
8589: }
8590:
8591: /**
8592: * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
8593: * used to update column values in the current row, or the insert row. The
8594: * updateXXX() methods do not update the underlying database, instead the
8595: * updateRow() or insertRow() methods are called to update the database.
8596: *
8597: * @param columnIndex
8598: * the first column is 1, the second is 2, ...
8599: * @param x
8600: * the new column value
8601: *
8602: * @exception SQLException
8603: * if a database-access error occurs
8604: * @throws NotUpdatable
8605: * DOCUMENT ME!
8606: */
8607: public void updateDate(int columnIndex, java.sql.Date x)
8608: throws SQLException {
8609: throw new NotUpdatable();
8610: }
8611:
8612: /**
8613: * JDBC 2.0 Update a column with a Date value. The updateXXX() methods are
8614: * used to update column values in the current row, or the insert row. The
8615: * updateXXX() methods do not update the underlying database, instead the
8616: * updateRow() or insertRow() methods are called to update the database.
8617: *
8618: * @param columnName
8619: * the name of the column
8620: * @param x
8621: * the new column value
8622: *
8623: * @exception SQLException
8624: * if a database-access error occurs
8625: */
8626: public void updateDate(String columnName, java.sql.Date x)
8627: throws SQLException {
8628: updateDate(findColumn(columnName), x);
8629: }
8630:
8631: /**
8632: * JDBC 2.0 Update a column with a Double value. The updateXXX() methods are
8633: * used to update column values in the current row, or the insert row. The
8634: * updateXXX() methods do not update the underlying database, instead the
8635: * updateRow() or insertRow() methods are called to update the database.
8636: *
8637: * @param columnIndex
8638: * the first column is 1, the second is 2, ...
8639: * @param x
8640: * the new column value
8641: *
8642: * @exception SQLException
8643: * if a database-access error occurs
8644: * @throws NotUpdatable
8645: * DOCUMENT ME!
8646: */
8647: public void updateDouble(int columnIndex, double x)
8648: throws SQLException {
8649: throw new NotUpdatable();
8650: }
8651:
8652: /**
8653: * JDBC 2.0 Update a column with a double value. The updateXXX() methods are
8654: * used to update column values in the current row, or the insert row. The
8655: * updateXXX() methods do not update the underlying database, instead the
8656: * updateRow() or insertRow() methods are called to update the database.
8657: *
8658: * @param columnName
8659: * the name of the column
8660: * @param x
8661: * the new column value
8662: *
8663: * @exception SQLException
8664: * if a database-access error occurs
8665: */
8666: public void updateDouble(String columnName, double x)
8667: throws SQLException {
8668: updateDouble(findColumn(columnName), x);
8669: }
8670:
8671: /**
8672: * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
8673: * used to update column values in the current row, or the insert row. The
8674: * updateXXX() methods do not update the underlying database, instead the
8675: * updateRow() or insertRow() methods are called to update the database.
8676: *
8677: * @param columnIndex
8678: * the first column is 1, the second is 2, ...
8679: * @param x
8680: * the new column value
8681: *
8682: * @exception SQLException
8683: * if a database-access error occurs
8684: * @throws NotUpdatable
8685: * DOCUMENT ME!
8686: */
8687: public void updateFloat(int columnIndex, float x)
8688: throws SQLException {
8689: throw new NotUpdatable();
8690: }
8691:
8692: /**
8693: * JDBC 2.0 Update a column with a float value. The updateXXX() methods are
8694: * used to update column values in the current row, or the insert row. The
8695: * updateXXX() methods do not update the underlying database, instead the
8696: * updateRow() or insertRow() methods are called to update the database.
8697: *
8698: * @param columnName
8699: * the name of the column
8700: * @param x
8701: * the new column value
8702: *
8703: * @exception SQLException
8704: * if a database-access error occurs
8705: */
8706: public void updateFloat(String columnName, float x)
8707: throws SQLException {
8708: updateFloat(findColumn(columnName), x);
8709: }
8710:
8711: /**
8712: * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
8713: * are used to update column values in the current row, or the insert row.
8714: * The updateXXX() methods do not update the underlying database, instead
8715: * the updateRow() or insertRow() methods are called to update the database.
8716: *
8717: * @param columnIndex
8718: * the first column is 1, the second is 2, ...
8719: * @param x
8720: * the new column value
8721: *
8722: * @exception SQLException
8723: * if a database-access error occurs
8724: * @throws NotUpdatable
8725: * DOCUMENT ME!
8726: */
8727: public void updateInt(int columnIndex, int x) throws SQLException {
8728: throw new NotUpdatable();
8729: }
8730:
8731: /**
8732: * JDBC 2.0 Update a column with an integer value. The updateXXX() methods
8733: * are used to update column values in the current row, or the insert row.
8734: * The updateXXX() methods do not update the underlying database, instead
8735: * the updateRow() or insertRow() methods are called to update the database.
8736: *
8737: * @param columnName
8738: * the name of the column
8739: * @param x
8740: * the new column value
8741: *
8742: * @exception SQLException
8743: * if a database-access error occurs
8744: */
8745: public void updateInt(String columnName, int x) throws SQLException {
8746: updateInt(findColumn(columnName), x);
8747: }
8748:
8749: /**
8750: * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
8751: * used to update column values in the current row, or the insert row. The
8752: * updateXXX() methods do not update the underlying database, instead the
8753: * updateRow() or insertRow() methods are called to update the database.
8754: *
8755: * @param columnIndex
8756: * the first column is 1, the second is 2, ...
8757: * @param x
8758: * the new column value
8759: *
8760: * @exception SQLException
8761: * if a database-access error occurs
8762: * @throws NotUpdatable
8763: * DOCUMENT ME!
8764: */
8765: public void updateLong(int columnIndex, long x) throws SQLException {
8766: throw new NotUpdatable();
8767: }
8768:
8769: /**
8770: * JDBC 2.0 Update a column with a long value. The updateXXX() methods are
8771: * used to update column values in the current row, or the insert row. The
8772: * updateXXX() methods do not update the underlying database, instead the
8773: * updateRow() or insertRow() methods are called to update the database.
8774: *
8775: * @param columnName
8776: * the name of the column
8777: * @param x
8778: * the new column value
8779: *
8780: * @exception SQLException
8781: * if a database-access error occurs
8782: */
8783: public void updateLong(String columnName, long x)
8784: throws SQLException {
8785: updateLong(findColumn(columnName), x);
8786: }
8787:
8788: /**
8789: * JDBC 2.0 Give a nullable column a null value. The updateXXX() methods are
8790: * used to update column values in the current row, or the insert row. The
8791: * updateXXX() methods do not update the underlying database, instead the
8792: * updateRow() or insertRow() methods are called to update the database.
8793: *
8794: * @param columnIndex
8795: * the first column is 1, the second is 2, ...
8796: *
8797: * @exception SQLException
8798: * if a database-access error occurs
8799: * @throws NotUpdatable
8800: * DOCUMENT ME!
8801: */
8802: public void updateNull(int columnIndex) throws SQLException {
8803: throw new NotUpdatable();
8804: }
8805:
8806: /**
8807: * JDBC 2.0 Update a column with a null value. The updateXXX() methods are
8808: * used to update column values in the current row, or the insert row. The
8809: * updateXXX() methods do not update the underlying database, instead the
8810: * updateRow() or insertRow() methods are called to update the database.
8811: *
8812: * @param columnName
8813: * the name of the column
8814: *
8815: * @exception SQLException
8816: * if a database-access error occurs
8817: */
8818: public void updateNull(String columnName) throws SQLException {
8819: updateNull(findColumn(columnName));
8820: }
8821:
8822: /**
8823: * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8824: * are used to update column values in the current row, or the insert row.
8825: * The updateXXX() methods do not update the underlying database, instead
8826: * the updateRow() or insertRow() methods are called to update the database.
8827: *
8828: * @param columnIndex
8829: * the first column is 1, the second is 2, ...
8830: * @param x
8831: * the new column value
8832: *
8833: * @exception SQLException
8834: * if a database-access error occurs
8835: * @throws NotUpdatable
8836: * DOCUMENT ME!
8837: */
8838: public void updateObject(int columnIndex, Object x)
8839: throws SQLException {
8840: throw new NotUpdatable();
8841: }
8842:
8843: /**
8844: * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8845: * are used to update column values in the current row, or the insert row.
8846: * The updateXXX() methods do not update the underlying database, instead
8847: * the updateRow() or insertRow() methods are called to update the database.
8848: *
8849: * @param columnIndex
8850: * the first column is 1, the second is 2, ...
8851: * @param x
8852: * the new column value
8853: * @param scale
8854: * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
8855: * this is the number of digits after the decimal. For all other
8856: * types this value will be ignored.
8857: *
8858: * @exception SQLException
8859: * if a database-access error occurs
8860: * @throws NotUpdatable
8861: * DOCUMENT ME!
8862: */
8863: public void updateObject(int columnIndex, Object x, int scale)
8864: throws SQLException {
8865: throw new NotUpdatable();
8866: }
8867:
8868: /**
8869: * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8870: * are used to update column values in the current row, or the insert row.
8871: * The updateXXX() methods do not update the underlying database, instead
8872: * the updateRow() or insertRow() methods are called to update the database.
8873: *
8874: * @param columnName
8875: * the name of the column
8876: * @param x
8877: * the new column value
8878: *
8879: * @exception SQLException
8880: * if a database-access error occurs
8881: */
8882: public void updateObject(String columnName, Object x)
8883: throws SQLException {
8884: updateObject(findColumn(columnName), x);
8885: }
8886:
8887: /**
8888: * JDBC 2.0 Update a column with an Object value. The updateXXX() methods
8889: * are used to update column values in the current row, or the insert row.
8890: * The updateXXX() methods do not update the underlying database, instead
8891: * the updateRow() or insertRow() methods are called to update the database.
8892: *
8893: * @param columnName
8894: * the name of the column
8895: * @param x
8896: * the new column value
8897: * @param scale
8898: * For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types
8899: * this is the number of digits after the decimal. For all other
8900: * types this value will be ignored.
8901: *
8902: * @exception SQLException
8903: * if a database-access error occurs
8904: */
8905: public void updateObject(String columnName, Object x, int scale)
8906: throws SQLException {
8907: updateObject(findColumn(columnName), x);
8908: }
8909:
8910: /**
8911: * @see ResultSetInternalMethods#updateRef(int, Ref)
8912: */
8913: public void updateRef(int arg0, Ref arg1) throws SQLException {
8914: throw new NotImplemented();
8915: }
8916:
8917: /**
8918: * @see ResultSetInternalMethods#updateRef(String, Ref)
8919: */
8920: public void updateRef(String arg0, Ref arg1) throws SQLException {
8921: throw new NotImplemented();
8922: }
8923:
8924: /**
8925: * JDBC 2.0 Update the underlying database with the new contents of the
8926: * current row. Cannot be called when on the insert row.
8927: *
8928: * @exception SQLException
8929: * if a database-access error occurs, or if called when on
8930: * the insert row
8931: * @throws NotUpdatable
8932: * DOCUMENT ME!
8933: */
8934: public void updateRow() throws SQLException {
8935: throw new NotUpdatable();
8936: }
8937:
8938: /**
8939: * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
8940: * used to update column values in the current row, or the insert row. The
8941: * updateXXX() methods do not update the underlying database, instead the
8942: * updateRow() or insertRow() methods are called to update the database.
8943: *
8944: * @param columnIndex
8945: * the first column is 1, the second is 2, ...
8946: * @param x
8947: * the new column value
8948: *
8949: * @exception SQLException
8950: * if a database-access error occurs
8951: * @throws NotUpdatable
8952: * DOCUMENT ME!
8953: */
8954: public void updateShort(int columnIndex, short x)
8955: throws SQLException {
8956: throw new NotUpdatable();
8957: }
8958:
8959: /**
8960: * JDBC 2.0 Update a column with a short value. The updateXXX() methods are
8961: * used to update column values in the current row, or the insert row. The
8962: * updateXXX() methods do not update the underlying database, instead the
8963: * updateRow() or insertRow() methods are called to update the database.
8964: *
8965: * @param columnName
8966: * the name of the column
8967: * @param x
8968: * the new column value
8969: *
8970: * @exception SQLException
8971: * if a database-access error occurs
8972: */
8973: public void updateShort(String columnName, short x)
8974: throws SQLException {
8975: updateShort(findColumn(columnName), x);
8976: }
8977:
8978: /**
8979: * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
8980: * used to update column values in the current row, or the insert row. The
8981: * updateXXX() methods do not update the underlying database, instead the
8982: * updateRow() or insertRow() methods are called to update the database.
8983: *
8984: * @param columnIndex
8985: * the first column is 1, the second is 2, ...
8986: * @param x
8987: * the new column value
8988: *
8989: * @exception SQLException
8990: * if a database-access error occurs
8991: * @throws NotUpdatable
8992: * DOCUMENT ME!
8993: */
8994: public void updateString(int columnIndex, String x)
8995: throws SQLException {
8996: throw new NotUpdatable();
8997: }
8998:
8999: /**
9000: * JDBC 2.0 Update a column with a String value. The updateXXX() methods are
9001: * used to update column values in the current row, or the insert row. The
9002: * updateXXX() methods do not update the underlying database, instead the
9003: * updateRow() or insertRow() methods are called to update the database.
9004: *
9005: * @param columnName
9006: * the name of the column
9007: * @param x
9008: * the new column value
9009: *
9010: * @exception SQLException
9011: * if a database-access error occurs
9012: */
9013: public void updateString(String columnName, String x)
9014: throws SQLException {
9015: updateString(findColumn(columnName), x);
9016: }
9017:
9018: /**
9019: * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
9020: * used to update column values in the current row, or the insert row. The
9021: * updateXXX() methods do not update the underlying database, instead the
9022: * updateRow() or insertRow() methods are called to update the database.
9023: *
9024: * @param columnIndex
9025: * the first column is 1, the second is 2, ...
9026: * @param x
9027: * the new column value
9028: *
9029: * @exception SQLException
9030: * if a database-access error occurs
9031: * @throws NotUpdatable
9032: * DOCUMENT ME!
9033: */
9034: public void updateTime(int columnIndex, java.sql.Time x)
9035: throws SQLException {
9036: throw new NotUpdatable();
9037: }
9038:
9039: /**
9040: * JDBC 2.0 Update a column with a Time value. The updateXXX() methods are
9041: * used to update column values in the current row, or the insert row. The
9042: * updateXXX() methods do not update the underlying database, instead the
9043: * updateRow() or insertRow() methods are called to update the database.
9044: *
9045: * @param columnName
9046: * the name of the column
9047: * @param x
9048: * the new column value
9049: *
9050: * @exception SQLException
9051: * if a database-access error occurs
9052: */
9053: public void updateTime(String columnName, java.sql.Time x)
9054: throws SQLException {
9055: updateTime(findColumn(columnName), x);
9056: }
9057:
9058: /**
9059: * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
9060: * are used to update column values in the current row, or the insert row.
9061: * The updateXXX() methods do not update the underlying database, instead
9062: * the updateRow() or insertRow() methods are called to update the database.
9063: *
9064: * @param columnIndex
9065: * the first column is 1, the second is 2, ...
9066: * @param x
9067: * the new column value
9068: *
9069: * @exception SQLException
9070: * if a database-access error occurs
9071: * @throws NotUpdatable
9072: * DOCUMENT ME!
9073: */
9074: public void updateTimestamp(int columnIndex, java.sql.Timestamp x)
9075: throws SQLException {
9076: throw new NotUpdatable();
9077: }
9078:
9079: /**
9080: * JDBC 2.0 Update a column with a Timestamp value. The updateXXX() methods
9081: * are used to update column values in the current row, or the insert row.
9082: * The updateXXX() methods do not update the underlying database, instead
9083: * the updateRow() or insertRow() methods are called to update the database.
9084: *
9085: * @param columnName
9086: * the name of the column
9087: * @param x
9088: * the new column value
9089: *
9090: * @exception SQLException
9091: * if a database-access error occurs
9092: */
9093: public void updateTimestamp(String columnName, java.sql.Timestamp x)
9094: throws SQLException {
9095: updateTimestamp(findColumn(columnName), x);
9096: }
9097:
9098: /**
9099: * A column may have the value of SQL NULL; wasNull() reports whether the
9100: * last column read had this special value. Note that you must first call
9101: * getXXX on a column to try to read its value and then call wasNull() to
9102: * find if the value was SQL NULL
9103: *
9104: * @return true if the last column read was SQL NULL
9105: *
9106: * @exception SQLException
9107: * if a database access error occurred
9108: */
9109: public boolean wasNull() throws SQLException {
9110: return this .wasNullFlag;
9111: }
9112:
9113: protected Calendar getGmtCalendar() {
9114:
9115: // Worst case we allocate this twice and the other gets GC'd,
9116: // however prevents deadlock
9117: if (this .gmtCalendar == null) {
9118: this .gmtCalendar = Calendar.getInstance(TimeZone
9119: .getTimeZone("GMT"));
9120: }
9121:
9122: return this.gmtCalendar;
9123: }
9124: }
|