UpdatableResultSet.java
资源名称:bookshop.zip [点击查看]
上传用户:sxlinghang
上传日期:2022-07-20
资源大小:1405k
文件大小:77k
源码类别:
数据库编程
开发平台:
Java
- /*
- Copyright (C) 2002 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- 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 java.io.UnsupportedEncodingException;
- import java.math.BigDecimal;
- import java.sql.SQLException;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- /**
- * A result set that is updatable.
- *
- * @author Mark Matthews
- */
- public class UpdatableResultSet extends ResultSet {
- /** Marker for 'stream' data when doing INSERT rows */
- private final static byte[] STREAM_DATA_MARKER = "** STREAM DATA **"
- .getBytes();
- /** List of primary keys */
- private List primaryKeyIndicies = null;
- /** PreparedStatement used to delete data */
- private com.mysql.jdbc.PreparedStatement deleter = null;
- /** PreparedStatement used to insert data */
- private com.mysql.jdbc.PreparedStatement inserter = null;
- /** PreparedStatement used to refresh data */
- private com.mysql.jdbc.PreparedStatement refresher;
- /** PreparedStatement used to delete data */
- private com.mysql.jdbc.PreparedStatement updater = null;
- private SingleByteCharsetConverter charConverter;
- private String charEncoding;
- private String deleteSQL = null;
- private String insertSQL = null;
- private String quotedIdChar = null;
- private String refreshSQL = null;
- private String tableName;
- /** SQL for in-place modifcation */
- private String updateSQL = null;
- /** What is the default value for the column? */
- private byte[][] defaultColumnValue;
- /** The binary data for the 'current' row */
- private byte[][] savedCurrentRow;
- /** Is this result set updateable? */
- private boolean isUpdatable = false;
- /**
- * Creates a new UpdatableResultSet object.
- *
- * @param updateCount DOCUMENT ME!
- * @param updateID DOCUMENT ME!
- */
- public UpdatableResultSet(long updateCount, long updateID) {
- super(updateCount, updateID);
- }
- // ****************************************************************
- //
- // END OF PUBLIC INTERFACE
- //
- // ****************************************************************
- /**
- * Create a new ResultSet - Note that we create ResultSets to represent the
- * results of everything.
- *
- * @param catalog the database in use when this result set was created
- * @param fields an array of Field objects (basically, the ResultSet
- * MetaData)
- * @param rows Vector of the actual data
- * @param conn the status string returned from the back end
- *
- * @throws SQLException DOCUMENT ME!
- */
- public UpdatableResultSet(String catalog, Field[] fields, RowData rows,
- com.mysql.jdbc.Connection conn) throws SQLException {
- super(catalog, fields, rows, conn);
- isUpdatable = checkUpdatability();
- }
- /**
- * Creates a new UpdatableResultSet object.
- *
- * @param fields DOCUMENT ME!
- * @param rows DOCUMENT ME!
- *
- * @throws SQLException DOCUMENT ME!
- */
- public UpdatableResultSet(Field[] fields, RowData rows)
- throws SQLException {
- super(fields, rows);
- isUpdatable = checkUpdatability();
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Determine if the cursor is after the last row in the result set.
- * </p>
- *
- * @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 synchronized boolean isAfterLast() throws SQLException {
- return super.isAfterLast();
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Determine if the cursor is before the first row in the result set.
- * </p>
- *
- * @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 synchronized boolean isBeforeFirst() throws SQLException {
- return super.isBeforeFirst();
- }
- /**
- * 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 (isUpdatable ? CONCUR_UPDATABLE : CONCUR_READ_ONLY);
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Determine if the cursor is on the first row of the result set.
- * </p>
- *
- * @return true if on the first row, false otherwise.
- *
- * @exception SQLException if a database-access error occurs.
- */
- public synchronized boolean isFirst() throws SQLException {
- return super.isFirst();
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * 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.
- * </p>
- *
- * @return true if on the last row, false otherwise.
- *
- * @exception SQLException if a database-access error occurs.
- */
- public synchronized boolean isLast() throws SQLException {
- return super.isLast();
- }
- /**
- * 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 DOCUMENT ME!
- *
- * @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 synchronized boolean absolute(int row) throws SQLException {
- return super.absolute(row);
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Moves to the end of the result set, just after the last row. Has no
- * effect if the result set contains no rows.
- * </p>
- *
- * @exception SQLException if a database-access error occurs, or result set
- * type is TYPE_FORWARD_ONLY.
- */
- public synchronized void afterLast() throws SQLException {
- super.afterLast();
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Moves to the front of the result set, just before the first row. Has no
- * effect if the result set contains no rows.
- * </p>
- *
- * @exception SQLException if a database-access error occurs, or result set
- * type is TYPE_FORWARD_ONLY
- */
- public synchronized void beforeFirst() throws SQLException {
- super.beforeFirst();
- }
- /**
- * 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 synchronized void cancelRowUpdates() throws SQLException {
- if (doingUpdates) {
- doingUpdates = false;
- updater.clearParameters();
- }
- }
- /**
- * After this call, getWarnings returns null until a new warning is
- * reported for this ResultSet
- *
- * @exception java.sql.SQLException if a database access error occurs
- */
- public synchronized void clearWarnings() throws java.sql.SQLException {
- warningChain = null;
- }
- /**
- * In some cases, it is desirable to immediately release a ResultSet
- * database and JDBC resources instead of waiting for this to happen when
- * it is automatically closed. The close method provides this immediate
- * release.
- *
- * <p>
- * <B>Note:</B> A ResultSet is automatically closed by the Statement 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. A ResultSet is also automatically closed when it is garbage
- * collected.
- * </p>
- *
- * @exception java.sql.SQLException if a database access error occurs
- */
- public synchronized void close() throws java.sql.SQLException {
- super.close();
- }
- /**
- * 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.
- * @throws SQLException if the ResultSet is not updatable or some other
- * error occurs
- */
- public synchronized void deleteRow() throws SQLException {
- if (!isUpdatable) {
- throw new NotUpdatable();
- }
- if (onInsertRow) {
- throw new SQLException(
- "Can not call deleteRow() when on insert row");
- } else if (rowData.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.PreparedStatement) connection
- .prepareStatement(deleteSQL);
- if (deleter.getMaxRows() != 0) {
- deleter.setMaxRows(0);
- }
- }
- deleter.clearParameters();
- String characterEncoding = null;
- if (connection.useUnicode()) {
- characterEncoding = connection.getEncoding();
- }
- //
- // FIXME: Use internal routines where possible for character
- // conversion!
- try {
- int numKeys = primaryKeyIndicies.size();
- if (numKeys == 1) {
- int index = ((Integer) primaryKeyIndicies.get(0)).intValue();
- String currentVal = ((characterEncoding == null)
- ? new String(thisRow[index])
- : new String(thisRow[index], characterEncoding));
- deleter.setString(1, currentVal);
- } else {
- for (int i = 0; i < numKeys; i++) {
- int index = ((Integer) primaryKeyIndicies.get(i)).intValue();
- String currentVal = ((characterEncoding == null)
- ? new String(thisRow[index])
- : new String(thisRow[index], characterEncoding));
- deleter.setString(i + 1, currentVal);
- }
- }
- deleter.executeUpdate();
- rowData.removeRow(rowData.getCurrentRowNumber());
- } catch (java.io.UnsupportedEncodingException encodingEx) {
- throw new SQLException("Unsupported character encoding '"
- + connection.getEncoding() + "'");
- }
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Moves to the first row in the result set.
- * </p>
- *
- * @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 synchronized boolean first() throws SQLException {
- return super.first();
- }
- /**
- * 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 synchronized void insertRow() throws SQLException {
- if (!onInsertRow) {
- throw new SQLException("Not on insert row");
- } else {
- inserter.executeUpdate();
- int numPrimaryKeys = 0;
- if (primaryKeyIndicies != null) {
- numPrimaryKeys = primaryKeyIndicies.size();
- }
- long autoIncrementId = inserter.getLastInsertID();
- int numFields = fields.length;
- byte[][] newRow = new byte[numFields][];
- for (int i = 0; i < numFields; 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();
- }
- }
- rowData.addRow(newRow);
- resetInserter();
- }
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Moves to the last row in the result set.
- * </p>
- *
- * @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 synchronized boolean last() throws SQLException {
- return super.last();
- }
- /**
- * 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
- * @throws SQLException if the ResultSet is not updatable or some other
- * error occurs
- */
- public synchronized void moveToCurrentRow() throws SQLException {
- if (!isUpdatable) {
- throw new NotUpdatable();
- }
- if (this.onInsertRow) {
- onInsertRow = false;
- this.thisRow = this.savedCurrentRow;
- }
- }
- /**
- * 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
- * @throws NotUpdatable DOCUMENT ME!
- */
- public synchronized void moveToInsertRow() throws SQLException {
- if (!this.isUpdatable) {
- throw new NotUpdatable();
- }
- if (this.inserter == null) {
- generateStatements();
- this.inserter = (com.mysql.jdbc.PreparedStatement) connection
- .prepareStatement(this.insertSQL);
- if (this.inserter.getMaxRows() != 0) {
- this.inserter.setMaxRows(0);
- }
- extractDefaultValues();
- resetInserter();
- } else {
- resetInserter();
- }
- int numFields = this.fields.length;
- this.onInsertRow = true;
- this.doingUpdates = false;
- this.savedCurrentRow = this.thisRow;
- this.thisRow = new byte[numFields][];
- for (int i = 0; i < numFields; i++) {
- if (this.defaultColumnValue[i] != null) {
- this.inserter.setBytes(i + 1, this.defaultColumnValue[i]);
- // This value _could_ be changed from a getBytes(), so we
- // need a copy....
- byte[] defaultValueCopy = new byte[this.defaultColumnValue[i].length];
- System.arraycopy(defaultColumnValue[i], 0, defaultValueCopy, 0, defaultValueCopy.length);
- this.thisRow[i] = defaultValueCopy;
- } else {
- this.inserter.setNull(i + 1, java.sql.Types.NULL);
- this.thisRow[i] = null;
- }
- }
- }
- /**
- * A ResultSet is initially positioned before its first row, the first call
- * to next makes the first row the current row; the second call makes the
- * second row the current row, etc.
- *
- * <p>
- * If an input stream from the previous row is open, it is implicitly
- * closed. The ResultSet's warning chain is cleared when a new row is
- * read
- * </p>
- *
- * @return true if the new current is valid; false if there are no more
- * rows
- *
- * @exception java.sql.SQLException if a database access error occurs
- */
- public synchronized boolean next() throws java.sql.SQLException {
- return super.next();
- }
- /**
- * The prev method is not part of JDBC, but because of the architecture of
- * this driver it is possible to move both forward and backward within the
- * result set.
- *
- * <p>
- * If an input stream from the previous row is open, it is implicitly
- * closed. The ResultSet's warning chain is cleared when a new row is
- * read
- * </p>
- *
- * @return true if the new current is valid; false if there are no more
- * rows
- *
- * @exception java.sql.SQLException if a database access error occurs
- */
- public synchronized boolean prev() throws java.sql.SQLException {
- return super.prev();
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * Moves to the previous row in the result set.
- * </p>
- *
- * <p>
- * Note: previous() is not the same as relative(-1) since it makes sense to
- * call previous() when there is no current row.
- * </p>
- *
- * @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 synchronized boolean previous() throws SQLException {
- return super.previous();
- }
- /**
- * 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.
- * @throws NotUpdatable DOCUMENT ME!
- */
- public synchronized void refreshRow() throws SQLException {
- if (!isUpdatable) {
- throw new NotUpdatable();
- }
- if (onInsertRow) {
- throw new SQLException(
- "Can not call refreshRow() when on insert row");
- } else if (rowData.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.PreparedStatement) connection
- .prepareStatement(refreshSQL);
- if (refresher.getMaxRows() != 0) {
- refresher.setMaxRows(0);
- }
- }
- refresher.clearParameters();
- int numKeys = primaryKeyIndicies.size();
- if (numKeys == 1) {
- byte[] dataFrom = null;
- int index = ((Integer) primaryKeyIndicies.get(0)).intValue();
- if (!doingUpdates) {
- dataFrom = thisRow[index];
- } else {
- dataFrom = updater.getBytes(index);
- // Primary keys not set?
- if (updater.isNull(index) || (dataFrom.length == 0)) {
- dataFrom = thisRow[index];
- }
- }
- refresher.setBytesNoEscape(1, dataFrom);
- } else {
- for (int i = 0; i < numKeys; i++) {
- byte[] dataFrom = null;
- int index = ((Integer) primaryKeyIndicies.get(i)).intValue();
- if (!doingUpdates) {
- dataFrom = thisRow[index];
- } else {
- dataFrom = updater.getBytes(index);
- // Primary keys not set?
- if (updater.isNull(index) || (dataFrom.length == 0)) {
- dataFrom = thisRow[index];
- }
- }
- refresher.setBytesNoEscape(i + 1, dataFrom);
- }
- }
- 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",
- SQLError.SQL_STATE_GENERAL_ERROR);
- }
- } finally {
- if (rs != null) {
- try {
- rs.close();
- } catch (SQLException ex) {
- ; // ignore
- }
- }
- }
- }
- /**
- * JDBC 2.0
- *
- * <p>
- * 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.
- * </p>
- *
- * <p>
- * 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.
- * </p>
- *
- * @param rows DOCUMENT ME!
- *
- * @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 synchronized boolean relative(int rows) throws SQLException {
- return super.relative(rows);
- }
- /**
- * 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
- * @throws NotImplemented DOCUMENT ME!
- *
- * @see DatabaseMetaData#deletesAreDetected
- */
- public synchronized boolean rowDeleted() 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
- * @throws NotImplemented DOCUMENT ME!
- *
- * @see DatabaseMetaData#insertsAreDetected
- */
- public synchronized boolean rowInserted() throws SQLException {
- throw new NotImplemented();
- }
- //---------------------------------------------------------------------
- // 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
- * @throws NotImplemented DOCUMENT ME!
- *
- * @see DatabaseMetaData#updatesAreDetected
- */
- public synchronized boolean rowUpdated() throws SQLException {
- throw new NotImplemented();
- }
- /**
- * 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 synchronized void updateAsciiStream(int columnIndex,
- java.io.InputStream x, int length) throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setAsciiStream(columnIndex, x, length);
- } else {
- inserter.setAsciiStream(columnIndex, x, length);
- this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
- }
- }
- /**
- * 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 synchronized 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 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 synchronized void updateBigDecimal(int columnIndex, BigDecimal x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setBigDecimal(columnIndex, x);
- } else {
- inserter.setBigDecimal(columnIndex, x);
- if (x == null) {
- this.thisRow[columnIndex - 1] = null;
- } else {
- this.thisRow[columnIndex - 1] = x.toString().getBytes();
- }
- }
- }
- /**
- * 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 synchronized void updateBigDecimal(String columnName, BigDecimal x)
- throws SQLException {
- updateBigDecimal(findColumn(columnName), x);
- }
- /**
- * 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 synchronized void updateBinaryStream(int columnIndex,
- java.io.InputStream x, int length) throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setBinaryStream(columnIndex, x, length);
- } else {
- inserter.setBinaryStream(columnIndex, x, length);
- if (x == null) {
- this.thisRow[columnIndex - 1] = null;
- } else {
- this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
- }
- }
- }
- /**
- * 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 synchronized void updateBinaryStream(String columnName,
- java.io.InputStream x, int length) throws SQLException {
- updateBinaryStream(findColumn(columnName), x, length);
- }
- /**
- * @see ResultSet#updateBlob(int, Blob)
- */
- public void updateBlob(int columnIndex, java.sql.Blob blob)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setBlob(columnIndex, blob);
- } else {
- inserter.setBlob(columnIndex, blob);
- if (blob == null) {
- this.thisRow[columnIndex - 1] = null;
- } else {
- this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
- }
- }
- }
- /**
- * @see ResultSet#updateBlob(String, Blob)
- */
- public void updateBlob(String columnName, java.sql.Blob blob)
- throws SQLException {
- updateBlob(findColumn(columnName), blob);
- }
- /**
- * 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 synchronized void updateBoolean(int columnIndex, boolean x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setBoolean(columnIndex, x);
- } else {
- inserter.setBoolean(columnIndex, x);
- this.thisRow[columnIndex - 1] = inserter.getBytes(1);
- }
- }
- /**
- * 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 synchronized 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 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 synchronized void updateByte(int columnIndex, byte x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setByte(columnIndex, x);
- } else {
- inserter.setByte(columnIndex, x);
- this.thisRow[columnIndex - 1] = inserter.getBytes(columnIndex);
- }
- }
- /**
- * 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 synchronized void updateByte(String columnName, byte x)
- throws SQLException {
- updateByte(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 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 synchronized void updateBytes(int columnIndex, byte[] x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setBytes(columnIndex, x);
- } else {
- inserter.setBytes(columnIndex, x);
- this.thisRow[columnIndex - 1] = 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 synchronized void updateBytes(String columnName, byte[] x)
- throws SQLException {
- updateBytes(findColumn(columnName), x);
- }
- /**
- * 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 synchronized void updateCharacterStream(int columnIndex,
- java.io.Reader x, int length) throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setCharacterStream(columnIndex, x, length);
- } else {
- inserter.setCharacterStream(columnIndex, x, length);
- if (x == null) {
- this.thisRow[columnIndex - 1] = null;
- } else {
- this.thisRow[columnIndex - 1] = STREAM_DATA_MARKER;
- }
- }
- }
- /**
- * 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 reader the new column value
- * @param length of the stream
- *
- * @exception SQLException if a database-access error occurs
- */
- public synchronized void updateCharacterStream(String columnName,
- java.io.Reader reader, int length) throws SQLException {
- updateCharacterStream(findColumn(columnName), reader, length);
- }
- /**
- * @see ResultSet#updateClob(int, Clob)
- */
- public void updateClob(int columnIndex, java.sql.Clob clob) throws SQLException {
- if (clob == null) {
- updateNull(columnIndex);
- } else {
- updateCharacterStream(columnIndex, clob.getCharacterStream(), (int) clob.length());
- }
- }
- /**
- * 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 synchronized void updateDate(int columnIndex, java.sql.Date x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setDate(columnIndex, x);
- } else {
- inserter.setDate(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateDate(String columnName, java.sql.Date x)
- throws SQLException {
- updateDate(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 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 synchronized void updateDouble(int columnIndex, double x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setDouble(columnIndex, x);
- } else {
- inserter.setDouble(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateDouble(String columnName, double x)
- throws SQLException {
- updateDouble(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 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 synchronized void updateFloat(int columnIndex, float x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setFloat(columnIndex, x);
- } else {
- inserter.setFloat(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateFloat(String columnName, float x)
- throws SQLException {
- updateFloat(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 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 synchronized void updateInt(int columnIndex, int x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setInt(columnIndex, x);
- } else {
- inserter.setInt(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized 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 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 synchronized void updateLong(int columnIndex, long x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setLong(columnIndex, x);
- } else {
- inserter.setLong(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateLong(String columnName, long x)
- throws SQLException {
- updateLong(findColumn(columnName), x);
- }
- /**
- * 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 synchronized void updateNull(int columnIndex)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setNull(columnIndex, 0);
- } else {
- inserter.setNull(columnIndex, 0);
- this.thisRow[columnIndex - 1] = null;
- }
- }
- /**
- * 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 synchronized void updateNull(String columnName)
- throws SQLException {
- updateNull(findColumn(columnName));
- }
- /**
- * 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 synchronized void updateObject(int columnIndex, Object x, int scale)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setObject(columnIndex, x);
- } else {
- inserter.setObject(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateObject(int columnIndex, Object x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setObject(columnIndex, x);
- } else {
- inserter.setObject(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized 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 synchronized void updateObject(String columnName, Object x)
- throws SQLException {
- updateObject(findColumn(columnName), x);
- }
- /**
- * 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
- * @throws NotUpdatable DOCUMENT ME!
- */
- public synchronized void updateRow() throws SQLException {
- if (!isUpdatable) {
- throw new NotUpdatable();
- }
- if (doingUpdates) {
- updater.executeUpdate();
- refreshRow();
- doingUpdates = false;
- }
- //
- // fixes calling updateRow() and then doing more
- // updates on same row...
- syncUpdate();
- }
- /**
- * 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 synchronized void updateShort(int columnIndex, short x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setShort(columnIndex, x);
- } else {
- inserter.setShort(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateShort(String columnName, short x)
- throws SQLException {
- updateShort(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 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 synchronized void updateString(int columnIndex, String x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setString(columnIndex, x);
- } else {
- inserter.setString(columnIndex, x);
- if (x == null) {
- this.thisRow[columnIndex - 1] = null;
- } else {
- if (getCharConverter() != null) {
- try {
- this.thisRow[columnIndex - 1] = StringUtils.getBytes(x,
- this.charConverter, this.charEncoding);
- } catch (UnsupportedEncodingException uEE) {
- throw new SQLException(
- "Unsupported character encoding '"
- + this.charEncoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
- }
- } else {
- this.thisRow[columnIndex - 1] = x.getBytes();
- }
- }
- }
- }
- /**
- * 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 synchronized void updateString(String columnName, String x)
- throws SQLException {
- updateString(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 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 synchronized void updateTime(int columnIndex, java.sql.Time x)
- throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setTime(columnIndex, x);
- } else {
- inserter.setTime(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized 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 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 synchronized void updateTimestamp(int columnIndex,
- java.sql.Timestamp x) throws SQLException {
- if (!onInsertRow) {
- if (!doingUpdates) {
- doingUpdates = true;
- syncUpdate();
- }
- updater.setTimestamp(columnIndex, x);
- } else {
- inserter.setTimestamp(columnIndex, x);
- this.thisRow[columnIndex - 1] = this.inserter.getBytes(columnIndex
- - 1);
- }
- }
- /**
- * 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 synchronized void updateTimestamp(String columnName,
- java.sql.Timestamp x) throws SQLException {
- updateTimestamp(findColumn(columnName), x);
- }
- /**
- * Sets the concurrency type of this result set
- *
- * @param concurrencyFlag the type of concurrency that this ResultSet
- * should support.
- */
- protected void setResultSetConcurrency(int concurrencyFlag) {
- super.setResultSetConcurrency(concurrencyFlag);
- //
- // FIXME: Issue warning when asked for updateable result set, but result set is not
- // updatable
- //
- //if ((concurrencyFlag == CONCUR_UPDATABLE) && !isUpdatable()) {
- //java.sql.SQLWarning warning = new java.sql.SQLWarning(
- //NotUpdatable.NOT_UPDATEABLE_MESSAGE);
- //}
- }
- protected void checkRowPos() throws SQLException {
- // don't use RowData's idea of
- // row bounds when we're doing
- // inserts...
- if (!this.onInsertRow) {
- super.checkRowPos();
- }
- }
- /**
- * Figure out whether or not this ResultSet is updateable, and if so,
- * generate the PreparedStatements to support updates.
- *
- * @throws SQLException DOCUMENT ME!
- * @throws NotUpdatable DOCUMENT ME!
- */
- protected void generateStatements() throws SQLException {
- if (!isUpdatable) {
- this.doingUpdates = false;
- this.onInsertRow = false;
- throw new NotUpdatable();
- }
- String quotedId = getQuotedIdChar();
- this.tableName = null;
- if (fields[0].getOriginalTableName() != null) {
- StringBuffer tableNameBuffer = new StringBuffer();
- String databaseName = fields[0].getDatabaseName();
- if ((databaseName != null) && (databaseName.length() > 0)) {
- tableNameBuffer.append(quotedId);
- tableNameBuffer.append(databaseName);
- tableNameBuffer.append(quotedId);
- tableNameBuffer.append('.');
- }
- tableNameBuffer.append(quotedId);
- tableNameBuffer.append(fields[0].getOriginalTableName());
- tableNameBuffer.append(quotedId);
- this.tableName = tableNameBuffer.toString();
- } else {
- StringBuffer tableNameBuffer = new StringBuffer();
- tableNameBuffer.append(quotedId);
- tableNameBuffer.append(fields[0].getTableName());
- tableNameBuffer.append(quotedId);
- this.tableName = tableNameBuffer.toString();
- }
- primaryKeyIndicies = new ArrayList();
- StringBuffer fieldValues = new StringBuffer();
- StringBuffer keyValues = new StringBuffer();
- StringBuffer columnNames = new StringBuffer();
- StringBuffer insertPlaceHolders = new StringBuffer();
- boolean firstTime = true;
- boolean keysFirstTime = true;
- for (int i = 0; i < fields.length; i++) {
- String originalColumnName = fields[i].getOriginalName();
- String columnName = null;
- if (this.connection.getIO().hasLongColumnInfo()
- && (originalColumnName != null)
- && (originalColumnName.length() > 0)) {
- columnName = originalColumnName;
- } else {
- columnName = fields[i].getName();
- }
- if (fields[i].isPrimaryKey()) {
- primaryKeyIndicies.add(new Integer(i));
- if (!keysFirstTime) {
- keyValues.append(" AND ");
- } else {
- keysFirstTime = false;
- }
- keyValues.append(quotedId);
- keyValues.append(columnName);
- keyValues.append(quotedId);
- keyValues.append("=?");
- }
- if (firstTime) {
- firstTime = false;
- fieldValues.append("SET ");
- } else {
- fieldValues.append(",");
- columnNames.append(",");
- insertPlaceHolders.append(",");
- }
- insertPlaceHolders.append("?");
- columnNames.append(quotedId);
- columnNames.append(columnName);
- columnNames.append(quotedId);
- fieldValues.append(quotedId);
- fieldValues.append(columnName);
- fieldValues.append(quotedId);
- fieldValues.append("=?");
- }
- updateSQL = "UPDATE " + this.tableName + " " + fieldValues.toString()
- + " WHERE " + keyValues.toString();
- insertSQL = "INSERT INTO " + this.tableName + " ("
- + columnNames.toString() + ") VALUES ("
- + insertPlaceHolders.toString() + ")";
- refreshSQL = "SELECT " + columnNames.toString() + " FROM " + tableName
- + " WHERE " + keyValues.toString();
- deleteSQL = "DELETE FROM " + this.tableName + " WHERE "
- + keyValues.toString();
- }
- boolean isUpdatable() {
- return this.isUpdatable;
- }
- /**
- * Reset UPDATE prepared statement to value in current row. This_Row MUST
- * point to current, valid row.
- *
- * @throws SQLException DOCUMENT ME!
- */
- void syncUpdate() throws SQLException {
- if (updater == null) {
- if (updateSQL == null) {
- generateStatements();
- }
- updater = (com.mysql.jdbc.PreparedStatement) connection
- .prepareStatement(updateSQL);
- if (updater.getMaxRows() != 0) {
- updater.setMaxRows(0);
- }
- }
- int numFields = fields.length;
- updater.clearParameters();
- for (int i = 0; i < numFields; i++) {
- if (thisRow[i] != null) {
- updater.setBytes(i + 1, thisRow[i]);
- } else {
- updater.setNull(i + 1, 0);
- }
- }
- int numKeys = primaryKeyIndicies.size();
- if (numKeys == 1) {
- int index = ((Integer) primaryKeyIndicies.get(0)).intValue();
- byte[] keyData = thisRow[index];
- updater.setBytes(numFields + 1, keyData);
- } else {
- for (int i = 0; i < numKeys; i++) {
- byte[] currentVal = thisRow[((Integer) primaryKeyIndicies.get(i))
- .intValue()];
- if (currentVal != null) {
- updater.setBytes(numFields + i + 1, currentVal);
- } else {
- updater.setNull(numFields + i + 1, 0);
- }
- }
- }
- }
- private boolean initializedCharConverter = false;
- private synchronized SingleByteCharsetConverter getCharConverter()
- throws SQLException {
- if (!this.initializedCharConverter) {
- this.initializedCharConverter = true;
- if (this.connection.useUnicode()) {
- this.charEncoding = connection.getEncoding();
- this.charConverter = this.connection.getCharsetConverter(this.charEncoding);
- }
- }
- return this.charConverter;
- }
- private synchronized String getQuotedIdChar() throws SQLException {
- if (this.quotedIdChar == null) {
- boolean useQuotedIdentifiers = connection.supportsQuotedIdentifiers();
- if (useQuotedIdentifiers) {
- java.sql.DatabaseMetaData dbmd = connection.getMetaData();
- this.quotedIdChar = dbmd.getIdentifierQuoteString();
- } else {
- this.quotedIdChar = "";
- }
- }
- return this.quotedIdChar;
- }
- /**
- * DOCUMENT ME!
- *
- * @param field
- *
- * @return String
- */
- private String getTableName(Field field) {
- String originalTableName = field.getOriginalTableName();
- if ((originalTableName != null) && (originalTableName.length() > 0)) {
- return originalTableName;
- } else {
- return field.getTableName();
- }
- }
- /**
- * Is this ResultSet updateable?
- *
- * @return DOCUMENT ME!
- *
- * @throws SQLException DOCUMENT ME!
- */
- private boolean checkUpdatability() throws SQLException {
- String tableName = null;
- String catalogName = null;
- int primaryKeyCount = 0;
- if (fields.length > 0) {
- tableName = fields[0].getOriginalTableName();
- catalogName = fields[0].getDatabaseName();
- if (tableName == null) {
- tableName = fields[0].getTableName();
- catalogName = this.catalog;
- }
- if (fields[0].isPrimaryKey()) {
- primaryKeyCount++;
- }
- //
- // References only one table?
- //
- for (int i = 1; i < fields.length; i++) {
- String otherTableName = fields[i].getOriginalTableName();
- String otherCatalogName = fields[i].getDatabaseName();
- if (otherTableName == null) {
- otherTableName = fields[i].getTableName();
- otherCatalogName = this.catalog;
- }
- // Can't have more than one table
- if ((tableName == null)
- || !otherTableName.equals(tableName)) {
- return false;
- }
- // Can't reference more than one database
- if ((catalogName == null) || !otherCatalogName.equals(catalogName)) {
- return false;
- }
- if (fields[i].isPrimaryKey()) {
- primaryKeyCount++;
- }
- }
- if ((tableName == null) || (tableName.length() == 0)) {
- return false;
- }
- } else {
- return false;
- }
- //
- // Must have at least one primary key
- //
- if (primaryKeyCount == 0) {
- return false;
- }
- // We can only do this if we know that there is a currently
- // selected database, or if we're talking to a > 4.1 version
- // of MySQL server (as it returns database names in field
- // info)
- //
- if ((this.catalog == null) || (this.catalog.length() == 0)) {
- this.catalog = fields[0].getDatabaseName();
- if ((this.catalog == null) || (this.catalog.length() == 0)) {
- throw new SQLException(
- "Can not create updatable result sets when there is no currently selected database"
- + " and MySQL server version < 4.1", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
- }
- }
- if (this.connection.useStrictUpdates()) {
- java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();
- java.sql.ResultSet rs = null;
- HashMap primaryKeyNames = new HashMap();
- try {
- rs = dbmd.getPrimaryKeys(catalogName, null, tableName);
- while (rs.next()) {
- String keyName = rs.getString(4);
- keyName = keyName.toUpperCase();
- primaryKeyNames.put(keyName, keyName);
- }
- } finally {
- if (rs != null) {
- try {
- rs.close();
- } catch (Exception ex) {
- AssertionFailedException.shouldNotHappen(ex);
- }
- rs = null;
- }
- }
- if (primaryKeyNames.size() == 0) {
- return false; // we can't update tables w/o keys
- }
- //
- // Contains all primary keys?
- //
- for (int i = 0; i < fields.length; i++) {
- if (fields[i].isPrimaryKey()) {
- String columnNameUC = fields[i].getName().toUpperCase();
- if (primaryKeyNames.remove(columnNameUC) == null) {
- // try original name
- String originalName = fields[i].getOriginalName();
- if (originalName != null) {
- if (primaryKeyNames.remove(
- originalName.toUpperCase()) == null) {
- // we don't know about this key, so give up :(
- return false;
- }
- }
- }
- }
- }
- return primaryKeyNames.isEmpty();
- }
- return true;
- }
- private synchronized void extractDefaultValues() throws SQLException {
- java.sql.DatabaseMetaData dbmd = this.connection.getMetaData();
- java.sql.ResultSet columnsResultSet = null;
- try {
- String unquotedTableName = this.tableName;
- if (unquotedTableName.startsWith(this.quotedIdChar)) {
- unquotedTableName = unquotedTableName.substring(1);
- }
- if (unquotedTableName.endsWith(this.quotedIdChar)) {
- unquotedTableName = unquotedTableName.substring(0,
- unquotedTableName.length() - 1);
- }
- columnsResultSet = dbmd.getColumns(this.catalog, null,
- unquotedTableName, "%");
- HashMap columnNameToDefaultValueMap = new HashMap(this.fields.length /* at least this big... */);
- while (columnsResultSet.next()) {
- String columnName = columnsResultSet.getString("COLUMN_NAME");
- byte[] defaultValue = columnsResultSet.getBytes("COLUMN_DEF");
- columnNameToDefaultValueMap.put(columnName, defaultValue);
- }
- int numFields = this.fields.length;
- this.defaultColumnValue = new byte[numFields][];
- for (int i = 0; i < numFields; i++) {
- String tableName = this.fields[i].getOriginalName();
- if ((tableName == null) || (tableName.length() == 0)) {
- tableName = this.fields[i].getName();
- }
- if (tableName != null) {
- byte[] defaultVal = (byte[]) columnNameToDefaultValueMap
- .get(tableName);
- this.defaultColumnValue[i] = defaultVal;
- }
- }
- } finally {
- if (columnsResultSet != null) {
- columnsResultSet.close();
- columnsResultSet = null;
- }
- }
- }
- private void resetInserter() throws SQLException {
- inserter.clearParameters();
- for (int i = 0; i < fields.length; i++) {
- inserter.setNull(i + 1, 0);
- }
- }
- }