?? resultset.java
字號:
/* Copyright (C) 2002-2007 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. There are special exceptions to the terms and conditions of the GPL as it is applied to this software. View the full text of the exception in file EXCEPTIONS-CONNECTOR-J in the directory of this software distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package com.mysql.jdbc;import com.mysql.jdbc.profiler.ProfileEventSink;import com.mysql.jdbc.profiler.ProfilerEvent;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.ObjectInputStream;import java.io.StringReader;import java.io.UnsupportedEncodingException;import java.math.BigDecimal;import java.math.BigInteger;import java.net.MalformedURLException;import java.net.URL;import java.sql.Array;import java.sql.DataTruncation;import java.sql.Date;import java.sql.Ref;import java.sql.SQLException;import java.sql.SQLWarning;import java.sql.Time;import java.sql.Timestamp;import java.sql.Types;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.HashMap;import java.util.Locale;import java.util.Map;import java.util.StringTokenizer;import java.util.TimeZone;import java.util.TreeMap;/** * A ResultSet provides access to a table of data generated by executing a * Statement. The table rows are retrieved in sequence. Within a row its column * values can be accessed in any order. * * <P> * A ResultSet maintains a cursor pointing to its current row of data. Initially * the cursor is positioned before the first row. The 'next' method moves the * cursor to the next row. * </p> * * <P> * The getXXX methods retrieve column values for the current row. You can * retrieve values either using the index number of the column, or by using the * name of the column. In general using the column index will be more efficient. * Columns are numbered from 1. * </p> * * <P> * For maximum portability, ResultSet columns within each row should be read in * left-to-right order and each column should be read only once. * </p> * * <P> * For the getXXX methods, the JDBC driver attempts to convert the underlying * data to the specified Java type and returns a suitable Java value. See the * JDBC specification for allowable mappings from SQL types to Java types with * the ResultSet getXXX methods. * </p> * * <P> * Column names used as input to getXXX methods are case insenstive. When * performing a getXXX using a column name, if several columns have the same * name, then the value of the first matching column will be returned. The * column name option is designed to be used when column names are used in the * SQL Query. For columns that are NOT explicitly named in the query, it is best * to use column numbers. If column names were used there is no way for the * programmer to guarentee that they actually refer to the intended columns. * </p> * * <P> * A ResultSet is automatically closed by the Statement that generated it when * that Statement is closed, re-executed, or is used to retrieve the next result * from a sequence of multiple results. * </p> * * <P> * The number, types and properties of a ResultSet's columns are provided by the * ResultSetMetaData object returned by the getMetaData method. * </p> * * @author Mark Matthews * @version $Id: ResultSet.java 6563 2007-09-06 14:02:01Z mmatthews $ * * @see ResultSetMetaData * @see java.sql.ResultSet */public class ResultSet implements java.sql.ResultSet { /** * Epsillon between Float.MIN_VALUE and the double representation of said value. */ protected static final double MIN_DIFF_PREC = Float.parseFloat(Float.toString(Float.MIN_VALUE)) - Double.parseDouble(Float.toString(Float.MIN_VALUE)); /** * Epsillon between Float.MAX_VALUE and the double representation of said value. */ protected static final double MAX_DIFF_PREC = Float.parseFloat(Float.toString(Float.MAX_VALUE)) - Double.parseDouble(Float.toString(Float.MAX_VALUE)); /** Counter used to generate IDs for profiling. */ protected static int resultCounter = 1; /** * Converts the given value as a java long, to an 'unsigned' long, using the * java.math.BigInteger class. */ protected static BigInteger convertLongToUlong(long longVal) { byte[] asBytes = new byte[8]; asBytes[7] = (byte) (longVal & 0xff); asBytes[6] = (byte) (longVal >>> 8); asBytes[5] = (byte) (longVal >>> 16); asBytes[4] = (byte) (longVal >>> 24); asBytes[3] = (byte) (longVal >>> 32); asBytes[2] = (byte) (longVal >>> 40); asBytes[1] = (byte) (longVal >>> 48); asBytes[0] = (byte) (longVal >>> 56); return new BigInteger(1, asBytes); } /** The catalog that was in use when we were created */ protected String catalog = null; /** Map column names (and all of their permutations) to column indices */ protected Map columnNameToIndex = null; /** Keep track of columns accessed */ protected boolean[] columnUsed = null; /** The Connection instance that created us */ protected com.mysql.jdbc.Connection connection; // The connection that // created us protected long connectionId = 0; /** The current row #, -1 == before start of result set */ protected int currentRow = -1; // Cursor to current row; private TimeZone defaultTimeZone; /** Are we in the middle of doing updates to the current row? */ protected boolean doingUpdates = false; protected ProfileEventSink eventSink = null; private Calendar fastDateCal = null; /** The direction to fetch rows (always FETCH_FORWARD) */ protected int fetchDirection = FETCH_FORWARD; /** The number of rows to fetch in one go... */ protected int fetchSize = 0; /** The fields for this result set */ protected Field[] fields; // The fields /** * First character of the query that created this result set...Used to * determine whether or not to parse server info messages in certain * circumstances. */ protected char firstCharOfQuery; /** Map of fully-specified column names to column indices */ protected Map fullColumnNameToIndex = null; protected boolean hasBuiltIndexMapping = false; /** * Is the data stored as strings (default) or natively (which is the case * with results from PrepStmts) */ protected boolean isBinaryEncoded = false; /** Has this result set been closed? */ protected boolean isClosed = false; protected ResultSet nextResultSet = null; /** Are we on the insert row? */ protected boolean onInsertRow = false; /** The statement that created us */ protected com.mysql.jdbc.Statement owningStatement; /** * StackTrace generated where ResultSet was created... used when profiling */ protected Throwable pointOfOrigin; /** Are we tracking items for profileSql? */ protected boolean profileSql = false; /** * Do we actually contain rows, or just information about * UPDATE/INSERT/DELETE? */ protected boolean reallyResult = false; /** The id (used when profiling) to identify us */ protected int resultId; /** Are we read-only or updatable? */ protected int resultSetConcurrency = 0; /** Are we scroll-sensitive/insensitive? */ protected int resultSetType = 0; /** The actual rows */ protected RowData rowData; // The results /** * Any info message from the server that was created while generating this * result set (if 'info parsing' is enabled for the connection). */ protected String serverInfo = null; private PreparedStatement statementUsedForFetchingRows; /** Pointer to current row data */ protected Object[] thisRow = null; // Values for current row // These are longs for // recent versions of the MySQL server. // // They get reduced to ints via the JDBC API, // but can be retrieved through a MySQLStatement // in their entirety. // /** How many rows were affected by UPDATE/INSERT/DELETE? */ protected long updateCount; /** Value generated for AUTO_INCREMENT columns */ protected long updateId = -1; private boolean useStrictFloatingPoint = false; protected boolean useUsageAdvisor = false; /** The warning chain */ protected java.sql.SQLWarning warningChain = null; /** Did the previous value retrieval find a NULL? */ protected boolean wasNullFlag = false; protected java.sql.Statement wrapperStatement; protected boolean retainOwningStatement; protected Calendar gmtCalendar = null; protected boolean useFastDateParsing = false; private boolean padCharsWithSpace = false; protected final static char[] EMPTY_SPACE = new char[255]; static { for (int i = 0; i < EMPTY_SPACE.length; i++) { EMPTY_SPACE[i] = ' '; } } /** * Create a result set for an executeUpdate statement. * * @param updateCount * the number of rows affected by the update * @param updateID * the autoincrement value (if any) * @param conn * DOCUMENT ME! * @param creatorStmt * DOCUMENT ME! */ public ResultSet(long updateCount, long updateID, Connection conn, Statement creatorStmt) { this.updateCount = updateCount; this.updateId = updateID; this.reallyResult = false; this.fields = new Field[0]; this.connection = conn; this.owningStatement = creatorStmt; this.retainOwningStatement = false; if (this.connection != null) { this.retainOwningStatement = this.connection.getRetainStatementAfterResultSetClose(); this.connectionId = this.connection.getId(); } } /** * Creates a new ResultSet object. * * @param catalog * the database in use when we were created * @param fields * an array of Field objects (basically, the ResultSet MetaData) * @param tuples * actual row data * @param conn * the Connection that created us. * @param creatorStmt * DOCUMENT ME! * * @throws SQLException * if an error occurs */ public ResultSet(String catalog, Field[] fields, RowData tuples, Connection conn, Statement creatorStmt) throws SQLException { this.connection = conn; if (this.connection != null) { this.useStrictFloatingPoint = this.connection .getStrictFloatingPoint(); this.setDefaultTimeZone(this.connection.getDefaultTimeZone()); this.connectionId = this.connection.getId(); this.useFastDateParsing = this.connection.getUseFastDateParsing(); this.padCharsWithSpace = this.connection.getPadCharsWithSpace(); } this.owningStatement = creatorStmt; this.catalog = catalog; this.profileSql = this.connection.getProfileSql(); this.fields = fields; this.rowData = tuples; this.updateCount = this.rowData.size(); if (Driver.DEBUG) { System.out.println(Messages.getString("ResultSet.Retrieved__1") + this.updateCount + " rows"); //$NON-NLS-1$ } this.reallyResult = true; // Check for no results if (this.rowData.size() > 0) { if (this.updateCount == 1) { if (this.thisRow == null) { this.rowData.close(); // empty result set this.updateCount = -1; } } } else { this.thisRow = null; } this.rowData.setOwner(this); if (this.fields != null) { initializeWithMetadata(); } // else called by Connection.initializeResultsMetadataFromCache() when cached this.retainOwningStatement = false; if (this.connection != null) { retainOwningStatement = this.connection.getRetainStatementAfterResultSetClose(); } } protected void initializeWithMetadata() throws SQLException { if (this.profileSql || this.connection.getUseUsageAdvisor()) { this.columnUsed = new boolean[this.fields.length]; this.pointOfOrigin = new Throwable(); this.resultId = resultCounter++; this.useUsageAdvisor = this.connection.getUseUsageAdvisor(); this.eventSink = ProfileEventSink.getInstance(this.connection); } if (this.connection.getGatherPerformanceMetrics()) { this.connection.incrementNumberOfResultSetsCreated(); Map tableNamesMap = new HashMap(); for (int i = 0; i < this.fields.length; i++) { Field f = this.fields[i]; String tableName = f.getOriginalTableName(); if (tableName == null) { tableName = f.getTableName(); } if (tableName != null) { if (this.connection.lowerCaseTableNames()) { tableName = tableName.toLowerCase(); // on windows, table // names are not case-sens. } tableNamesMap.put(tableName, null); } } this.connection.reportNumberOfTablesAccessed(tableNamesMap.size()); } } private synchronized void createCalendarIfNeeded() { if (this.fastDateCal == null) { this.fastDateCal = new GregorianCalendar(Locale.US); this.fastDateCal.setTimeZone(this.getDefaultTimeZone()); } } /** * JDBC 2.0 * * <p> * Move to an absolute row number in the result set. * </p> * * <p> * If row is positive, moves to an absolute row with respect to the * beginning of the result set. The first row is row 1, the second is row 2, * etc. * </p> * * <p> * If row is negative, moves to an absolute row position with respect to the * end of result set. For example, calling absolute(-1) positions the cursor * on the last row, absolute(-2) indicates the next-to-last row, etc. * </p> * * <p> * An attempt to position the cursor beyond the first/last row in the result * set, leaves the cursor before/after the first/last row, respectively. * </p> * * <p> * Note: Calling absolute(1) is the same as calling first(). Calling * absolute(-1) is the same as calling last(). * </p> * * @param row * the row number to move to * * @return true if on the result set, false if off. * * @exception SQLException * if a database-access error occurs, or row is 0, or result
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -