diff options
author | Bruce Momjian <bruce@momjian.us> | 2002-09-06 21:23:06 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 2002-09-06 21:23:06 +0000 |
commit | f37c1c486a383a3d266598463e13958359dbcce9 (patch) | |
tree | 6ad11ea2a33bae8b485c084434cbde9fc35f374f /src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java | |
parent | b4295d052e81a246bd7b15f6bc4ad37bd7ab4e86 (diff) | |
download | postgresql-f37c1c486a383a3d266598463e13958359dbcce9.tar.gz |
Run pgjindent for Java folks.
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java')
-rw-r--r-- | src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java | 2239 |
1 files changed, 1239 insertions, 1000 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java index 5d6816ad6c..cc468ff50a 100644 --- a/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java +++ b/src/interfaces/jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java @@ -15,1339 +15,1578 @@ import org.postgresql.util.PGbytea; import org.postgresql.util.PSQLException; -/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.6 2002/09/01 23:40:36 davec Exp $ +/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2ResultSet.java,v 1.7 2002/09/06 21:23:06 momjian Exp $ * This class defines methods of the jdbc2 specification. This class extends * org.postgresql.jdbc1.AbstractJdbc1ResultSet which provides the jdbc1 * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2ResultSet */ -public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet { +public abstract class AbstractJdbc2ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet +{ + + //needed for updateable result set support + protected boolean updateable = false; + protected boolean doingUpdates = false; + protected boolean onInsertRow = false; + protected Hashtable updateValues = new Hashtable(); + private boolean usingOID = false; // are we using the OID for the primary key? + private Vector primaryKeys; // list of primary keys + private int numKeys = 0; + private boolean singleTable = false; + protected String tableName = null; + protected PreparedStatement updateStatement = null; + protected PreparedStatement insertStatement = null; + protected PreparedStatement deleteStatement = null; + private PreparedStatement selectStatement = null; + + + + public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) + { + super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); + } + + public java.net.URL getURL(int columnIndex) throws SQLException + { + return null; + } + + + public java.net.URL getURL(String columnName) throws SQLException + { + return null; + } + + + /* + * Get the value of a column in the current row as a Java object + * + * <p>This method will return the value of the given column as a + * Java object. The type of the Java object will be the default + * Java Object type corresponding to the column's SQL type, following + * the mapping specified in the JDBC specification. + * + * <p>This method may also be used to read database specific abstract + * data types. + * + * @param columnIndex the first column is 1, the second is 2... + * @return a Object holding the column value + * @exception SQLException if a database access error occurs + */ + public Object getObject(int columnIndex) throws SQLException + { + Field field; + + checkResultSet( columnIndex ); + + wasNullFlag = (this_row[columnIndex - 1] == null); + if (wasNullFlag) + return null; + + field = fields[columnIndex - 1]; + + // some fields can be null, mainly from those returned by MetaData methods + if (field == null) + { + wasNullFlag = true; + return null; + } + + switch (field.getSQLType()) + { + case Types.BIT: + return getBoolean(columnIndex) ? Boolean.TRUE : Boolean.FALSE; + + case Types.SMALLINT: + return new Short(getShort(columnIndex)); + + case Types.INTEGER: + return new Integer(getInt(columnIndex)); + + case Types.BIGINT: + return new Long(getLong(columnIndex)); + + case Types.NUMERIC: + return getBigDecimal + (columnIndex, (field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff)); + + case Types.REAL: + return new Float(getFloat(columnIndex)); + + case Types.DOUBLE: + return new Double(getDouble(columnIndex)); + + case Types.CHAR: + case Types.VARCHAR: + return getString(columnIndex); + + case Types.DATE: + return getDate(columnIndex); + + case Types.TIME: + return getTime(columnIndex); + + case Types.TIMESTAMP: + return getTimestamp(columnIndex); + + case Types.BINARY: + case Types.VARBINARY: + return getBytes(columnIndex); + + case Types.ARRAY: + return getArray(columnIndex); + + default: + String type = field.getPGType(); + // if the backend doesn't know the type then coerce to String + if (type.equals("unknown")) + { + return getString(columnIndex); + } + else + { + return connection.getObject(field.getPGType(), getString(columnIndex)); + } + } + } + + + public boolean absolute(int index) throws SQLException + { + // index is 1-based, but internally we use 0-based indices + int internalIndex; + + if (index == 0) + throw new SQLException("Cannot move to index of 0"); + + final int rows_size = rows.size(); + + //if index<0, count from the end of the result set, but check + //to be sure that it is not beyond the first index + if (index < 0) + { + if (index >= -rows_size) + internalIndex = rows_size + index; + else + { + beforeFirst(); + return false; + } + } + else + { + //must be the case that index>0, + //find the correct place, assuming that + //the index is not too large + if (index <= rows_size) + internalIndex = index - 1; + else + { + afterLast(); + return false; + } + } + + current_row = internalIndex; + this_row = (byte[][]) rows.elementAt(internalIndex); + return true; + } + + + public void afterLast() throws SQLException + { + final int rows_size = rows.size(); + if (rows_size > 0) + current_row = rows_size; + } + + + public void beforeFirst() throws SQLException + { + if (rows.size() > 0) + current_row = -1; + } + + + public boolean first() throws SQLException + { + if (rows.size() <= 0) + return false; + + onInsertRow = false; + current_row = 0; + this_row = (byte[][]) rows.elementAt(current_row); + + rowBuffer = new byte[this_row.length][]; + System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); + + return true; + } + + + public java.sql.Array getArray(String colName) throws SQLException + { + return getArray(findColumn(colName)); + } + + + public java.sql.Array getArray(int i) throws SQLException + { + wasNullFlag = (this_row[i - 1] == null); + if (wasNullFlag) + return null; + + if (i < 1 || i > fields.length) + throw new PSQLException("postgresql.res.colrange"); + return (java.sql.Array) new org.postgresql.jdbc2.Array( connection, i, fields[i - 1], (java.sql.ResultSet) this ); + } + + + public java.math.BigDecimal getBigDecimal(int columnIndex) throws SQLException + { + return getBigDecimal(columnIndex, -1); + } + + + public java.math.BigDecimal getBigDecimal(String columnName) throws SQLException + { + return getBigDecimal(findColumn(columnName)); + } + + + public Blob getBlob(String columnName) throws SQLException + { + return getBlob(findColumn(columnName)); + } - //needed for updateable result set support - protected boolean updateable = false; - protected boolean doingUpdates = false; - protected boolean onInsertRow = false; - protected Hashtable updateValues = new Hashtable(); - private boolean usingOID = false; // are we using the OID for the primary key? - private Vector primaryKeys; // list of primary keys - private int numKeys = 0; - private boolean singleTable = false; - protected String tableName = null; - protected PreparedStatement updateStatement = null; - protected PreparedStatement insertStatement = null; - protected PreparedStatement deleteStatement = null; - private PreparedStatement selectStatement = null; - - - - public AbstractJdbc2ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { - super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); - } - - public java.net.URL getURL(int columnIndex) throws SQLException { - return null; - } - - - public java.net.URL getURL(String columnName) throws SQLException { - return null; - } - - - /* - * Get the value of a column in the current row as a Java object - * - * <p>This method will return the value of the given column as a - * Java object. The type of the Java object will be the default - * Java Object type corresponding to the column's SQL type, following - * the mapping specified in the JDBC specification. - * - * <p>This method may also be used to read database specific abstract - * data types. - * - * @param columnIndex the first column is 1, the second is 2... - * @return a Object holding the column value - * @exception SQLException if a database access error occurs - */ - public Object getObject(int columnIndex) throws SQLException { - Field field; - - checkResultSet( columnIndex ); - - wasNullFlag = (this_row[columnIndex - 1] == null); - if (wasNullFlag) - return null; - - field = fields[columnIndex - 1]; - - // some fields can be null, mainly from those returned by MetaData methods - if (field == null) { - wasNullFlag = true; - return null; - } - - switch (field.getSQLType()) { - case Types.BIT: - return getBoolean(columnIndex) ? Boolean.TRUE : Boolean.FALSE; - - case Types.SMALLINT: - return new Short(getShort(columnIndex)); - - case Types.INTEGER: - return new Integer(getInt(columnIndex)); - - case Types.BIGINT: - return new Long(getLong(columnIndex)); - - case Types.NUMERIC: - return getBigDecimal - (columnIndex, (field.getMod() == -1) ? -1 : ((field.getMod() - 4) & 0xffff)); - - case Types.REAL: - return new Float(getFloat(columnIndex)); - - case Types.DOUBLE: - return new Double(getDouble(columnIndex)); - - case Types.CHAR: - case Types.VARCHAR: - return getString(columnIndex); - - case Types.DATE: - return getDate(columnIndex); - - case Types.TIME: - return getTime(columnIndex); - - case Types.TIMESTAMP: - return getTimestamp(columnIndex); - - case Types.BINARY: - case Types.VARBINARY: - return getBytes(columnIndex); - - case Types.ARRAY: - return getArray(columnIndex); - default: - String type = field.getPGType(); - // if the backend doesn't know the type then coerce to String - if (type.equals("unknown")) { - return getString(columnIndex); - } - else { - return connection.getObject(field.getPGType(), getString(columnIndex)); - } - } - } + public abstract Blob getBlob(int i) throws SQLException; + + + public java.io.Reader getCharacterStream(String columnName) throws SQLException + { + return getCharacterStream(findColumn(columnName)); + } + + public java.io.Reader getCharacterStream(int i) throws SQLException + { + checkResultSet( i ); + wasNullFlag = (this_row[i - 1] == null); + if (wasNullFlag) + return null; - public boolean absolute(int index) throws SQLException { - // index is 1-based, but internally we use 0-based indices - int internalIndex; + if (((AbstractJdbc2Connection) connection).haveMinimumCompatibleVersion("7.2")) + { + //Version 7.2 supports AsciiStream for all the PG text types + //As the spec/javadoc for this method indicate this is to be used for + //large text values (i.e. LONGVARCHAR) PG doesn't have a separate + //long string datatype, but with toast the text datatype is capable of + //handling very large values. Thus the implementation ends up calling + //getString() since there is no current way to stream the value from the server + return new CharArrayReader(getString(i).toCharArray()); + } + else + { + // In 7.1 Handle as BLOBS so return the LargeObject input stream + Encoding encoding = connection.getEncoding(); + InputStream input = getBinaryStream(i); + return encoding.getDecodingReader(input); + } + } - if (index == 0) - throw new SQLException("Cannot move to index of 0"); - final int rows_size = rows.size(); + public Clob getClob(String columnName) throws SQLException + { + return getClob(findColumn(columnName)); + } - //if index<0, count from the end of the result set, but check - //to be sure that it is not beyond the first index - if (index < 0) { - if (index >= -rows_size) - internalIndex = rows_size + index; - else { - beforeFirst(); - return false; - } - } - else { - //must be the case that index>0, - //find the correct place, assuming that - //the index is not too large - if (index <= rows_size) - internalIndex = index - 1; - else { - afterLast(); - return false; - } - } - current_row = internalIndex; - this_row = (byte[][]) rows.elementAt(internalIndex); - return true; - } + public abstract Clob getClob(int i) throws SQLException; - public void afterLast() throws SQLException { - final int rows_size = rows.size(); - if (rows_size > 0) - current_row = rows_size; - } + public int getConcurrency() throws SQLException + { + if (statement == null) + return java.sql.ResultSet.CONCUR_READ_ONLY; + return statement.getResultSetConcurrency(); + } - public void beforeFirst() throws SQLException { - if (rows.size() > 0) - current_row = -1; - } + public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException + { + // If I read the specs, this should use cal only if we don't + // store the timezone, and if we do, then act just like getDate()? + // for now... + return getDate(i); + } - public boolean first() throws SQLException - { - if (rows.size() <= 0) - return false; + public Time getTime(int i, java.util.Calendar cal) throws SQLException + { + // If I read the specs, this should use cal only if we don't + // store the timezone, and if we do, then act just like getTime()? + // for now... + return getTime(i); + } - onInsertRow = false; - current_row = 0; - this_row = (byte[][]) rows.elementAt(current_row); - rowBuffer = new byte[this_row.length][]; - System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); + public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException + { + // If I read the specs, this should use cal only if we don't + // store the timezone, and if we do, then act just like getDate()? + // for now... + return getTimestamp(i); + } - return true; - } + public java.sql.Date getDate(String c, java.util.Calendar cal) throws SQLException + { + return getDate(findColumn(c), cal); + } - public java.sql.Array getArray(String colName) throws SQLException { - return getArray(findColumn(colName)); - } + public Time getTime(String c, java.util.Calendar cal) throws SQLException + { + return getTime(findColumn(c), cal); + } - public java.sql.Array getArray(int i) throws SQLException { - wasNullFlag = (this_row[i - 1] == null); - if (wasNullFlag) - return null; - if (i < 1 || i > fields.length) - throw new PSQLException("postgresql.res.colrange"); - return (java.sql.Array) new org.postgresql.jdbc2.Array( connection, i, fields[i - 1], (java.sql.ResultSet) this ); - } + public Timestamp getTimestamp(String c, java.util.Calendar cal) throws SQLException + { + return getTimestamp(findColumn(c), cal); + } - public java.math.BigDecimal getBigDecimal(int columnIndex) throws SQLException { - return getBigDecimal(columnIndex, -1); - } + public int getFetchDirection() throws SQLException + { + //PostgreSQL normally sends rows first->last + return java.sql.ResultSet.FETCH_FORWARD; + } - public java.math.BigDecimal getBigDecimal(String columnName) throws SQLException { - return getBigDecimal(findColumn(columnName)); - } + public int getFetchSize() throws SQLException + { + // In this implementation we return the entire result set, so + // here return the number of rows we have. Sub-classes can return a proper + // value + return rows.size(); + } - public Blob getBlob(String columnName) throws SQLException { - return getBlob(findColumn(columnName)); - } + public Object getObject(String columnName, java.util.Map map) throws SQLException + { + return getObject(findColumn(columnName), map); + } - public abstract Blob getBlob(int i) throws SQLException; + /* + * This checks against map for the type of column i, and if found returns + * an object based on that mapping. The class must implement the SQLData + * interface. + */ + public Object getObject(int i, java.util.Map map) throws SQLException + { + throw org.postgresql.Driver.notImplemented(); + } - public java.io.Reader getCharacterStream(String columnName) throws SQLException { - return getCharacterStream(findColumn(columnName)); - } + public Ref getRef(String columnName) throws SQLException + { + return getRef(findColumn(columnName)); + } - public java.io.Reader getCharacterStream(int i) throws SQLException { - checkResultSet( i ); - wasNullFlag = (this_row[i - 1] == null); - if (wasNullFlag) - return null; + public Ref getRef(int i) throws SQLException + { + //The backend doesn't yet have SQL3 REF types + throw new PSQLException("postgresql.psqlnotimp"); + } - if (((AbstractJdbc2Connection) connection).haveMinimumCompatibleVersion("7.2")) { - //Version 7.2 supports AsciiStream for all the PG text types - //As the spec/javadoc for this method indicate this is to be used for - //large text values (i.e. LONGVARCHAR) PG doesn't have a separate - //long string datatype, but with toast the text datatype is capable of - //handling very large values. Thus the implementation ends up calling - //getString() since there is no current way to stream the value from the server - return new CharArrayReader(getString(i).toCharArray()); - } - else { - // In 7.1 Handle as BLOBS so return the LargeObject input stream - Encoding encoding = connection.getEncoding(); - InputStream input = getBinaryStream(i); - return encoding.getDecodingReader(input); - } - } + public int getRow() throws SQLException + { + final int rows_size = rows.size(); - public Clob getClob(String columnName) throws SQLException { - return getClob(findColumn(columnName)); - } + if (current_row < 0 || current_row >= rows_size) + return 0; + return current_row + 1; + } - public abstract Clob getClob(int i) throws SQLException; + // This one needs some thought, as not all ResultSets come from a statement + public Statement getStatement() throws SQLException + { + return statement; + } - public int getConcurrency() throws SQLException { - if (statement == null) - return java.sql.ResultSet.CONCUR_READ_ONLY; - return statement.getResultSetConcurrency(); - } + public int getType() throws SQLException + { + // This implementation allows scrolling but is not able to + // see any changes. Sub-classes may overide this to return a more + // meaningful result. + return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE; + } - public java.sql.Date getDate(int i, java.util.Calendar cal) throws SQLException { - // If I read the specs, this should use cal only if we don't - // store the timezone, and if we do, then act just like getDate()? - // for now... - return getDate(i); - } + public boolean isAfterLast() throws SQLException + { + final int rows_size = rows.size(); + return (current_row >= rows_size && rows_size > 0); + } - public Time getTime(int i, java.util.Calendar cal) throws SQLException { - // If I read the specs, this should use cal only if we don't - // store the timezone, and if we do, then act just like getTime()? - // for now... - return getTime(i); - } + public boolean isBeforeFirst() throws SQLException + { + return (current_row < 0 && rows.size() > 0); + } - public Timestamp getTimestamp(int i, java.util.Calendar cal) throws SQLException { - // If I read the specs, this should use cal only if we don't - // store the timezone, and if we do, then act just like getDate()? - // for now... - return getTimestamp(i); - } + public boolean isFirst() throws SQLException + { + return (current_row == 0 && rows.size() >= 0); + } - public java.sql.Date getDate(String c, java.util.Calendar cal) throws SQLException { - return getDate(findColumn(c), cal); - } + public boolean isLast() throws SQLException + { + final int rows_size = rows.size(); + return (current_row == rows_size - 1 && rows_size > 0); + } - public Time getTime(String c, java.util.Calendar cal) throws SQLException { - return getTime(findColumn(c), cal); - } + public boolean last() throws SQLException + { + final int rows_size = rows.size(); + if (rows_size <= 0) + return false; - public Timestamp getTimestamp(String c, java.util.Calendar cal) throws SQLException { - return getTimestamp(findColumn(c), cal); - } + current_row = rows_size - 1; + this_row = (byte[][]) rows.elementAt(current_row); + rowBuffer = new byte[this_row.length][]; + System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); - public int getFetchDirection() throws SQLException { - //PostgreSQL normally sends rows first->last - return java.sql.ResultSet.FETCH_FORWARD; - } + return true; + } - public int getFetchSize() throws SQLException { - // In this implementation we return the entire result set, so - // here return the number of rows we have. Sub-classes can return a proper - // value - return rows.size(); - } + public boolean previous() throws SQLException + { + if (--current_row < 0) + return false; + this_row = (byte[][]) rows.elementAt(current_row); + System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); + return true; + } - public Object getObject(String columnName, java.util.Map map) throws SQLException { - return getObject(findColumn(columnName), map); - } + public boolean relative(int rows) throws SQLException + { + //have to add 1 since absolute expects a 1-based index + return absolute(current_row + 1 + rows); + } - /* - * This checks against map for the type of column i, and if found returns - * an object based on that mapping. The class must implement the SQLData - * interface. - */ - public Object getObject(int i, java.util.Map map) throws SQLException { - throw org.postgresql.Driver.notImplemented(); - } + public void setFetchDirection(int direction) throws SQLException + { + throw new PSQLException("postgresql.psqlnotimp"); + } - public Ref getRef(String columnName) throws SQLException { - return getRef(findColumn(columnName)); - } + public void setFetchSize(int rows) throws SQLException + { + // Sub-classes should implement this as part of their cursor support + throw org.postgresql.Driver.notImplemented(); + } - public Ref getRef(int i) throws SQLException { - //The backend doesn't yet have SQL3 REF types - throw new PSQLException("postgresql.psqlnotimp"); - } + public synchronized void cancelRowUpdates() + throws SQLException + { + if (doingUpdates) + { + doingUpdates = false; + clearRowBuffer(); + } + } - public int getRow() throws SQLException { - final int rows_size = rows.size(); - if (current_row < 0 || current_row >= rows_size) - return 0; + public synchronized void deleteRow() + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - return current_row + 1; - } + if (onInsertRow) + { + throw new PSQLException( "postgresql.updateable.oninsertrow" ); + } + if (rows.size() == 0) + { + throw new PSQLException( "postgresql.updateable.emptydelete" ); + } + if (isBeforeFirst()) + { + throw new PSQLException( "postgresql.updateable.beforestartdelete" ); + } + if (isAfterLast()) + { + throw new PSQLException( "postgresql.updateable.afterlastdelete" ); + } - // This one needs some thought, as not all ResultSets come from a statement - public Statement getStatement() throws SQLException { - return statement; - } + int numKeys = primaryKeys.size(); + if ( deleteStatement == null ) + { - public int getType() throws SQLException { - // This implementation allows scrolling but is not able to - // see any changes. Sub-classes may overide this to return a more - // meaningful result. - return java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE; - } + StringBuffer deleteSQL = new StringBuffer("DELETE FROM " ).append(tableName).append(" where " ); - public boolean isAfterLast() throws SQLException { - final int rows_size = rows.size(); - return (current_row >= rows_size && rows_size > 0); - } + for ( int i = 0; i < numKeys; i++ ) + { + deleteSQL.append( ((PrimaryKey) primaryKeys.get(i)).name ).append( " = ? " ); + if ( i < numKeys - 1 ) + { + deleteSQL.append( " and " ); + } + } + deleteStatement = ((java.sql.Connection) connection).prepareStatement(deleteSQL.toString()); + } + deleteStatement.clearParameters(); - public boolean isBeforeFirst() throws SQLException { - return (current_row < 0 && rows.size() > 0); - } + for ( int i = 0; i < numKeys; i++ ) + { + deleteStatement.setObject(i + 1, ((PrimaryKey) primaryKeys.get(i)).getValue()); + } - public boolean isFirst() throws SQLException { - return (current_row == 0 && rows.size() >= 0); - } + deleteStatement.executeUpdate(); + rows.removeElementAt(current_row); + } - public boolean isLast() throws SQLException { - final int rows_size = rows.size(); - return (current_row == rows_size - 1 && rows_size > 0); - } + public synchronized void insertRow() + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - public boolean last() throws SQLException { - final int rows_size = rows.size(); - if (rows_size <= 0) - return false; + if (!onInsertRow) + { + throw new PSQLException( "postgresql.updateable.notoninsertrow" ); + } + else + { - current_row = rows_size - 1; - this_row = (byte[][]) rows.elementAt(current_row); + // loop through the keys in the insertTable and create the sql statement + // we have to create the sql every time since the user could insert different + // columns each time - rowBuffer = new byte[this_row.length][]; - System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); + StringBuffer insertSQL = new StringBuffer("INSERT INTO ").append(tableName).append(" ("); + StringBuffer paramSQL = new StringBuffer(") values (" ); - return true; - } + Enumeration columnNames = updateValues.keys(); + int numColumns = updateValues.size(); + for ( int i = 0; columnNames.hasMoreElements(); i++ ) + { + String columnName = (String) columnNames.nextElement(); - public boolean previous() throws SQLException { - if (--current_row < 0) - return false; - this_row = (byte[][]) rows.elementAt(current_row); - System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); - return true; - } + insertSQL.append( columnName ); + if ( i < numColumns - 1 ) + { + insertSQL.append(", "); + paramSQL.append("?,"); + } + else + { + paramSQL.append("?)"); + } + } - public boolean relative(int rows) throws SQLException { - //have to add 1 since absolute expects a 1-based index - return absolute(current_row + 1 + rows); - } + insertSQL.append(paramSQL.toString()); + insertStatement = ((java.sql.Connection) connection).prepareStatement(insertSQL.toString()); + Enumeration keys = updateValues.keys(); - public void setFetchDirection(int direction) throws SQLException { - throw new PSQLException("postgresql.psqlnotimp"); - } + for ( int i = 1; keys.hasMoreElements(); i++) + { + String key = (String) keys.nextElement(); + insertStatement.setObject(i, updateValues.get( key ) ); + } + insertStatement.executeUpdate(); - public void setFetchSize(int rows) throws SQLException { - // Sub-classes should implement this as part of their cursor support - throw org.postgresql.Driver.notImplemented(); - } + if ( usingOID ) + { + // we have to get the last inserted OID and put it in the resultset + long insertedOID = ((AbstractJdbc2Statement) insertStatement).getLastOID(); - public synchronized void cancelRowUpdates() throws SQLException - { - if (doingUpdates) - { - doingUpdates = false; + updateValues.put("oid", new Long(insertedOID) ); - clearRowBuffer(); - } - } + } + // update the underlying row to the new inserted data + updateRowBuffer(); - public synchronized void deleteRow() throws SQLException - { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + rows.addElement(rowBuffer); - if (onInsertRow) { - throw new PSQLException( "postgresql.updateable.oninsertrow" ); - } + // we should now reflect the current data in this_row + // that way getXXX will get the newly inserted data + this_row = rowBuffer; - if (rows.size() == 0) { - throw new PSQLException( "postgresql.updateable.emptydelete" ); - } - if (isBeforeFirst()) { - throw new PSQLException( "postgresql.updateable.beforestartdelete" ); - } - if (isAfterLast()) { - throw new PSQLException( "postgresql.updateable.afterlastdelete" ); - } + // need to clear this in case of another insert + clearRowBuffer(); - int numKeys = primaryKeys.size(); - if ( deleteStatement == null ) { + } + } - StringBuffer deleteSQL = new StringBuffer("DELETE FROM " ).append(tableName).append(" where " ); + public synchronized void moveToCurrentRow() + throws SQLException + { + if (!updateable) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - for ( int i = 0; i < numKeys; i++ ) { - deleteSQL.append( ((PrimaryKey) primaryKeys.get(i)).name ).append( " = ? " ); - if ( i < numKeys - 1 ) { - deleteSQL.append( " and " ); - } - } + this_row = (byte[][]) rows.elementAt(current_row); - deleteStatement = ((java.sql.Connection) connection).prepareStatement(deleteSQL.toString()); - } - deleteStatement.clearParameters(); + rowBuffer = new byte[this_row.length][]; + System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); - for ( int i = 0; i < numKeys; i++ ) { - deleteStatement.setObject(i + 1, ((PrimaryKey) primaryKeys.get(i)).getValue()); - } + onInsertRow = false; + doingUpdates = false; + } - deleteStatement.executeUpdate(); + public synchronized void moveToInsertRow() + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - rows.removeElementAt(current_row); - } + if (insertStatement != null) + { + insertStatement = null; + } - public synchronized void insertRow() throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + // make sure the underlying data is null + clearRowBuffer(); - if (!onInsertRow) { - throw new PSQLException( "postgresql.updateable.notoninsertrow" ); - } - else { + onInsertRow = true; + doingUpdates = false; - // loop through the keys in the insertTable and create the sql statement - // we have to create the sql every time since the user could insert different - // columns each time + } - StringBuffer insertSQL = new StringBuffer("INSERT INTO ").append(tableName).append(" ("); - StringBuffer paramSQL = new StringBuffer(") values (" ); - Enumeration columnNames = updateValues.keys(); - int numColumns = updateValues.size(); + private synchronized void clearRowBuffer() + throws SQLException + { + // rowBuffer is the temporary storage for the row + rowBuffer = new byte[fields.length][]; - for ( int i = 0; columnNames.hasMoreElements(); i++ ) { - String columnName = (String) columnNames.nextElement(); + // clear the updateValues hashTable for the next set of updates + updateValues.clear(); - insertSQL.append( columnName ); - if ( i < numColumns - 1 ) { - insertSQL.append(", "); - paramSQL.append("?,"); - } - else { - paramSQL.append("?)"); - } + } - } - insertSQL.append(paramSQL.toString()); - insertStatement = ((java.sql.Connection) connection).prepareStatement(insertSQL.toString()); + public boolean rowDeleted() throws SQLException + { + // only sub-classes implement CONCURuPDATEABLE + throw Driver.notImplemented(); + } - Enumeration keys = updateValues.keys(); - for ( int i = 1; keys.hasMoreElements(); i++) { - String key = (String) keys.nextElement(); - insertStatement.setObject(i, updateValues.get( key ) ); - } + public boolean rowInserted() throws SQLException + { + // only sub-classes implement CONCURuPDATEABLE + throw Driver.notImplemented(); + } - insertStatement.executeUpdate(); - if ( usingOID ) { - // we have to get the last inserted OID and put it in the resultset + public boolean rowUpdated() throws SQLException + { + // only sub-classes implement CONCURuPDATEABLE + throw Driver.notImplemented(); + } - long insertedOID = ((AbstractJdbc2Statement) insertStatement).getLastOID(); - updateValues.put("oid", new Long(insertedOID) ); + public synchronized void updateAsciiStream(int columnIndex, + java.io.InputStream x, + int length + ) + throws SQLException + { - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - // update the underlying row to the new inserted data - updateRowBuffer(); + byte[] theData = null; - rows.addElement(rowBuffer); + try + { + x.read(theData, 0, length); + } + catch (NullPointerException ex ) + { + throw new PSQLException("postgresql.updateable.inputstream"); + } + catch (IOException ie) + { + throw new PSQLException("postgresql.updateable.ioerror" + ie); + } - // we should now reflect the current data in this_row - // that way getXXX will get the newly inserted data - this_row = rowBuffer; + doingUpdates = !onInsertRow; - // need to clear this in case of another insert - clearRowBuffer(); + updateValues.put( fields[columnIndex - 1].getName(), theData ); + } - } - } + public synchronized void updateBigDecimal(int columnIndex, + java.math.BigDecimal x ) + throws SQLException + { - public synchronized void moveToCurrentRow() throws SQLException { - if (!updateable) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - this_row = (byte[][]) rows.elementAt(current_row); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); - rowBuffer = new byte[this_row.length][]; - System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length); + } - onInsertRow = false; - doingUpdates = false; - } + public synchronized void updateBinaryStream(int columnIndex, + java.io.InputStream x, + int length + ) + throws SQLException + { - public synchronized void moveToInsertRow() throws SQLException - { - if ( !isUpdateable() ) - { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - if (insertStatement != null) - { - insertStatement = null; - } + byte[] theData = null; + try + { + x.read(theData, 0, length); - // make sure the underlying data is null - clearRowBuffer(); + } + catch ( NullPointerException ex ) + { + throw new PSQLException("postgresql.updateable.inputstream"); + } + catch (IOException ie) + { + throw new PSQLException("postgresql.updateable.ioerror" + ie); + } - onInsertRow = true; - doingUpdates = false; + doingUpdates = !onInsertRow; - } + updateValues.put( fields[columnIndex - 1].getName(), theData ); + } - private synchronized void clearRowBuffer() throws SQLException - { - // rowBuffer is the temporary storage for the row - rowBuffer = new byte[fields.length][]; - // clear the updateValues hashTable for the next set of updates - updateValues.clear(); + public synchronized void updateBoolean(int columnIndex, boolean x) + throws SQLException + { - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } + if ( Driver.logDebug ) + Driver.debug("updating boolean " + fields[columnIndex - 1].getName() + "=" + x); - public boolean rowDeleted() throws SQLException { - // only sub-classes implement CONCURuPDATEABLE - throw Driver.notImplemented(); - } + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), new Boolean(x) ); + } - public boolean rowInserted() throws SQLException { - // only sub-classes implement CONCURuPDATEABLE - throw Driver.notImplemented(); - } + public synchronized void updateByte(int columnIndex, byte x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - public boolean rowUpdated() throws SQLException { - // only sub-classes implement CONCURuPDATEABLE - throw Driver.notImplemented(); - } + doingUpdates = true; + updateValues.put( fields[columnIndex - 1].getName(), String.valueOf(x) ); + } - public synchronized void updateAsciiStream(int columnIndex, - java.io.InputStream x, - int length - ) throws SQLException { + public synchronized void updateBytes(int columnIndex, byte[] x) + throws SQLException + { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - byte[] theData = null; + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); - try { - x.read(theData, 0, length); - } - catch (NullPointerException ex ) { - throw new PSQLException("postgresql.updateable.inputstream"); - } - catch (IOException ie) { - throw new PSQLException("postgresql.updateable.ioerror" + ie); - } + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), theData ); + public synchronized void updateCharacterStream(int columnIndex, + java.io.Reader x, + int length + ) + throws SQLException + { - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } + char[] theData = null; - public synchronized void updateBigDecimal(int columnIndex, - java.math.BigDecimal x ) - throws SQLException { + try + { + x.read(theData, 0, length); - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + } + catch (NullPointerException ex) + { + throw new PSQLException("postgresql.updateable.inputstream"); + } + catch (IOException ie) + { + throw new PSQLException("postgresql.updateable.ioerror" + ie); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), theData); - } + } - public synchronized void updateBinaryStream(int columnIndex, - java.io.InputStream x, - int length - ) throws SQLException { + public synchronized void updateDate(int columnIndex, java.sql.Date x) + throws SQLException + { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - byte[] theData = null; + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); + } - try { - x.read(theData, 0, length); - } - catch ( NullPointerException ex ) { - throw new PSQLException("postgresql.updateable.inputstream"); - } - catch (IOException ie) { - throw new PSQLException("postgresql.updateable.ioerror" + ie); - } + public synchronized void updateDouble(int columnIndex, double x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - doingUpdates = !onInsertRow; + if ( Driver.logDebug ) + Driver.debug("updating double " + fields[columnIndex - 1].getName() + "=" + x); - updateValues.put( fields[columnIndex - 1].getName(), theData ); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), new Double(x) ); - } + } - public synchronized void updateBoolean(int columnIndex, boolean x) throws SQLException { + public synchronized void updateFloat(int columnIndex, float x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + if ( Driver.logDebug ) + Driver.debug("updating float " + fields[columnIndex - 1].getName() + "=" + x); - if ( Driver.logDebug ) Driver.debug("updating boolean " + fields[columnIndex - 1].getName() + "=" + x); + doingUpdates = !onInsertRow; - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), new Boolean(x) ); + updateValues.put( fields[columnIndex - 1].getName(), new Float(x) ); - } + } - public synchronized void updateByte(int columnIndex, byte x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + public synchronized void updateInt(int columnIndex, int x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - doingUpdates = true; - updateValues.put( fields[columnIndex - 1].getName(), String.valueOf(x) ); - } + if ( Driver.logDebug ) + Driver.debug("updating int " + fields[columnIndex - 1].getName() + "=" + x); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), new Integer(x) ); - public synchronized void updateBytes(int columnIndex, byte[] x) throws SQLException { + } - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); + public synchronized void updateLong(int columnIndex, long x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - } + if ( Driver.logDebug ) + Driver.debug("updating long " + fields[columnIndex - 1].getName() + "=" + x); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), new Long(x) ); - public synchronized void updateCharacterStream(int columnIndex, - java.io.Reader x, - int length - ) throws SQLException { + } - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } - char[] theData = null; + public synchronized void updateNull(int columnIndex) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - try { - x.read(theData, 0, length); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), null); - } - catch (NullPointerException ex) { - throw new PSQLException("postgresql.updateable.inputstream"); - } - catch (IOException ie) { - throw new PSQLException("postgresql.updateable.ioerror" + ie); - } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), theData); + } - } + public synchronized void updateObject(int columnIndex, Object x) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - public synchronized void updateDate(int columnIndex, java.sql.Date x) throws SQLException { + if ( Driver.logDebug ) + Driver.debug("updating object " + fields[columnIndex - 1].getName() + " = " + x); - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); - } + public synchronized void updateObject(int columnIndex, Object x, int scale) + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } - public synchronized void updateDouble(int columnIndex, double x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + this.updateObject(columnIndex, x); - if ( Driver.logDebug ) Driver.debug("updating double " + fields[columnIndex - 1].getName() + "=" + x); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), new Double(x) ); - } + public void refreshRow() throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } + try + { + StringBuffer selectSQL = new StringBuffer( "select "); - public synchronized void updateFloat(int columnIndex, float x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + final int numColumns = java.lang.reflect.Array.getLength(fields); - if ( Driver.logDebug ) Driver.debug("updating float " + fields[columnIndex - 1].getName() + "=" + x); + for (int i = 0; i < numColumns; i++ ) + { - doingUpdates = !onInsertRow; + selectSQL.append( fields[i].getName() ); - updateValues.put( fields[columnIndex - 1].getName(), new Float(x) ); + if ( i < numColumns - 1 ) + { - } + selectSQL.append(", "); + } + } + selectSQL.append(" from " ).append(tableName).append(" where "); - public synchronized void updateInt(int columnIndex, int x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + int numKeys = primaryKeys.size(); - if ( Driver.logDebug ) Driver.debug("updating int " + fields[columnIndex - 1].getName() + "=" + x); + for ( int i = 0; i < numKeys; i++ ) + { - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), new Integer(x) ); + PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i)); + selectSQL.append(primaryKey.name).append("= ?"); - } + if ( i < numKeys - 1 ) + { + selectSQL.append(" and "); + } + } + if ( Driver.logDebug ) + Driver.debug("selecting " + selectSQL.toString()); + selectStatement = ((java.sql.Connection) connection).prepareStatement(selectSQL.toString()); - public synchronized void updateLong(int columnIndex, long x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + for ( int j = 0, i = 1; j < numKeys; j++, i++) + { + selectStatement.setObject( i, ((PrimaryKey) primaryKeys.get(j)).getValue() ); + } - if ( Driver.logDebug ) Driver.debug("updating long " + fields[columnIndex - 1].getName() + "=" + x); + AbstractJdbc2ResultSet rs = (AbstractJdbc2ResultSet) selectStatement.executeQuery(); - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), new Long(x) ); + if ( rs.first() ) + { + rowBuffer = rs.rowBuffer; + } - } + rows.setElementAt( rowBuffer, current_row ); + if ( Driver.logDebug ) + Driver.debug("done updates"); + rs.close(); + selectStatement.close(); + selectStatement = null; - public synchronized void updateNull(int columnIndex) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + } + catch (Exception e) + { + if ( Driver.logDebug ) + Driver.debug(e.getClass().getName() + e); + throw new SQLException( e.getMessage() ); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), null); + } - } + public synchronized void updateRow() + throws SQLException + { + if ( !isUpdateable() ) + { + throw new PSQLException( "postgresql.updateable.notupdateable" ); + } + if (doingUpdates) + { - public synchronized void updateObject(int columnIndex, Object x) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + try + { - if ( Driver.logDebug ) Driver.debug("updating object " + fields[columnIndex - 1].getName() + " = " + x); + StringBuffer updateSQL = new StringBuffer("UPDATE " + tableName + " SET "); - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); - } + int numColumns = updateValues.size(); + Enumeration columns = updateValues.keys(); + for (int i = 0; columns.hasMoreElements(); i++ ) + { - public synchronized void updateObject(int columnIndex, Object x, int scale) throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + String column = (String) columns.nextElement(); + updateSQL.append( column + "= ?"); - this.updateObject(columnIndex, x); + if ( i < numColumns - 1 ) + { - } + updateSQL.append(", "); + } + } + updateSQL.append( " WHERE " ); - public void refreshRow() throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + int numKeys = primaryKeys.size(); - try { - StringBuffer selectSQL = new StringBuffer( "select "); + for ( int i = 0; i < numKeys; i++ ) + { - final int numColumns = java.lang.reflect.Array.getLength(fields); + PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i)); + updateSQL.append(primaryKey.name).append("= ?"); - for (int i = 0; i < numColumns; i++ ) { + if ( i < numKeys - 1 ) + { + updateSQL.append(" and "); + } + } + if ( Driver.logDebug ) + Driver.debug("updating " + updateSQL.toString()); + updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString()); - selectSQL.append( fields[i].getName() ); + int i = 0; + Iterator iterator = updateValues.values().iterator(); + for (; iterator.hasNext(); i++) + { + updateStatement.setObject( i + 1, iterator.next() ); - if ( i < numColumns - 1 ) { + } + for ( int j = 0; j < numKeys; j++, i++) + { + updateStatement.setObject( i + 1, ((PrimaryKey) primaryKeys.get(j)).getValue() ); + } - selectSQL.append(", "); - } + updateStatement.executeUpdate(); + updateStatement.close(); - } - selectSQL.append(" from " ).append(tableName).append(" where "); + updateStatement = null; + updateRowBuffer(); - int numKeys = primaryKeys.size(); - for ( int i = 0; i < numKeys; i++ ) { + if ( Driver.logDebug ) + Driver.debug("copying data"); + System.arraycopy(rowBuffer, 0, this_row, 0, rowBuffer.length); - PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i)); - selectSQL.append(primaryKey.name).append("= ?"); + rows.setElementAt( rowBuffer, current_row ); + if ( Driver.logDebug ) + Driver.debug("done updates"); - if ( i < numKeys - 1 ) { - selectSQL.append(" and "); - } - } - if ( Driver.logDebug ) Driver.debug("selecting " + selectSQL.toString()); - selectStatement = ((java.sql.Connection) connection).prepareStatement(selectSQL.toString()); + doingUpdates = false; + } + catch (Exception e) + { + if ( Driver.logDebug ) + Driver.debug(e.getClass().getName() + e); + throw new SQLException( e.getMessage() ); + } + } - for ( int j = 0, i = 1; j < numKeys; j++, i++) { - selectStatement.setObject( i, ((PrimaryKey) primaryKeys.get(j)).getValue() ); - } + } - AbstractJdbc2ResultSet rs = (AbstractJdbc2ResultSet) selectStatement.executeQuery(); - if ( rs.first() ) { - rowBuffer = rs.rowBuffer; - } + public synchronized void updateShort(int columnIndex, short x) + throws SQLException + { + if ( Driver.logDebug ) + Driver.debug("in update Short " + fields[columnIndex - 1].getName() + " = " + x); - rows.setElementAt( rowBuffer, current_row ); - if ( Driver.logDebug ) Driver.debug("done updates"); - rs.close(); - selectStatement.close(); - selectStatement = null; + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), new Short(x) ); - } - catch (Exception e) { - if ( Driver.logDebug ) Driver.debug(e.getClass().getName() + e); - throw new SQLException( e.getMessage() ); - } + } - } + public synchronized void updateString(int columnIndex, String x) + throws SQLException + { + if ( Driver.logDebug ) + Driver.debug("in update String " + fields[columnIndex - 1].getName() + " = " + x); - public synchronized void updateRow() throws SQLException { - if ( !isUpdateable() ) { - throw new PSQLException( "postgresql.updateable.notupdateable" ); - } + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); - if (doingUpdates) { + } - try { - StringBuffer updateSQL = new StringBuffer("UPDATE " + tableName + " SET "); + public synchronized void updateTime(int columnIndex, Time x) + throws SQLException + { + if ( Driver.logDebug ) + Driver.debug("in update Time " + fields[columnIndex - 1].getName() + " = " + x); - int numColumns = updateValues.size(); - Enumeration columns = updateValues.keys(); - for (int i = 0; columns.hasMoreElements(); i++ ) { + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); - String column = (String) columns.nextElement(); - updateSQL.append( column + "= ?"); + } - if ( i < numColumns - 1 ) { - updateSQL.append(", "); - } + public synchronized void updateTimestamp(int columnIndex, Timestamp x) + throws SQLException + { + if ( Driver.logDebug ) + Driver.debug("updating Timestamp " + fields[columnIndex - 1].getName() + " = " + x); - } - updateSQL.append( " WHERE " ); + doingUpdates = !onInsertRow; + updateValues.put( fields[columnIndex - 1].getName(), x ); - int numKeys = primaryKeys.size(); - for ( int i = 0; i < numKeys; i++ ) { + } - PrimaryKey primaryKey = ((PrimaryKey) primaryKeys.get(i)); - updateSQL.append(primaryKey.name).append("= ?"); - if ( i < numKeys - 1 ) { - updateSQL.append(" and "); - } - } - if ( Driver.logDebug ) Driver.debug("updating " + updateSQL.toString()); - updateStatement = ((java.sql.Connection) connection).prepareStatement(updateSQL.toString()); + public synchronized void updateNull(String columnName) + throws SQLException + { + updateNull(findColumn(columnName)); + } - int i = 0; - Iterator iterator = updateValues.values().iterator(); - for (; iterator.hasNext(); i++) { - updateStatement.setObject( i + 1, iterator.next() ); - } - for ( int j = 0; j < numKeys; j++, i++) { - updateStatement.setObject( i + 1, ((PrimaryKey) primaryKeys.get(j)).getValue() ); - } + public synchronized void updateBoolean(String columnName, boolean x) + throws SQLException + { + updateBoolean(findColumn(columnName), x); + } - updateStatement.executeUpdate(); - updateStatement.close(); - updateStatement = null; - updateRowBuffer(); + public synchronized void updateByte(String columnName, byte x) + throws SQLException + { + updateByte(findColumn(columnName), x); + } - if ( Driver.logDebug ) Driver.debug("copying data"); - System.arraycopy(rowBuffer, 0, this_row, 0, rowBuffer.length); + public synchronized void updateShort(String columnName, short x) + throws SQLException + { + updateShort(findColumn(columnName), x); + } - rows.setElementAt( rowBuffer, current_row ); - if ( Driver.logDebug ) Driver.debug("done updates"); - doingUpdates = false; - } - catch (Exception e) { - if ( Driver.logDebug ) Driver.debug(e.getClass().getName() + e); - throw new SQLException( e.getMessage() ); - } + public synchronized void updateInt(String columnName, int x) + throws SQLException + { + updateInt(findColumn(columnName), x); + } - } - } + public synchronized void updateLong(String columnName, long x) + throws SQLException + { + updateLong(findColumn(columnName), x); + } - public synchronized void updateShort(int columnIndex, short x) throws SQLException { - if ( Driver.logDebug ) Driver.debug("in update Short " + fields[columnIndex - 1].getName() + " = " + x); + public synchronized void updateFloat(String columnName, float x) + throws SQLException + { + updateFloat(findColumn(columnName), x); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), new Short(x) ); + public synchronized void updateDouble(String columnName, double x) + throws SQLException + { + updateDouble(findColumn(columnName), x); + } - } + public synchronized void updateBigDecimal(String columnName, BigDecimal x) + throws SQLException + { + updateBigDecimal(findColumn(columnName), x); + } - public synchronized void updateString(int columnIndex, String x) throws SQLException { - if ( Driver.logDebug ) Driver.debug("in update String " + fields[columnIndex - 1].getName() + " = " + x); - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); + public synchronized void updateString(String columnName, String x) + throws SQLException + { + updateString(findColumn(columnName), x); + } - } + public synchronized void updateBytes(String columnName, byte x[]) + throws SQLException + { + updateBytes(findColumn(columnName), x); + } - public synchronized void updateTime(int columnIndex, Time x) throws SQLException { - if ( Driver.logDebug ) Driver.debug("in update Time " + fields[columnIndex - 1].getName() + " = " + x); + public synchronized void updateDate(String columnName, java.sql.Date x) + throws SQLException + { + updateDate(findColumn(columnName), x); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); - } + public synchronized void updateTime(String columnName, java.sql.Time x) + throws SQLException + { + updateTime(findColumn(columnName), x); + } - public synchronized void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - if ( Driver.logDebug ) Driver.debug("updating Timestamp " + fields[columnIndex - 1].getName() + " = " + x); + public synchronized void updateTimestamp(String columnName, java.sql.Timestamp x) + throws SQLException + { + updateTimestamp(findColumn(columnName), x); + } - doingUpdates = !onInsertRow; - updateValues.put( fields[columnIndex - 1].getName(), x ); + public synchronized void updateAsciiStream( + String columnName, + java.io.InputStream x, + int length) + throws SQLException + { + updateAsciiStream(findColumn(columnName), x, length); + } - } + public synchronized void updateBinaryStream( + String columnName, + java.io.InputStream x, + int length) + throws SQLException + { + updateBinaryStream(findColumn(columnName), x, length); + } - public synchronized void updateNull(String columnName) throws SQLException { - updateNull(findColumn(columnName)); - } + public synchronized void updateCharacterStream( + String columnName, + java.io.Reader reader, + int length) + throws SQLException + { + updateCharacterStream(findColumn(columnName), reader, length); + } - public synchronized void updateBoolean(String columnName, boolean x) throws SQLException { - updateBoolean(findColumn(columnName), x); - } + public synchronized void updateObject(String columnName, Object x, int scale) + throws SQLException + { + updateObject(findColumn(columnName), x); + } - public synchronized void updateByte(String columnName, byte x) throws SQLException { - updateByte(findColumn(columnName), x); - } + public synchronized void updateObject(String columnName, Object x) + throws SQLException + { + updateObject(findColumn(columnName), x); + } - public synchronized void updateShort(String columnName, short x) throws SQLException { - updateShort(findColumn(columnName), x); - } + private int _findColumn( String columnName ) + { + int i; - public synchronized void updateInt(String columnName, int x) throws SQLException { - updateInt(findColumn(columnName), x); - } + final int flen = fields.length; + for (i = 0; i < flen; ++i) + { + if (fields[i].getName().equalsIgnoreCase(columnName)) + { + return (i + 1); + } + } + return -1; + } - public synchronized void updateLong(String columnName, long x) throws SQLException { - updateLong(findColumn(columnName), x); - } + /** + * Is this ResultSet updateable? + */ + boolean isUpdateable() throws SQLException + { - public synchronized void updateFloat(String columnName, float x) throws SQLException { - updateFloat(findColumn(columnName), x); - } + if (updateable) + return true; + if ( Driver.logDebug ) + Driver.debug("checking if rs is updateable"); - public synchronized void updateDouble(String columnName, double x) throws SQLException { - updateDouble(findColumn(columnName), x); - } + parseQuery(); + if ( singleTable == false ) + { + if ( Driver.logDebug ) + Driver.debug("not a single table"); + return false; + } - public synchronized void updateBigDecimal(String columnName, BigDecimal x) - throws SQLException { - updateBigDecimal(findColumn(columnName), x); - } + if ( Driver.logDebug ) + Driver.debug("getting primary keys"); + // + // Contains the primary key? + // - public synchronized void updateString(String columnName, String x) throws SQLException { - updateString(findColumn(columnName), x); - } + primaryKeys = new Vector(); + // this is not stricty jdbc spec, but it will make things much faster if used + // the user has to select oid, * from table and then we will just use oid - public synchronized void updateBytes(String columnName, byte x[]) throws SQLException { - updateBytes(findColumn(columnName), x); - } + usingOID = false; + int oidIndex = _findColumn( "oid" ); + int i = 0; - public synchronized void updateDate(String columnName, java.sql.Date x) - throws SQLException { - updateDate(findColumn(columnName), x); - } + // if we find the oid then just use it + + if ( oidIndex > 0 ) + { + i++; + primaryKeys.add( new PrimaryKey( oidIndex, "oid" ) ); + usingOID = true; + } + else + { + // otherwise go and get the primary keys and create a hashtable of keys + java.sql.ResultSet rs = ((java.sql.Connection) connection).getMetaData().getPrimaryKeys("", "", tableName); + + + for (; rs.next(); i++ ) + { + String columnName = rs.getString(4); // get the columnName + + int index = findColumn( columnName ); + + if ( index > 0 ) + { + primaryKeys.add( new PrimaryKey(index, columnName ) ); // get the primary key information + } + } + + rs.close(); + } + + numKeys = primaryKeys.size(); + + if ( Driver.logDebug ) + Driver.debug( "no of keys=" + i ); - public synchronized void updateTime(String columnName, java.sql.Time x) - throws SQLException { - updateTime(findColumn(columnName), x); - } - - - public synchronized void updateTimestamp(String columnName, java.sql.Timestamp x) - throws SQLException { - updateTimestamp(findColumn(columnName), x); - } - - - public synchronized void updateAsciiStream( - String columnName, - java.io.InputStream x, - int length) - throws SQLException { - updateAsciiStream(findColumn(columnName), x, length); - } - - - public synchronized void updateBinaryStream( - String columnName, - java.io.InputStream x, - int length) - throws SQLException { - updateBinaryStream(findColumn(columnName), x, length); - } - - - public synchronized void updateCharacterStream( - String columnName, - java.io.Reader reader, - int length) - throws SQLException { - updateCharacterStream(findColumn(columnName), reader, length); - } - - - public synchronized void updateObject(String columnName, Object x, int scale) - throws SQLException { - updateObject(findColumn(columnName), x); - } - - - public synchronized void updateObject(String columnName, Object x) throws SQLException { - updateObject(findColumn(columnName), x); - } - - - private int _findColumn( String columnName ) { - int i; - - final int flen = fields.length; - for (i = 0; i < flen; ++i) { - if (fields[i].getName().equalsIgnoreCase(columnName)) { - return (i + 1); - } - } - return -1; - } - - - /** - * Is this ResultSet updateable? - */ - - boolean isUpdateable() throws SQLException - { - - if (updateable) return true; - - if ( Driver.logDebug ) Driver.debug("checking if rs is updateable"); - - parseQuery(); - - if ( singleTable == false ) { - if ( Driver.logDebug ) Driver.debug("not a single table"); - return false; - } - - if ( Driver.logDebug ) Driver.debug("getting primary keys"); - - // - // Contains the primary key? - // - - primaryKeys = new Vector(); - - // this is not stricty jdbc spec, but it will make things much faster if used - // the user has to select oid, * from table and then we will just use oid - - - usingOID = false; - int oidIndex = _findColumn( "oid" ); - int i = 0; - - - // if we find the oid then just use it - - if ( oidIndex > 0 ) { - i++; - primaryKeys.add( new PrimaryKey( oidIndex, "oid" ) ); - usingOID = true; - } - else { - // otherwise go and get the primary keys and create a hashtable of keys - java.sql.ResultSet rs = ((java.sql.Connection) connection).getMetaData().getPrimaryKeys("", "", tableName); - - - for (; rs.next(); i++ ) { - String columnName = rs.getString(4); // get the columnName - - int index = findColumn( columnName ); - - if ( index > 0 ) { - primaryKeys.add( new PrimaryKey(index, columnName ) ); // get the primary key information - } - } - - rs.close(); - } - - numKeys = primaryKeys.size(); - - if ( Driver.logDebug ) Driver.debug( "no of keys=" + i ); - - if ( i < 1 ) { - throw new SQLException("No Primary Keys"); - } - - updateable = primaryKeys.size() > 0; - - if ( Driver.logDebug ) Driver.debug( "checking primary key " + updateable ); - - return updateable; - } - - - public void parseQuery() { - String[] l_sqlFragments = ((AbstractJdbc2Statement)statement).getSqlFragments(); - String l_sql = l_sqlFragments[0]; - StringTokenizer st = new StringTokenizer(l_sql, " \r\t"); - boolean tableFound = false, tablesChecked = false; - String name = ""; - - singleTable = true; - - while ( !tableFound && !tablesChecked && st.hasMoreTokens() ) { - name = st.nextToken(); - if ( !tableFound ) { - if (name.toLowerCase().equals("from")) { - tableName = st.nextToken(); - tableFound = true; - } - } - else { - tablesChecked = true; - // if the very next token is , then there are multiple tables - singleTable = !name.equalsIgnoreCase(","); - } - } - } - - - private void updateRowBuffer() throws SQLException { - - Enumeration columns = updateValues.keys(); - - while ( columns.hasMoreElements() ) { - String columnName = (String) columns.nextElement(); - int columnIndex = _findColumn( columnName ) - 1; - - switch ( connection.getSQLType( fields[columnIndex].getPGType() ) ) { - - case Types.DECIMAL: - case Types.BIGINT: - case Types.DOUBLE: - case Types.BIT: - case Types.VARCHAR: - case Types.DATE: - case Types.TIME: - case Types.TIMESTAMP: - case Types.SMALLINT: - case Types.FLOAT: - case Types.INTEGER: - case Types.CHAR: - case Types.NUMERIC: - case Types.REAL: - case Types.TINYINT: - - try { - rowBuffer[columnIndex] = String.valueOf( updateValues.get( columnName ) ).getBytes(connection.getEncoding().name() ); - } - catch ( UnsupportedEncodingException ex) { - throw new SQLException("Unsupported Encoding " + connection.getEncoding().name()); - } - - case Types.NULL: - continue; - - default: - rowBuffer[columnIndex] = (byte[]) updateValues.get( columnName ); - } - - } - } - - - public void setStatement(Statement statement) { - this.statement = statement; - } - - - private class PrimaryKey { - int index; // where in the result set is this primaryKey - String name; // what is the columnName of this primary Key - - PrimaryKey( int index, String name) { - this.index = index; - this.name = name; - } - Object getValue() throws SQLException { - return getObject(index); - } - }; + if ( i < 1 ) + { + throw new SQLException("No Primary Keys"); + } + + updateable = primaryKeys.size() > 0; + + if ( Driver.logDebug ) + Driver.debug( "checking primary key " + updateable ); + + return updateable; + } + + + public void parseQuery() + { + String[] l_sqlFragments = ((AbstractJdbc2Statement)statement).getSqlFragments(); + String l_sql = l_sqlFragments[0]; + StringTokenizer st = new StringTokenizer(l_sql, " \r\t"); + boolean tableFound = false, tablesChecked = false; + String name = ""; + + singleTable = true; + + while ( !tableFound && !tablesChecked && st.hasMoreTokens() ) + { + name = st.nextToken(); + if ( !tableFound ) + { + if (name.toLowerCase().equals("from")) + { + tableName = st.nextToken(); + tableFound = true; + } + } + else + { + tablesChecked = true; + // if the very next token is , then there are multiple tables + singleTable = !name.equalsIgnoreCase(","); + } + } + } + + + private void updateRowBuffer() throws SQLException + { + + Enumeration columns = updateValues.keys(); + + while ( columns.hasMoreElements() ) + { + String columnName = (String) columns.nextElement(); + int columnIndex = _findColumn( columnName ) - 1; + + switch ( connection.getSQLType( fields[columnIndex].getPGType() ) ) + { + + case Types.DECIMAL: + case Types.BIGINT: + case Types.DOUBLE: + case Types.BIT: + case Types.VARCHAR: + case Types.DATE: + case Types.TIME: + case Types.TIMESTAMP: + case Types.SMALLINT: + case Types.FLOAT: + case Types.INTEGER: + case Types.CHAR: + case Types.NUMERIC: + case Types.REAL: + case Types.TINYINT: + + try + { + rowBuffer[columnIndex] = String.valueOf( updateValues.get( columnName ) ).getBytes(connection.getEncoding().name() ); + } + catch ( UnsupportedEncodingException ex) + { + throw new SQLException("Unsupported Encoding " + connection.getEncoding().name()); + } + + case Types.NULL: + continue; + + default: + rowBuffer[columnIndex] = (byte[]) updateValues.get( columnName ); + } + + } + } + + + public void setStatement(Statement statement) + { + this.statement = statement; + } + + + private class PrimaryKey + { + int index; // where in the result set is this primaryKey + String name; // what is the columnName of this primary Key + + PrimaryKey( int index, String name) + { + this.index = index; + this.name = name; + } + Object getValue() throws SQLException + { + return getObject(index); + } + }; |