/* * MM JDBC Drivers for MySQL * * $Id: ResultSet.java,v 1.8 2002/05/16 20:22:44 mark_matthews Exp $ * * Copyright (C) 1998 Mark Matthews * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330 * Boston, MA 02111-1307, USA. * * See the COPYING file located in the top-level-directory of * the archive of this library for complete text of license. * * Some portions: * * Copyright (c) 1996 Bradley McLean / Jeffrey Medeiros * Modifications Copyright (c) 1996/1997 Martin Rode * Copyright (c) 1997 Peter T Mount */ /** * 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. * *

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. * *

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. * *

For maximum portability, ResultSet columns within each row should be read * in left-to-right order and each column should be read only once. * *

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. * *

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. * *

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. * *

The number, types and properties of a ResultSet's columns are provided by * the ResultSetMetaData object returned by the getMetaData method. * * @see ResultSetMetaData * @see java.sql.ResultSet * @author Mark Matthews * @version $Id: ResultSet.java,v 1.8 2002/05/16 20:22:44 mark_matthews Exp $ */ package com.mysql.jdbc.jdbc2; import java.io.*; import java.math.*; import java.text.*; import java.util.*; import java.sql.*; import com.mysql.jdbc.Debug; import com.mysql.jdbc.Driver; public class ResultSet extends com.mysql.jdbc.ResultSet implements java.sql.ResultSet { private final static String UPDATEABLE_MESSAGE = "Result Set not updateable. The " + "query that generated this result set must select only one table, and must " + "select all primary keys from that table. See the JDBC 2.1 API Specification, " + "section 5.6 for more details."; /** * SQL for in-place modifcation */ protected String _UpdateSQL = null; protected String _DeleteSQL = null; protected String _InsertSQL = null; protected String _RefreshSQL = null; /** * PreparedStatement used to refresh data */ protected com.mysql.jdbc.jdbc2.PreparedStatement _Refresher; /** * PreparedStatement used to delete data */ protected com.mysql.jdbc.jdbc2.PreparedStatement _Updater = null; /** * PreparedStatement used to insert data */ protected com.mysql.jdbc.jdbc2.PreparedStatement _Inserter = null; /** * PreparedStatement used to delete data */ protected com.mysql.jdbc.jdbc2.PreparedStatement _Deleter = null; /** * List of primary keys */ protected Vector _PrimaryKeyIndicies = null; /** * Is this result set updateable? */ protected boolean _updatable = false; /** * Are we in the middle of doing updates to the current row? */ protected boolean _doing_updates = false; /** * Are we on the insert row? */ protected boolean _on_insert_row = false; /** * The numbers, types and properties of a ResultSet's columns are * provided by the getMetaData method * * @return a description of the ResultSet's columns * @exception java.sql.SQLException if a database access error occurs */ public java.sql.ResultSetMetaData getMetaData() throws java.sql.SQLException { return new com.mysql.jdbc.jdbc2.ResultSetMetaData(_rows, _fields); } //--------------------------JDBC 2.0----------------------------------- //--------------------------------------------------------------------- // Getter's and Setter's //--------------------------------------------------------------------- /** * JDBC 2.0 * *

Get the value of a column in the current row as a java.io.Reader. */ public java.io.Reader getCharacterStream(int columnIndex) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * *

Get the value of a column in the current row as a java.io.Reader. */ public java.io.Reader getCharacterStream(String columnName) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get the value of a column in the current row as a java.math.BigDecimal * object. * * @param columnIndex the first column is 1, the second is 2, ... * @return the column value (full precision); if the value is SQL NULL, * the result is null * @exception SQLException if a database-access error occurs. */ public BigDecimal getBigDecimal(int columnIndex) throws SQLException { String S = getString(columnIndex); BigDecimal Val; if (S != null) { if (S.length() == 0) { Val = new BigDecimal(0); return Val; } try { Val = new BigDecimal(S); return Val; } catch (NumberFormatException E) { throw new java.sql.SQLException( "Bad format for BigDecimal '" + S + "' in column " + columnIndex + "(" + _fields[columnIndex - 1] + ").", "S1009"); } } return null; // SQL NULL } /** * JDBC 2.0 * * Get the value of a column in the current row as a java.math.BigDecimal * object. * */ public BigDecimal getBigDecimal(String columnName) throws SQLException { String S = getString(columnName); BigDecimal Val; if (S != null) { if (S.length() == 0) { Val = new BigDecimal(0); return Val; } try { Val = new BigDecimal(S); return Val; } catch (NumberFormatException E) { throw new java.sql.SQLException( "Bad format for BigDecimal '" + S + "' in column " + columnName + ".", "S1009"); } } return null; // SQL NULL } //--------------------------------------------------------------------- // Traversal/Positioning //--------------------------------------------------------------------- /** * JDBC 1.0, over-ridden to handle row-updates */ public boolean next() throws SQLException { if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } return super.next(); } /** * JDBC 2.0 * *

Determine if the cursor is before the first row in the result * set. * * @return true if before the first row, false otherwise. Returns * false when the result set contains no rows. * @exception SQLException if a database-access error occurs. */ public boolean isBeforeFirst() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "isBeforeFirst", args); } boolean b = false; if (_rows.size() == 0) { b = false; } else { b = (_currentRow == -1); } if (Driver.trace) { Debug.returnValue(this, "isBeforeFirst", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Determine if the cursor is after the last row in the result * set. * * @return true if after the last row, false otherwise. Returns * false when the result set contains no rows. * @exception SQLException if a database-access error occurs. */ public boolean isAfterLast() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "isAfterLast", args); } boolean b = false; if (_rows.size() == 0) { b = false; } else { b = (_currentRow >= _rows.size()); } if (Driver.trace) { Debug.returnValue(this, "isAfterLast", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Determine if the cursor is on the first row of the result set. * * @return true if on the first row, false otherwise. * @exception SQLException if a database-access error occurs. */ public boolean isFirst() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "isFirst", args); } boolean b = false; if (_rows.size() == 0) { b = false; } else { b = (_currentRow == 0); } if (Driver.trace) { Debug.returnValue(this, "isFirst", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Determine if the cursor is on the last row of the result set. * Note: Calling isLast() may be expensive since the JDBC driver * might need to fetch ahead one row in order to determine * whether the current row is the last row in the result set. * * @return true if on the last row, false otherwise. * @exception SQLException if a database-access error occurs. */ public boolean isLast() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "isLast", args); } boolean b = false; if (_rows.size() == 0) { b = false; } else { b = (_currentRow == _rows.size() - 1); } if (Driver.trace) { Debug.returnValue(this, "relative", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Moves to the front of the result set, just before the * first row. Has no effect if the result set contains no rows. * * @exception SQLException if a database-access error occurs, or * result set type is TYPE_FORWARD_ONLY */ public void beforeFirst() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "beforeFirst", args); } if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } if (_rows.size() == 0) { return; } else { _currentRow = -1; _thisRow = null; } } /** * JDBC 2.0 * *

Moves to the end of the result set, just after the last * row. Has no effect if the result set contains no rows. * * @exception SQLException if a database-access error occurs, or * result set type is TYPE_FORWARD_ONLY. */ public void afterLast() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "afterLast", args); } if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } if (_rows.size() != 0) { _currentRow = _rows.size(); _thisRow = null; } } /** * JDBC 2.0 * *

Moves to the first row in the result set. * * @return true if on a valid row, false if no rows in the result set. * @exception SQLException if a database-access error occurs, or * result set type is TYPE_FORWARD_ONLY. */ public boolean first() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "first", args); } if (_on_insert_row) { _on_insert_row = false; } if (_rows.size() == 0) { return false; } else { if (_doing_updates) { _doing_updates = false; } _currentRow = 0; _thisRow = (byte[][]) _rows.elementAt(_currentRow); return true; } } /** * JDBC 2.0 * *

Moves to the last row in the result set. * * @return true if on a valid row, false if no rows in the result set. * @exception SQLException if a database-access error occurs, or * result set type is TYPE_FORWARD_ONLY. */ public boolean last() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "last", args); } if (_rows.size() == 0) { return false; } else { if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } _currentRow = _rows.size() - 1; _thisRow = (byte[][]) _rows.elementAt(_currentRow); return true; } } /** * JDBC 2.0 * *

Determine the current row number. The first row is number 1, the * second number 2, etc. * * @return the current row number, else return 0 if there is no * current row * @exception SQLException if a database-access error occurs. */ public int getRow() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "getRow", args); } int row = 0; if (_currentRow < 0 || _currentRow >= _rows.size() || _rows.size() == 0) { row = 0; } else { row = _currentRow + 1; } if (Driver.trace) { Debug.returnValue(this, "getRow", new Integer(row)); } return row; } /** * JDBC 2.0 * *

Move to an absolute row number in the result set. * *

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. * *

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. * *

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. * *

Note: Calling absolute(1) is the same as calling first(). * Calling absolute(-1) is the same as calling last(). * * @return true if on the result set, false if off. * @exception SQLException if a database-access error occurs, or * row is 0, or result set type is TYPE_FORWARD_ONLY. */ public boolean absolute(int row) throws SQLException { if (Driver.trace) { Object[] args = { new Integer(row)}; Debug.methodCall(this, "absolute", args); } boolean b; if (_rows.size() == 0) { b = false; } else { if (row == 0) { throw new SQLException("Cannot absolute position to row 0", "S1009"); } if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } if (row == 1) { b = first(); } else if (row == -1) { b = last(); } else if (row > _rows.size()) { afterLast(); b = false; } else { if (row < 0) { // adjust to reflect after end of result set int new_row_position = _rows.size() + row + 1; if (new_row_position <= 0) { beforeFirst(); b = false; } else { b = absolute(new_row_position); } } else { row--; // adjust for index difference _currentRow = row; _thisRow = (byte[][]) _rows.elementAt(_currentRow); b = true; } } } if (Driver.trace) { Debug.returnValue(this, "absolute", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Moves a relative number of rows, either positive or negative. * Attempting to move beyond the first/last row in the * result set positions the cursor before/after the * the first/last row. Calling relative(0) is valid, but does * not change the cursor position. * *

Note: Calling relative(1) is different than calling next() * since is makes sense to call next() when there is no current row, * for example, when the cursor is positioned before the first row * or after the last row of the result set. * * @return true if on a row, false otherwise. * @exception SQLException if a database-access error occurs, or there * is no current row, or result set type is TYPE_FORWARD_ONLY. */ public boolean relative(int rows) throws SQLException { if (Driver.trace) { Object[] args = { new Integer(rows)}; Debug.methodCall(this, "relative", args); } if (_rows.size() == 0) { return false; } int new_row_position = _currentRow + rows + 1; boolean b = absolute(new_row_position); if (Driver.trace) { Debug.returnValue(this, "relative", new Boolean(b)); } return b; } /** * JDBC 2.0 * *

Moves to the previous row in the result set. * *

Note: previous() is not the same as relative(-1) since it * makes sense to call previous() when there is no current row. * * @return true if on a valid row, false if off the result set. * @exception SQLException if a database-access error occurs, or * result set type is TYPE_FORWAR_DONLY. */ public boolean previous() throws SQLException { if (Driver.trace) { Object[] args = { }; Debug.methodCall(this, "previous", args); } if (_on_insert_row) { _on_insert_row = false; } if (_doing_updates) { _doing_updates = false; } return prev(); } protected int _fetch_direction = FETCH_FORWARD; /** * JDBC 2.0 * * Give a hint as to the direction in which the rows in this result set * will be processed. The initial value is determined by the statement * that produced the result set. The fetch direction may be changed * at any time. * * @exception SQLException if a database-access error occurs, or * the result set type is TYPE_FORWARD_ONLY and direction is not * FETCH_FORWARD. * * MM.MySQL actually ignores this, because it has the whole result * set anyway, so the direction is immaterial. */ public void setFetchDirection(int direction) throws SQLException { if (direction != FETCH_FORWARD && direction != FETCH_REVERSE) { throw new SQLException("Illegal value for fetch direction", "S1009"); } else { _fetch_direction = direction; } } /** * JDBC 2.0 * * Return the fetch direction for this result set. * * @exception SQLException if a database-access error occurs */ public int getFetchDirection() throws SQLException { return _fetch_direction; } protected int _fetch_size = 0; /** * JDBC 2.0 * * Give the JDBC driver a hint as to the number of rows that should * be fetched from the database when more rows are needed for this result * set. If the fetch size specified is zero, then the JDBC driver * ignores the value, and is free to make its own best guess as to what * the fetch size should be. The default value is set by the statement * that creates the result set. The fetch size may be changed at any * time. * * @param rows the number of rows to fetch * @exception SQLException if a database-access error occurs, or the * condition 0 <= rows <= this.getMaxRows() is not satisfied. * * Currently ignored by this driver. */ public void setFetchSize(int rows) throws SQLException { if (rows < 0 /* || rows > getMaxRows()*/ ) { throw new SQLException("Value must be between 0 and getMaxRows()", "S1009"); } _fetch_size = rows; } /** * JDBC 2.0 * * Return the fetch size for this result set. * * @exception SQLException if a database-access error occurs */ public int getFetchSize() throws SQLException { return _fetch_size; } /** * JDBC 2.0 * * Return the type of this result set. The type is determined based * on the statement that created the result set. * * @return TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, or * TYPE_SCROLL_SENSITIVE * @exception SQLException if a database-access error occurs */ public int getType() throws SQLException { return _resultSetType; } /** * JDBC 2.0 * * Return the concurrency of this result set. The concurrency * used is determined by the statement that created the result set. * * @return the concurrency type, CONCUR_READ_ONLY, etc. * @exception SQLException if a database-access error occurs */ public int getConcurrency() throws SQLException { return (_updatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY); } //--------------------------------------------------------------------- // Updates //--------------------------------------------------------------------- /** * JDBC 2.0 * * Determine if the current row has been updated. The value returned * depends on whether or not the result set can detect updates. * * @return true if the row has been visibly updated by the owner or * another, and updates are detected * @exception SQLException if a database-access error occurs * * @see DatabaseMetaData#updatesAreDetected */ public boolean rowUpdated() throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Determine if the current row has been inserted. The value returned * depends on whether or not the result set can detect visible inserts. * * @return true if inserted and inserts are detected * @exception SQLException if a database-access error occurs * * @see DatabaseMetaData#insertsAreDetected */ public boolean rowInserted() throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Determine if this row has been deleted. A deleted row may leave * a visible "hole" in a result set. This method can be used to * detect holes in a result set. The value returned depends on whether * or not the result set can detect deletions. * * @return true if deleted and deletes are detected * @exception SQLException if a database-access error occurs * * @see DatabaseMetaData#deletesAreDetected */ public boolean rowDeleted() throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Give a nullable column a null value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @exception SQLException if a database-access error occurs */ public void updateNull(int columnIndex) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setNull(columnIndex, 0); } else { _Inserter.setNull(columnIndex, 0); } } /** * JDBC 2.0 * * Update a column with a boolean value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBoolean(int columnIndex, boolean x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setBoolean(columnIndex, x); } else { _Inserter.setBoolean(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a byte value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateByte(int columnIndex, byte x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setByte(columnIndex, x); } else { _Inserter.setByte(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a short value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateShort(int columnIndex, short x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setShort(columnIndex, x); } else { _Inserter.setShort(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with an integer value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateInt(int columnIndex, int x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setInt(columnIndex, x); } else { _Inserter.setInt(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a long value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateLong(int columnIndex, long x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setLong(columnIndex, x); } else { _Inserter.setLong(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a float value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateFloat(int columnIndex, float x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setFloat(columnIndex, x); } else { _Inserter.setFloat(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a Double value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateDouble(int columnIndex, double x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setDouble(columnIndex, x); } else { _Inserter.setDouble(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a BigDecimal value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setBigDecimal(columnIndex, x); } else { _Inserter.setBigDecimal(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a String value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateString(int columnIndex, String x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setString(columnIndex, x); } else { _Inserter.setString(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a byte array value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBytes(int columnIndex, byte x[]) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setBytes(columnIndex, x); } else { _Inserter.setBytes(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a Date value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateDate(int columnIndex, java.sql.Date x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setDate(columnIndex, x); } else { _Inserter.setDate(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a Time value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateTime(int columnIndex, java.sql.Time x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setTime(columnIndex, x); } else { _Inserter.setTime(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a Timestamp value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateTimestamp(int columnIndex, java.sql.Timestamp x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setTimestamp(columnIndex, x); } else { _Inserter.setTimestamp(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with an ascii stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database-access error occurs */ public void updateAsciiStream( int columnIndex, java.io.InputStream x, int length) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setAsciiStream(columnIndex, x, length); } else { _Inserter.setAsciiStream(columnIndex, x, length); } } /** * JDBC 2.0 * * Update a column with a binary stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database-access error occurs */ public void updateBinaryStream( int columnIndex, java.io.InputStream x, int length) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setBinaryStream(columnIndex, x, length); } else { _Inserter.setBinaryStream(columnIndex, x, length); } } /** * JDBC 2.0 * * Update a column with a character stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param length the length of the stream * @exception SQLException if a database-access error occurs */ public void updateCharacterStream( int columnIndex, java.io.Reader x, int length) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setCharacterStream(columnIndex, x, length); } else { _Inserter.setCharacterStream(columnIndex, x, length); } } /** * JDBC 2.0 * * Update a column with an Object value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. * @exception SQLException if a database-access error occurs */ public void updateObject(int columnIndex, Object x, int scale) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setObject(columnIndex, x); } else { _Inserter.setObject(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with an Object value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnIndex the first column is 1, the second is 2, ... * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateObject(int columnIndex, Object x) throws SQLException { if (!_on_insert_row) { if (!_doing_updates) { _doing_updates = true; syncUpdate(); } _Updater.setObject(columnIndex, x); } else { _Inserter.setObject(columnIndex, x); } } /** * JDBC 2.0 * * Update a column with a null value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @exception SQLException if a database-access error occurs */ public void updateNull(String columnName) throws SQLException { updateNull(findColumn(columnName)); } /** * JDBC 2.0 * * Update a column with a boolean value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBoolean(String columnName, boolean x) throws SQLException { updateBoolean(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a byte value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateByte(String columnName, byte x) throws SQLException { updateByte(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a short value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateShort(String columnName, short x) throws SQLException { updateShort(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with an integer value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateInt(String columnName, int x) throws SQLException { updateInt(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a long value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateLong(String columnName, long x) throws SQLException { updateLong(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a float value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateFloat(String columnName, float x) throws SQLException { updateFloat(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a double value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateDouble(String columnName, double x) throws SQLException { updateDouble(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a BigDecimal value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException { updateBigDecimal(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a String value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateString(String columnName, String x) throws SQLException { updateString(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a byte array value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateBytes(String columnName, byte x[]) throws SQLException { updateBytes(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a Date value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateDate(String columnName, java.sql.Date x) throws SQLException { updateDate(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a Time value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateTime(String columnName, java.sql.Time x) throws SQLException { updateTime(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with a Timestamp value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateTimestamp(String columnName, java.sql.Timestamp x) throws SQLException { updateTimestamp(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with an ascii stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param length of the stream * @exception SQLException if a database-access error occurs */ public void updateAsciiStream( String columnName, java.io.InputStream x, int length) throws SQLException { updateAsciiStream(findColumn(columnName), x, length); } /** * JDBC 2.0 * * Update a column with a binary stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param length of the stream * @exception SQLException if a database-access error occurs */ public void updateBinaryStream( String columnName, java.io.InputStream x, int length) throws SQLException { updateBinaryStream(findColumn(columnName), x, length); } /** * JDBC 2.0 * * Update a column with a character stream value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param length of the stream * @exception SQLException if a database-access error occurs */ public void updateCharacterStream( String columnName, java.io.Reader reader, int length) throws SQLException { updateCharacterStream(findColumn(columnName), reader,length); } /** * JDBC 2.0 * * Update a column with an Object value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @param scale For java.sql.Types.DECIMAL or java.sql.Types.NUMERIC types * this is the number of digits after the decimal. For all other * types this value will be ignored. * @exception SQLException if a database-access error occurs */ public void updateObject(String columnName, Object x, int scale) throws SQLException { updateObject(findColumn(columnName), x); } /** * JDBC 2.0 * * Update a column with an Object value. * * The updateXXX() methods are used to update column values in the * current row, or the insert row. The updateXXX() methods do not * update the underlying database, instead the updateRow() or insertRow() * methods are called to update the database. * * @param columnName the name of the column * @param x the new column value * @exception SQLException if a database-access error occurs */ public void updateObject(String columnName, Object x) throws SQLException { updateObject(findColumn(columnName), x); } /** * JDBC 2.0 * * Insert the contents of the insert row into the result set and * the database. Must be on the insert row when this method is called. * * @exception SQLException if a database-access error occurs, * if called when not on the insert row, or if all non-nullable columns in * the insert row have not been given a value */ public void insertRow() throws SQLException { if (!_on_insert_row) { throw new SQLException("Not on insert row"); } else { _Inserter.executeUpdate(); int numPrimaryKeys = 0; if (_PrimaryKeyIndicies != null) { numPrimaryKeys = _PrimaryKeyIndicies.size(); } long autoIncrementId = _Inserter.getLastInsertID(); int num_fields = _fields.length; byte[][] NewRow = new byte[num_fields][]; for (int i = 0; i < num_fields; i++) { if (_Inserter.isNull(i)) { NewRow[i] = null; } else { NewRow[i] = _Inserter.getBytes(i); } if (numPrimaryKeys == 1 && _fields[i].isPrimaryKey() && autoIncrementId > 0) { NewRow[i] = String.valueOf(autoIncrementId).getBytes(); } } _rows.addElement(NewRow); resetInserter(); } } /** * JDBC 2.0 * * Update the underlying database with the new contents of the * current row. Cannot be called when on the insert row. * * @exception SQLException if a database-access error occurs, or * if called when on the insert row */ public void updateRow() throws SQLException { if (!_updatable) { throw new SQLException(UPDATEABLE_MESSAGE, "S1000"); } if (_doing_updates) { _Updater.executeUpdate(); //int num_fields = Fields.length; //for (int i = 0; i < num_fields; i++) { // if (_Updater.isNull(i)) { // System.out.println("isNull(" + i + ") = true"); // This_Row[i] = null; // } // else { // System.out.println("_Updater.getBytes(i) = " + new String(_Updater.getBytes(i))); // // This_Row[i] = _Updater.getBytes(i); // } //} refreshRow(); _doing_updates = false; } // // fixes calling updateRow() and then doing more // updates on same row... syncUpdate(); } /** * JDBC 2.0 * * Delete the current row from the result set and the underlying * database. Cannot be called when on the insert row. * * @exception SQLException if a database-access error occurs, or if * called when on the insert row. */ public void deleteRow() throws SQLException { if (!_updatable) { throw new SQLException(UPDATEABLE_MESSAGE, "S1000"); } if (_on_insert_row) { throw new SQLException("Can not call deleteRow() when on insert row"); } else if (_rows.size() == 0) { throw new SQLException("Can't deleteRow() on empty result set"); } else if (isBeforeFirst()) { throw new SQLException("Before start of result set. Can not call deleteRow()."); } else if (isAfterLast()) { throw new SQLException("After end of result set. Can not call deleteRow()."); } if (_Deleter == null) { if (_DeleteSQL == null) { generateStatements(); } _Deleter = (com.mysql.jdbc.jdbc2.PreparedStatement) _connection.prepareStatement(_DeleteSQL); } _Deleter.clearParameters(); String Encoding = null; if (_connection.useUnicode()) { Encoding = _connection.getEncoding(); } try { int num_keys = _PrimaryKeyIndicies.size(); if (num_keys == 1) { int index = ((Integer) _PrimaryKeyIndicies.elementAt(0)).intValue(); String CurrentVal = (Encoding == null ? new String(_thisRow[index]) : new String(_thisRow[index], Encoding)); _Deleter.setString(1, CurrentVal); } else { for (int i = 0; i < num_keys; i++) { int index = ((Integer) _PrimaryKeyIndicies.elementAt(i)).intValue(); String CurrentVal = (Encoding == null ? new String(_thisRow[index]) : new String(_thisRow[index], Encoding)); _Deleter.setString(i + 1, CurrentVal); } } _Deleter.executeUpdate(); _rows.removeElementAt(_currentRow); } catch (java.io.UnsupportedEncodingException UE) { throw new SQLException( "Unsupported character encoding '" + _connection.getEncoding() + "'"); } } /** * JDBC 2.0 * * Refresh the value of the current row with its current value in * the database. Cannot be called when on the insert row. * * The refreshRow() method provides a way for an application to * explicitly tell the JDBC driver to refetch a row(s) from the * database. An application may want to call refreshRow() when * caching or prefetching is being done by the JDBC driver to * fetch the latest value of a row from the database. The JDBC driver * may actually refresh multiple rows at once if the fetch size is * greater than one. * * All values are refetched subject to the transaction isolation * level and cursor sensitivity. If refreshRow() is called after * calling updateXXX(), but before calling updateRow() then the * updates made to the row are lost. Calling refreshRow() frequently * will likely slow performance. * * @exception SQLException if a database-access error occurs, or if * called when on the insert row. */ public void refreshRow() throws SQLException { if (!_updatable) { throw new SQLException(UPDATEABLE_MESSAGE, "S1000"); } if (_on_insert_row) { throw new SQLException("Can not call refreshRow() when on insert row"); } else if (_rows.size() == 0) { throw new SQLException("Can't refreshRow() on empty result set"); } else if (isBeforeFirst()) { throw new SQLException("Before start of result set. Can not call refreshRow()."); } else if (isAfterLast()) { throw new SQLException("After end of result set. Can not call refreshRow()."); } if (_Refresher == null) { if (_RefreshSQL == null) { generateStatements(); } _Refresher = (com.mysql.jdbc.jdbc2.PreparedStatement) _connection.prepareStatement(_RefreshSQL); } _Refresher.clearParameters(); String Encoding = null; if (_connection.useUnicode()) { Encoding = _connection.getEncoding(); } try { int num_keys = _PrimaryKeyIndicies.size(); if (num_keys == 1) { int index = ((Integer) _PrimaryKeyIndicies.elementAt(0)).intValue(); String CurrentVal = (Encoding == null ? new String(_thisRow[index]) : new String(_thisRow[index], Encoding)); _Refresher.setString(1, CurrentVal); } else { for (int i = 0; i < num_keys; i++) { int index = ((Integer) _PrimaryKeyIndicies.elementAt(i)).intValue(); String CurrentVal = (Encoding == null ? new String(_thisRow[index]) : new String(_thisRow[index], Encoding)); _Refresher.setString(i + 1, CurrentVal); } } java.sql.ResultSet rs = null; try { rs = _Refresher.executeQuery(); int numCols = rs.getMetaData().getColumnCount(); if (rs.next()) { for (int i = 0; i < numCols; i++) { byte[] val = rs.getBytes(i + 1); if (val == null || rs.wasNull()) { _thisRow[i] = null; } else { _thisRow[i] = rs.getBytes(i + 1); } } } else { throw new SQLException("refreshRow() called on row that has been deleted or had primary key changed", "S1000"); } } finally { if (rs != null) { try { rs.close(); } catch (Exception ex) {} } } } catch (java.io.UnsupportedEncodingException UE) { throw new SQLException( "Unsupported character encoding '" + _connection.getEncoding() + "'"); } } /** * JDBC 2.0 * * The cancelRowUpdates() method may be called after calling an * updateXXX() method(s) and before calling updateRow() to rollback * the updates made to a row. If no updates have been made or * updateRow() has already been called, then this method has no * effect. * * @exception SQLException if a database-access error occurs, or if * called when on the insert row. * */ public void cancelRowUpdates() throws SQLException { if (_doing_updates) { _doing_updates = false; _Updater.clearParameters(); } } /** * JDBC 2.0 * * Move to the insert row. The current cursor position is * remembered while the cursor is positioned on the insert row. * * The insert row is a special row associated with an updatable * result set. It is essentially a buffer where a new row may * be constructed by calling the updateXXX() methods prior to * inserting the row into the result set. * * Only the updateXXX(), getXXX(), and insertRow() methods may be * called when the cursor is on the insert row. All of the columns in * a result set must be given a value each time this method is * called before calling insertRow(). UpdateXXX()must be called before * getXXX() on a column. * * @exception SQLException if a database-access error occurs, * or the result set is not updatable */ public void moveToInsertRow() throws SQLException { if (!_updatable) { throw new SQLException(UPDATEABLE_MESSAGE, "S1000"); } if (_Inserter == null) { generateStatements(); _Inserter = (com.mysql.jdbc.jdbc2.PreparedStatement) _connection.prepareStatement(_InsertSQL); resetInserter(); } else { resetInserter(); } _on_insert_row = true; _doing_updates = false; } /** * JDBC 2.0 * * Move the cursor to the remembered cursor position, usually the * current row. Has no effect unless the cursor is on the insert * row. * * @exception SQLException if a database-access error occurs, * or the result set is not updatable */ public void moveToCurrentRow() throws SQLException { if (!_updatable) { throw new SQLException(UPDATEABLE_MESSAGE, "S1000"); } _on_insert_row = false; } /** * JDBC 2.0 * * Return the Statement that produced the ResultSet. * * @return the Statment that produced the result set, or * null if the result was produced some other way. * @exception SQLException if a database-access error occurs */ public java.sql.Statement getStatement() throws SQLException { return (java.sql.Statement) _owningStatement; } /** * JDBC 2.0 * * Returns the value of column @i as a Java object. Use the * @map to determine the class from which to construct data of * SQL structured and distinct types. * * @param i the first column is 1, the second is 2, ... * @param map the mapping from SQL type names to Java classes * @return an object representing the SQL value */ public Object getObject(int i, java.util.Map map) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get a REF(<structured-type>) column. * * @param i the first column is 1, the second is 2, ... * @return an object representing data of an SQL REF type */ public java.sql.Ref getRef(int i) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get a BLOB column. * * @param i the first column is 1, the second is 2, ... * @return an object representing a BLOB */ public java.sql.Blob getBlob(int columnIndex) throws SQLException { checkRowPos(); if (columnIndex < 1 || columnIndex > _fields.length) { throw new java.sql.SQLException( "Column Index out of range ( " + columnIndex + " > " + _fields.length + ").", "S1002"); } try { if (_thisRow[columnIndex - 1] == null) { _wasNullFlag = true; } else { _wasNullFlag = false; } } catch (NullPointerException E) { _wasNullFlag = true; } if (_wasNullFlag) { return null; } return new Blob(_thisRow[columnIndex - 1]); } /** * JDBC 2.0 * * Get a CLOB column. * * @param i the first column is 1, the second is 2, ... * @return an object representing a CLOB */ public java.sql.Clob getClob(int i) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get an array column. * * @param i the first column is 1, the second is 2, ... * @return an object representing an SQL array */ public java.sql.Array getArray(int i) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Returns the value of column @i as a Java object. Use the * @map to determine the class from which to construct data of * SQL structured and distinct types. * * @param colName the column name * @param map the mapping from SQL type names to Java classes * @return an object representing the SQL value */ public Object getObject(String colName, java.util.Map map) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get a REF(<structured-type>) column. * * @param colName the column name * @return an object representing data of an SQL REF type */ public java.sql.Ref getRef(String colName) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get a BLOB column. * * @param colName the column name * @return an object representing a BLOB */ public java.sql.Blob getBlob(String colName) throws SQLException { return getBlob(findColumn(colName)); } /** * JDBC 2.0 * * Get a CLOB column. * * @param colName the column name * @return an object representing a CLOB */ public java.sql.Clob getClob(String colName) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get an array column. * * @param colName the column name * @return an object representing an SQL array */ public java.sql.Array getArray(String colName) throws SQLException { throw new NotImplemented(); } /** * JDBC 2.0 * * Get the value of a column in the current row as a java.sql.Date * object. Use the calendar to construct an appropriate millisecond * value for the Date, if the underlying database doesn't store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the date * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Date getDate(int columnIndex, Calendar cal) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a java.sql.Date * object. Use the calendar to construct an appropriate millisecond * value for the Date, if the underlying database doesn't store * timezone information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the date * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Date getDate(String columnName, Calendar cal) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a java.sql.Time * object. Use the calendar to construct an appropriate millisecond * value for the Time, if the underlying database doesn't store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the time * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Time getTime(int columnIndex, Calendar cal) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a java.sql.Time * object. Use the calendar to construct an appropriate millisecond * value for the Time, if the underlying database doesn't store * timezone information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the time * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Time getTime(String columnName, Calendar cal) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a java.sql.Timestamp * object. Use the calendar to construct an appropriate millisecond * value for the Timestamp, if the underlying database doesn't store * timezone information. * * @param columnIndex the first column is 1, the second is 2, ... * @param cal the calendar to use in constructing the timestamp * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { throw new NotImplemented(); } /** * Get the value of a column in the current row as a java.sql.Timestamp * object. Use the calendar to construct an appropriate millisecond * value for the Timestamp, if the underlying database doesn't store * timezone information. * * @param columnName is the SQL name of the column * @param cal the calendar to use in constructing the timestamp * @return the column value; if the value is SQL NULL, the result is null * @exception SQLException if a database-access error occurs. */ public java.sql.Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException { throw new NotImplemented(); } // **************************************************************** // // END OF PUBLIC INTERFACE // // **************************************************************** /** * Create a new ResultSet - Note that we create ResultSets to * represent the results of everything. * * @param Fields an array of field data * @param Tuples Vector of the actual data */ public ResultSet( com.mysql.jdbc.Field[] Fields, Vector Tuples, com.mysql.jdbc.Connection Conn) { super(Fields, Tuples, Conn); _updatable = isUpdateable(); } public ResultSet(com.mysql.jdbc.Field[] Fields, Vector Tuples) { super(Fields, Tuples); } /** * Create a result set for an executeUpdate statement. * * @param updateCount the number of rows affected by the update */ public ResultSet(long updateCount, long updateID) { super(updateCount, updateID); } /** * Figure out whether or not this ResultSet is updateable, * and if so, generate the PreparedStatements to support updates. */ protected void generateStatements() throws SQLException { if (!_updatable) { throw new SQLException("ResultSet not updatable"); } boolean useQuotedIdentifiers = _connection.supportsQuotedIdentifiers(); String quotedId = getQuotedIdChar(); String TableName = _fields[0].getTableName(); _PrimaryKeyIndicies = new Vector(); StringBuffer FieldValues = new StringBuffer(); StringBuffer KeyValues = new StringBuffer(); StringBuffer ColumnNames = new StringBuffer(); StringBuffer InsertPlaceHolders = new StringBuffer(); boolean first_time = true; boolean keys_first_time = true; for (int i = 0; i < _fields.length; i++) { if (_fields[i].isPrimaryKey()) { _PrimaryKeyIndicies.addElement(new Integer(i)); if (!keys_first_time) { KeyValues.append(" AND "); } else { keys_first_time = false; } if (useQuotedIdentifiers) { KeyValues.append(quotedId); } KeyValues.append(_fields[i].getName()); if (useQuotedIdentifiers) { KeyValues.append(quotedId); } KeyValues.append("=?"); } if (first_time) { first_time = false; FieldValues.append("SET "); } else { FieldValues.append(","); ColumnNames.append(","); InsertPlaceHolders.append(","); } InsertPlaceHolders.append("?"); if (useQuotedIdentifiers) { ColumnNames.append(quotedId); } ColumnNames.append(_fields[i].getName()); if (useQuotedIdentifiers) { ColumnNames.append(quotedId); } if (useQuotedIdentifiers) { FieldValues.append(quotedId); } FieldValues.append(_fields[i].getName()); if (useQuotedIdentifiers) { FieldValues.append(quotedId); } FieldValues.append("=?"); } String quotedIdStr = useQuotedIdentifiers ? quotedId : ""; _UpdateSQL = "UPDATE " + quotedIdStr + TableName + quotedIdStr + " " + FieldValues.toString() + " WHERE " + KeyValues.toString(); _InsertSQL = "INSERT INTO " + quotedIdStr + TableName + quotedIdStr + " (" + ColumnNames.toString() + ") VALUES (" + InsertPlaceHolders.toString() + ")"; _RefreshSQL = "SELECT " + ColumnNames.toString() + " FROM " + quotedIdStr + TableName + quotedIdStr + " WHERE " + KeyValues.toString(); _DeleteSQL = "DELETE FROM " + quotedIdStr + TableName + quotedIdStr + " WHERE " + KeyValues.toString(); } static private String quotedIdChar = null; private synchronized String getQuotedIdChar() throws SQLException { if (quotedIdChar == null) { java.sql.DatabaseMetaData dbmd = _connection.getMetaData(); quotedIdChar = dbmd.getIdentifierQuoteString(); } return quotedIdChar; } /** * Reset UPDATE prepared statement to value in current row. * * This_Row MUST point to current, valid row. */ void syncUpdate() throws SQLException { if (_Updater == null) { if (_UpdateSQL == null) { generateStatements(); } _Updater = (com.mysql.jdbc.jdbc2.PreparedStatement) _connection.prepareStatement(_UpdateSQL); } int num_fields = _fields.length; _Updater.clearParameters(); for (int i = 0; i < num_fields; i++) { if (_thisRow[i] != null) { _Updater.setBytes(i + 1, _thisRow[i]); } else { _Updater.setNull(i + 1, 0); } } int num_keys = _PrimaryKeyIndicies.size(); if (num_keys == 1) { int index = ((Integer) _PrimaryKeyIndicies.elementAt(0)).intValue(); _Updater.setBytes( num_fields + 1, _thisRow[((Integer) _PrimaryKeyIndicies.elementAt(0)).intValue()]); } else { for (int i = 0; i < num_keys; i++) { byte[] currentVal = _thisRow[((Integer) _PrimaryKeyIndicies.elementAt(i)).intValue()]; if (currentVal != null) { _Updater.setBytes(num_fields + i + 1, currentVal); } else { _Updater.setNull(num_fields + i + 1, 0); } } } } /** * Is this ResultSet updateable? */ boolean isUpdateable() { if (_fields.length > 0) { String TableName = _fields[0].getTableName(); // // References only one table? // for (int i = 1; i < _fields.length; i++) { if (TableName == null || !_fields[i].getTableName().equals(TableName)) { return false; } } if (TableName == null || TableName.length() == 0) { return false; } } else { return false; } // // Contains the primary key? // boolean has_primary_key = false; for (int i = 0; i < _fields.length; i++) { if (_fields[i].isPrimaryKey()) { has_primary_key = true; break; } } if (!has_primary_key) { return false; } return true; } /** * Allows Statements to determine the type of result set they ended * up building. */ int getResultSetType() { return 0; } private void resetUpdater() throws SQLException { _Updater.clearParameters(); for (int i = 0; i < _fields.length; i++) { _Updater.setNull(i + 1, 0); } } private void resetInserter() throws SQLException { _Inserter.clearParameters(); for (int i = 0; i < _fields.length; i++) { _Inserter.setNull(i + 1, 0); } } /** * Sets the concurrency (JDBC2) */ protected void setResultSetConcurrency(int concurrencyFlag) { super.setResultSetConcurrency(concurrencyFlag); // // Issue warning is asked for updateable result set, but result set is not // updatable // if (concurrencyFlag == CONCUR_UPDATABLE && !isUpdateable()) { java.sql.SQLWarning warning = new java.sql.SQLWarning(UPDATEABLE_MESSAGE); } } }